--- /dev/null
+
+ 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
--- /dev/null
+
+ 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.
--- /dev/null
+
+ 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.
--- /dev/null
+.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.
--- /dev/null
+%!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
--- /dev/null
+.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
--- /dev/null
+%!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
--- /dev/null
+.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.
--- /dev/null
+%!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
--- /dev/null
+
+ 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.
--- /dev/null
+.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.
--- /dev/null
+%!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
--- /dev/null
+.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.
--- /dev/null
+%!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
--- /dev/null
+%!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
--- /dev/null
+
+ 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.
--- /dev/null
+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)
--- /dev/null
+
+
+//**********************************************************************
+// 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
--- /dev/null
+%!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
--- /dev/null
+//!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
--- /dev/null
+%!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
--- /dev/null
+//!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
--- /dev/null
+%!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
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Adjusting Mup output
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="debug.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="invisbar.html">next page --></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 "dist" 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>
+ <A HREF="debug.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="invisbar.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Chord-at-a-time input style
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="tuplets.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="bars.html">next page --></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&
+ 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 > ] ce& 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 & 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>
+ <A HREF="tuplets.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="bars.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Bar Lines
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="altinp.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="multirst.html">next page --></A>
+</P>
+
+<H2>
+Bar lines
+</H2>
+<P>
+Each measure must be ended with a "bar" 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 "dashed" or "dotted" 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 "invisbar" 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 "D.C. al Coda";
+dblbar
+
+// The restart follows a bar
+// without any music data in between.
+restart
+
+rom above 1: 1 "Coda";
+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 "pad" 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 "_bar6" with bar line
+bar =_bar6
+
+// Do double bar with an extra stepsize of
+// padding, and associate tag "q"
+// 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 "ending," 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 "endending" is used. Examples:
+<BR><PRE>
+bar ending "1."
+repeatend ending "2-3"
+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 "</B><I>label</I><B>"</B>
+</P>
+<P>
+In the first example, a rehearsal letter will be placed on the bar. The
+first occurrence of this will become rehearsal "A", the next "B", 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 "rehearsal" can be
+abbreviated to "reh" 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 "num" with "mnum" 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 "1"
+1: 1e;
+repeatend pad 1 =_xyz reh let ending "2."
+1: 1g;
+bar rehearsal "Duet"
+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 "dist <I>N</I>" 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 "!" 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 "A1" 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="<I>X</I>" 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="A" 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 "hidechanges"
+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&
+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>
+ <A HREF="altinp.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="multirst.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+"Mup Basics"
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="intro.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="running.html">next page --></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, "a" to "g." As an example, the first measure of "Three Blind
+Mice" can be described like this:
+<BR><PRE>
+1: 4e; 4d; 2c;
+</PRE><BR>
+<IMG SRC="mugex2.gif" ALT="Picture of Mup output"><BR>
+The "1:" 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 "Three Blind Mice" 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 "bar." 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 "Three Blind
+Mice" 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 "music" context,
+while things that apply in general to the whole
+score are given in "score" 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.,
+"music" or "score").
+At the beginning of input, music context is assumed.
+</P>
+<P>
+Here is a more complicated example:
+<BR><PRE>
+score
+ staffs=2
+ key=3&
+ 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 "flat" symbol
+on a standard computer keyboard, Mup uses the "&" symbol for flat.
+The time signature is then set to 2/4.
+</P>
+<P>
+Next we find the keyword "music," 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 "pickup" measure, which doesn't add up to the
+time signature, you can specify "space" 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 "staff" context, and voice parameters
+are set in "voice" context.
+As an example:
+<BR><PRE>
+score
+ staffs=3
+ key=1&
+staff 2
+ key=2&
+ 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 "Three Blind Mice"
+</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; "Three blind mice,";
+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 "allegro") 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 "counts" into the measure. For example:
+<BR><PRE>
+boldital below 1: 3 "mf";
+</PRE><BR>
+<IMG SRC="mugex8.gif" ALT="Picture of Mup output"><BR>
+tells Mup to print "mf" 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 > 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>
+ <A HREF="intro.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="running.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Bracketing notes across staffs
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="manual.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="crossbar.html">next page --></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>
+ <A HREF="manual.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="crossbar.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Breath marks
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="slashmrk.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="heeltoe.html">next page --></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 ",";
+bar
+
+1: e;d;2c;
+bar
+</PRE><BR>
+<IMG SRC="mugex100.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+ <A HREF="slashmrk.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="heeltoe.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Cadenzas
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="multsong.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="trnspose.html">next page --></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>
+ <A HREF="multsong.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="trnspose.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Chant
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="invisbar.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="sharehd.html">next page --></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: "This<^ is an example of one way>";
+bar
+
+1: d;e;2f;
+lyrics 1: "to do chant.";
+bar
+
+1: 1f;
+lyrics 1: "when<^ there are many words for a>";
+bar
+
+1: d;f;2;
+lyrics 1: "sin-gle note.";
+dblbar
+
+newscore
+// Note use of 'n' to not print the time signature
+score time=7/4n
+music
+1: a;;;b;g;2a;
+lyrics 1: "When there are man-y notes,";
+bar
+
+score time=8/4n
+music
+1: d;e;f;e;f;8e;;2;
+lyrics 1: "You might change the time sig-na-ture";
+bar
+
+score time=5/4n
+music
+1: a;e;;2d;
+lyrics 1: "on ev-ery bar,";
+bar
+
+score time=7/4n
+music
+1: e;f;e;d;c;2d;
+lyrics 1: "to match the syl-la-bles.";
+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: "You can al-so use tup-lets,";
+invisbar
+
+1: {f;g;e;2d;e;2.d;}9n,1/2;
+lyrics 1: "A-long with in-vis-bars.";
+dblbar
+
+newscore
+
+score stemlen=0
+music
+
+1: d+;c+;b;g;2a;;
+lyrics 1: "Set stem-len to ze-ro,";
+invisbar
+
+1: {f;2e;4d;c;1d;}9n,1/2;
+lyrics 1: "to get stem-less notes.";
+endbar
+</PRE><BR>
+<IMG SRC="mugex89.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+ <A HREF="invisbar.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="sharehd.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Specifying chords
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="music.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="noteattr.html">next page --></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 "voice" 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 & 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 & 4 2 & 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 "top"
+voice, voice 2 the "bottom" voice, and voice 3 the "middle" or "extra" voice.
+With the first two voices, Mup tries hard to avoid any "collisions"
+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 "a" through "g".
+<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 "space," 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 "pickup" 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 "s" with a "u" 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 "rpt" (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 "m rpt" 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>&</TT></TD> <TD>flat</TD>
+</TR>
+<TR>
+<TD><TT>x</TT></TD> <TD>double sharp</TD>
+</TR>
+<TR>
+<TD><TT>&&</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&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>
+ <A HREF="music.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="noteattr.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Chord attributes
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="noteattr.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="midmeas.html">next page --></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 "diam," or "xnote."
+In the case of "diam," the chords will be drawn with diamond-shaped notes,
+while with "xnote," 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 "righttri"]cf; [hs "slash"]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 "with"
+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 "with" 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>></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., "ff", "adagio", 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 ^, "\(ferm)"]
+[with "sfz"; cue]
+</PRE><BR>
+</P>
+<P>
+If the symbols acc_hat, ferm, or wedge are used by themselves in a "with"
+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 "up" or "down".
+<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 "[down]" 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 "len" 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 "pad" 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 "=" followed by a name, but is inside
+the square brackets rather than after a note.
+<BR><PRE>
+3: 2cf; [=h] egc+;
+1: [cue; with >; =_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 "+" or "-" 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 "nook" 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 "dist" 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 "[]"
+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 "[-]" 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 "[len 5][down]" and "[len 5;down]" 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>
+ <A HREF="noteattr.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="midmeas.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup Options
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="running.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="utilpgms.html">next page --></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 "Set Options" form off
+of the "Run" 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: </CODE>
+<A NAME="coption"><B>-c</B> <I>N</I></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Run > Set Options > Enable Auto Multirest and Min Measures to Combine
+<BR> <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: </CODE>
+<B>-C</B>
+<BR>
+<CODE>Mupmate: </CODE>
+Option not available (only used for debugging).
+<BR> <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: </CODE>
+<A NAME="dbgoption"><B>-d</B> <I>N</I></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Option not available (only used for debugging).
+<BR> <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: </CODE>
+<A NAME="doption"><B>-D</B> <I>MACRO[=macro-def]</I></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Run > Set Options > Macro Definitions
+<BR> <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: </CODE>
+<B>-e</B> <I>errfile</I>
+<BR>
+<CODE>Mupmate: </CODE>
+Option not needed. Mupmate automatically saves and displays error output.
+<BR> <BR>
+
+Place the error message output into <I>errfile</I> instead of writing it to
+the standard error output stream.
+<HR>
+<CODE>Command line: </CODE>
+<A NAME="Eoption"><B>-E</B></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Option not needed (only used for debugging).
+<BR> <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: </CODE>
+<B>-f</B> <I>outfile</I>
+<BR>
+<CODE>Mupmate: </CODE>
+Option not needed. Mupmate automatically creates appropriate output file.
+<BR> <BR>
+
+Place the PostScript output into <I>outfile</I> instead of writing to
+the standard output.
+<HR>
+<CODE>Command line: </CODE>
+<A NAME="Foption"><B>-F</B></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Run > Write PostScript File
+<BR> <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 ".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.
+<HR>
+<CODE>Command line: </CODE>
+<A NAME="moption"><B>-m</B> <I>midifile</I></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Option not needed. Mupmate automatically creates appropriate output file.
+<BR> <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>
+"MIDI" to become defined.
+<HR>
+<CODE>Command line: </CODE>
+<B>-M</B>
+<BR>
+<CODE>Mupmate: </CODE>
+Run > Write MIDI File
+<BR> <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 ".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.
+<HR>
+<CODE>Command line: </CODE>
+<A NAME="ooption"><B>-o</B> <I>pagelist</I></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Run > Set Options > Pages to Display
+<BR> <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 "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.
+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: </CODE>
+<A NAME="poption"><B>-p</B> <I>N</I></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Run > Set Options > First Page's Page Number
+<BR> <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: </CODE>
+<B>-r</B>
+<BR>
+<CODE>Mupmate: </CODE>
+Config > Registration Form
+<BR> <BR>
+
+Print a copy of the
+<A HREF="register.html">Mup shareware registration form</A>
+to standard output.
+<HR>
+<CODE>Command line: </CODE>
+<A NAME="soption"><B>-s</B> <I>stafflist</I></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Run > Set Options > Staffs to Display/Play
+<BR> <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 "1,5" or "1-3,7-8"
+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 "1v2" or "1-4v1,5-6v2". 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 "1v2,1v3".
+<A HREF="param.html#visible">See also the "visible" parameter.</A>
+<HR>
+<CODE>Command line: </CODE>
+<B>-v</B>
+<BR>
+<CODE>Mupmate: </CODE>
+Help > About Mupmate
+<BR> <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: </CODE>
+<A NAME="xoption"><B>-x</B><I>M</I><B>,</B><I>N</I></A>
+<BR>
+<CODE>Mupmate: </CODE>
+Run > Set Options > Extract Measures
+<BR> <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 > character, as in:
+<BR><PRE>
+ mup infile.mup > 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 "bcfgnsu" 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
+<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>
+ <A HREF="running.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="utilpgms.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup Contexts
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="gensyn.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="music.html">next page --></A>
+</P>
+
+<H2>
+Contexts
+</H2>
+<P>
+There is always a current Mup "context" that is in effect.
+When Mup begins reading input, it is operating in "music" 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 "top."
+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 "bottom."
+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>
+ <A HREF="gensyn.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="music.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Crescendo and decrescendo marks
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="phrase.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="octave.html">next page --></A>
+</P>
+
+<H2>
+Crescendo and decrescendo marks
+</H2>
+<P>
+The "<" and ">" 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;
+< below 1: 1 til 2; 3 til 4.5;
+3: 2c;g;
+> between 2&3: 1.7 til 2m + 1;
+bar
+1-2: d;e;2g;
+3: 2d;a;
+< 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>
+ <A HREF="phrase.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="octave.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Cross-bar beaming
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="brackmac.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="mixtsig.html">next page --></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 "line" 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 "a"
+// location tag on the chord in the second actual measure,
+// and get the vertical endpoints from the "b" 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>
+ <A HREF="brackmac.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="mixtsig.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Cross-staff stems
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="midmeas.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="ichdattr.html">next page --></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 "with" before the notes that
+are to go on the other staff, and following those notes with "above" or "below"
+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 "other" 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>
+ <A HREF="midmeas.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="ichdattr.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup debugging
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="param.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="adjust.html">next page --></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 "typos." 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 "music" 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>
+ <A HREF="param.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="adjust.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup font files
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="include.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="param.html">next page --></A>
+</P>
+
+<H2>
+Installing other fonts
+</H2>
+<P>
+The "fontfile" 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 "file"
+</PRE><BR>
+in your Mup program, where the given "file" 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>
+ <A HREF="include.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="param.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup General Syntax
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="utilpgms.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="contexts.html">next page --></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 "magic string"
+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 "\" (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 "stepsizes." One stepsize is half the distance between two staff lines.
+In the horizontal dimension, "counts" are sometimes used. A "count"
+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 "count" 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,
+"SCORE" is not the same as "score."
+</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>
+"This is a string."
+"Allegro"
+</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>
+ <A HREF="utilpgms.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="contexts.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup header and footers
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="newscore.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="macros.html">next page --></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 "layers" 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 "outer" layer is specified by four contexts: header, footer, header2,
+and footer2. The "inner" 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 "2" 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 "Here is the Title"
+</PRE><BR>
+For this simple example, it would work just as well to use "header" instead
+of "top," 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) "Here is the Title"
+ title ital (14) "Here is a subtitle"
+ title "Lyrics: Ann Author" "Composer: Me"
+bottom
+ title "\(copyright) Copyright 2003 by Ann Author and Me"
+</PRE><BR>
+Again, in this simple example,
+you could use "header" and "footer" rather than "top" and "bottom."
+</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 "Here is the Title - \%"
+</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 "page \% of \#."
+</P>
+<P>
+As a variation, perhaps you'd prefer the information at the bottom of
+the page.
+<BR><PRE>
+bottom2
+ title "This is the title" "Page \%"
+</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 "My Favorite Songs," 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 "My Favorite Songs"
+header2
+ title "My Favorite Songs"
+footer2
+ title "\%"
+</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) "This is the Song Title"
+top2
+ title "This is the Song Title"
+</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 "title" 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 "nl" 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>
+ <A HREF="newscore.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="macros.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Organ pedal heel/toe marks
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="breathmk.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="muspaper.html">next page --></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 "\s(-3)\f(HB)U" @
+define TOE "\s(-1)\(acc_hat)" @
+
+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>
+ <A HREF="breathmk.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="muspaper.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Inter-chord attributes
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="crossst.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="tuplets.html">next page --></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 "tie"
+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 "tie" may be preceded by the word "dotted" or "dashed" to
+produce dotted or dashed ties, otherwise normal, solid ties are drawn.
+The word "tie" may be followed by the word "up" or "down" 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<d> a<b> c+<d+>; 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 "slur" keyword
+and the chord that follows it must have the same number of notes.
+The word "slur" may be preceded by the word "dotted" or "dashed" to
+produce dotted or dashed slurs, otherwise normal, solid slurs are drawn.
+The word "slur" may be followed by the word "up" or "down" 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 "bm" and "ebm" keywords. The "bm" (short for "beam")
+is placed at the end of the chord which is the first to be beamed.
+The "ebm" (short for "end beam") 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 "r" at the end of the
+beamstyle parameter, it will beam across rests
+of eighth note or shorter duration. Similarly, specifying an "s" 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 "esbm"
+("end subbeam" or "end secondary beam")
+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, "bm with staff below" must
+be specified, while on the second staff you use "bm with staff above".
+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 "bm" marks must occur at the same time in the
+measure. Similarly, the two "ebm" marks must
+occur at the same time in each staff.
+Grouping subbeams using "esbm" 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 "alt <I>N</I>" 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 "beam"-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>
+ <A HREF="crossst.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="tuplets.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Generalized conditionals
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="macros.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="include.html">next page --></A>
+</P>
+
+<H3>
+Generalized conditionals
+</H3>
+<P>
+Mup also supports more general "if" clauses. If you happen to be
+familiar with the preprocessors for the C and C++ programming
+languages, Mup "if" 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 "ifdef," the "else" and second set of Mup statements is optional.
+</P>
+<P>
+One form of "if" is really just a variation of ifdef. It uses the
+keyword "defined" 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 "not," 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 "if" 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) && defined(TRANSPOSE_UP) && ! defined(MIDI) then
+</PRE><BR>
+would be true only if both FULL_SCORE and TRANSPOSE_UP were defined,
+but MIDI was not defined. The && means "and."
+There is also || which means "or," 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 > 5 then
+ // ... this would not be executed, since 3 is not greater than 5
+ endif
+ if 2 <= 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 "equals" 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><</TD> <TD>less than</TD>
+</TR>
+<TR>
+<TD>></TD> <TD>greater than</TD>
+</TR>
+<TR>
+<TD><=</TD> <TD>less than or equal</TD>
+</TR>
+<TR>
+<TD>>=</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 "octal" and "hexadecimal" 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 "precedence"
+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 "not" 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 "not" would be
+applied. But what does "not -5" mean? The "not" 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 "true,"
+and "not true" would be "false," 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><< >></TT></TD> <TD>left shift, right shift</TD> <TD>left to right</TD>
+</TR>
+<TR>
+<TD><TT>< <= > >=</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>&</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>&&</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>
+ <A HREF="macros.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="include.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup include files
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="ifclause.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="fontfile.html">next page --></A>
+</P>
+
+<H2>
+Include
+</H2>
+<P>
+The "include" statement can be used to include the contents of one file
+inside another.
+<BR><PRE>
+<B>include "</B><I>filename</I><B>"</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 "boilerplate"
+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>
+ <A HREF="ifclause.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="fontfile.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<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>
+ <A HREF="intro.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Introduction to Mup
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="index.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="basics.html">next page --></A>
+</P>
+
+<H1>
+INTRODUCTION
+</H1>
+<P>
+The music publisher program called "Mup" 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>
+ <A HREF="index.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="basics.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Special uses of invisbar
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="adjust.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="chant.html">next page --></A>
+</P>
+
+<H2>
+Special uses of invisbar
+</H2>
+<P>
+The "invisbar" 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 "space"
+// 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 "courtesy"
+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&
+music
+1: g;f;e;d;
+repeatstart
+1: c;e;f;g;
+dblbar
+score key=0&
+music
+1: g;f;e;d;
+bar ending "1."
+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&
+music
+1: ms;
+repeatend ending "2."
+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>
+ <A HREF="adjust.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="chant.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Lines and curves
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="prnttext.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="newscore.html">next page --></A>
+</P>
+
+<H2>
+Lines and curves
+</H2>
+<P>
+The "line" 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 "wide," "medium," "wavy," "dotted," "dashed,"
+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>) "</B><I>string</I><B>"</B>
+</PRE><BR>
+at the end of the "line" statement. Only the keyword "with" 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) "gliss."
+bar
+</PRE><BR>
+<IMG SRC="mugex84.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+Arbitrary curves can be drawn using the "curve" 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 "curve" statement,
+at least three coordinates must be specified; more are permitted.
+The <I>linetype</I> can be "medium," "wide," "dashed,"
+or "dotted," 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 "bulge" 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>
+ <A HREF="prnttext.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="newscore.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Lyrics
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="multirst.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="tabstaff.html">next page --></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 "lyrics"
+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 "above" or "below," 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 "all," 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 "between <I>M</I><B>&</B><I>N</I>"
+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&2, 3&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&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: "2" for half notes, "8." 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 "below"
+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: "The sun will shine";
+// 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: "up-on the earth.";
+// 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 "below" 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: "for-ev-er";
+lyrics above 4-6: "nev-er-more";
+lyrics between 4&5,6&7: "this is it";
+lyrics below 4,2: "and so forth";
+</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; \
+ "This is some-thing else."; \
+ [4,5] "How do you like this?"; \
+ [2-3,6] "Now try this out too.";
+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] "verse one"; [2] "verse two";
+lyrics 1: 2s;4;; [c] "The refrain"; // 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] "Three blind mice";
+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<>;e;8g;b;4a;
+lyrics above 1: "now_ or nev-er";
+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 "empty syllable," consisting of "<>". 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<>;e;
+lyrics 1: "last word._";
+bar
+
+1: 4d;e;f;g;
+// add empty syllable to end the underscore
+lyrics 1: 1; "<>";
+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 "~" can be used in place of a space between the syllables.
+On output, Mup will replace the "~"
+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; "man-y~a day";
+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 "\(space)" 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] "this is verse one"; \
+ [2] "this is verse two";
+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 "space"
+by using an "s" after time values that have no
+lyric syllable associated with them. For example:
+<BR><PRE>
+1: 2r;g;
+lyrics 1: 2s;; [1] "Now";
+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 "Now"
+as its lyric. Note that the "s" does not work quite the same way with lyrics
+as it does with notes. With notes, "2s;;" 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, "2s;;" 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., "mf") with a particular verse, or
+marking a section for a subset of the singers (e.g., "Men:" or "Solo:").
+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 "^" immediately
+after the "<".
+</P>
+<P>
+Some examples:
+<BR><PRE>
+1: f;e;d;c;
+lyrics 1: "<1. >This is verse one.";
+bar
+1: 2g;4;;
+lyrics 1: 2s;4;; "<^\f(TX)ff\f(PV) >Loud-er";
+bar
+</PRE><BR>
+<IMG SRC="mugex49.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The < > 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 "strength" and would like
+to shift it leftward somewhat. Entering it as "<str>ength" would
+cause Mup to move the syllable farther to the left than it normally would.
+<BR><PRE>
+1: c;d;e;f;
+lyrics 1: "This strength not moved."; \
+ "This <str>ength was moved.";
+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: "All<^ these words will be treated like one syllable.>";
+</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 "all" is used for the staff number, the score parameters are used.
+In the case of "between," 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 "\f(TI)" 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 "middle" 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: "<1. >|\"How are you?\" -7|He asked her."; \
+ "<2. >|\"I am fine,\" -7|She re-plied.";
+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&2,3&4: 4;8;;4;s; "This is a test.";
+lyrics above 2: 2s;4;; "The end.";
+bar
+</PRE><BR>
+<IMG SRC="mugex52.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+ <A HREF="multirst.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="tabstaff.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup macros
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="headfoot.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="ifclause.html">next page --></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 "@" terminates the macro. A literal "@" 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 "undef"
+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
+"ifdef," "else," and "endif." The keyword "ifdef" 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 "else,"
+it will skip over input until the matching "endif."
+If the macro is not currently defined, Mup will skip over the input
+until it finds a matching "else" or "endif." There is also
+an "ifndef" command that uses the opposite logic: it will read the input
+up to the "else" or "endif" 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 "FRED" 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 "ff";
+boldital between 5&6: 1 "ff";
+</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&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,"ff")
+</PRE><BR>
+would give a VOLUME of "ff" at COUNT 1, whereas
+<BR><PRE>
+DYN(3.5,"mp")
+</PRE><BR>
+would give a VOLUME of "mp" 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&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 "hello" hello
+print QUOTED("hello") "hello" "\"hello\"" "hello"
+print QUOTED(\\n) \n "\n" a literal newline
+print QUOTED("\\n") "\n" "\"\\n\"" "\n"
+</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>
+ <A HREF="headfoot.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="ifclause.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Manually placed tuplet numbers
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="sharehd.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="manual.html">next page --></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) "\f(NX)\s(11)" +`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>
+ <A HREF="sharehd.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="manual.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Manual placement of notes
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="mantup.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="brackmac.html">next page --></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) "\(up2n)"
+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 "h" 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) "\(flat)"
+</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 "line"
+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>
+ <A HREF="mantup.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="brackmac.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup MIDI output
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="pstools.html"><-- previous page</A>
+
+ <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 "proofreading"
+(or perhaps we should say "proof-listening").
+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 "program" 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 "D.S. al coda" 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 "sign" and a "jump to coda" symbol could
+be put inside a macro definition, then the macro can be called. Then later
+in the piece, where the "D. S." 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 "sign";
+bar
+
+// define macro for section between sign and
+// symbol to "jump to coda"
+define SECTION
+1: g;a;g;;
+mussym above all: 5 "coda";
+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 "D. S. al Coda";
+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 "Coda";
+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 "swing time," 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 "knows" 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 "keyword=value";</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 "keyword=value";</I>
+</PRE><BR>
+is used instead.
+The items specified using "all" 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 "note off" commands are generated, then the "midi"
+command events, then "note on" 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 "chanpressure" which requires at least five letters to differentiate
+it from "channel" ("cha" or "chan" will be interpreted as channel).
+In most cases, the "=" is followed by either a number or some text. Exceptions
+to this are discussed in the next few paragraphs.
+</P>
+<P>
+The "parameter" 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 "parameter=7,90";
+</PRE><BR>
+</P>
+<P>
+The "onvelocity" and "offvelocity" 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 "onvelocity=76, 60";
+</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 "hex" 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 "tempo=72";
+midi 1-2 1-2: 0 "channel=2"; 0 "program=14"; 3.5 "program=76";
+midi all: 3 "hex= ff 00 02 00 01"; // sequence number 1
+midi 3,6: 0 "channel=5"; 0 "prog=15"; 0 "instr=dulcimer";
+// set parameter 7 (usually volume) to 100
+midi 2: "par = 7, 100";
+</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 "tempo=108"; 4 "tempo=96";
+
+// 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 "channel=1"; 0 "program=68"; //oboe
+midi 1 2: 0 "channel=2"; 0 "program=11"; //vibraphone
+midi 2 1: 0 "channel=6"; 0 "program=60"; //french horn
+midi 2 2: 0 "channel=4"; 0 "program=35"; //fretless bass
+
+// Make the top voice louder, and put an
+// accent on the third beat
+midi 1 1: 0 "onvelocity=86"; 3 "onvelocity=100"; 4 "onvel=86";
+
+// Set maximum reverb on french horn part,
+// starting at the second beat.
+// (Reverb is parameter 91)
+midi 2 1: 2 "parameter=91, 127";
+
+// Set chorus on oboe to 75, from the beginning.
+// (Chorus is parameter 93)
+midi 1 1: 0 "param=93, 75";
+
+// 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 "parameter=10, 32";
+
+// 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>
+ <A HREF="pstools.html"><-- previous page</A>
+ <A HREF="index.html">Table of Contents</A></P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mid-measure parameter changes
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="chrdattr.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="crossst.html">next page --></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; <<score clef=bass>> 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>
+<< staff clef = tenor ; defoct = 4 >>
+</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; <<score release=100>><<staff clef=alto>><<voice defoct=3>> c;
+</PRE><BR>
+</P>
+<P>
+If you specify "staff" or "voice" 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>
+ <A HREF="chrdattr.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="crossst.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mixed time signatures
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="crossbar.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="oddeven.html">next page --></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) "\f(newcentury bold)\s(16)3";
+print (t.w - 4, t.y - 4) "\f(newcentury bold)\s(16)4";
+
+// Then print the 6/8
+print (t.w - 4, s.y) "\f(newcentury bold)\s(16)6";
+print (t.w - 4, s.y - 4) "\f(newcentury bold)\s(16)8";
+bar
+</PRE><BR>
+<IMG SRC="mugex94.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+ <A HREF="crossbar.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="oddeven.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Multirests
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="bars.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="lyrics.html">next page --></A>
+</P>
+
+<H2>
+Multirest
+</H2>
+<P>
+Multiple measure rests can be indicated using the "multirest" 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>
+ <A HREF="bars.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="lyrics.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Placing several songs on one page
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="tempochg.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="cadenza.html">next page --></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 "hidechanges."
+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=""
+header
+ title (18) "Title for first song"
+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) " " // Allow some extra room above title
+title (18) "Title for second song"
+
+score
+ // Set up for second song
+ time=4/4
+ key=1&
+
+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>
+ <A HREF="tempochg.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="cadenza.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup music context
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="contexts.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="chordinp.html">next page --></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>
+ <A HREF="contexts.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="chordinp.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Generating blank staff paper
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="heeltoe.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="pstools.html">next page --></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="" // make sure left edges line up both on first
+ label2="" // 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>
+ <A HREF="heeltoe.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="pstools.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Music symbols
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="textmark.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="phrase.html">next page --></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 "mussym"
+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 "\(ferm)";
+mussym above 1: 1 "ferm";
+</PRE><BR>
+</P>
+<P>
+A duration is not allowed on mussym statements
+except in one special case--if the
+symbol is "tr" (trill). In that case, the duration tells Mup how long a
+wavy line to draw from the end of the "tr" symbol.
+<BR><PRE>
+1: 2e;g;
+mussym above 1: 1 "tr" til 2; 3 "ferm";
+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: "turn";
+</PRE><BR>
+</P>
+<HR><P>
+ <A HREF="textmark.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="phrase.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Newscore and newpage
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="linecurv.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="headfoot.html">next page --></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 "newscore" statement, or to the next page with a "newpage" 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 "leftmargin=<I>num</I>," 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 "rightmargin=<I>num</I>," 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>
+ <A HREF="linecurv.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="headfoot.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Note attributes
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="chordinp.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="chrdattr.html">next page --></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 "e" 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 "small" 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<e>; e; f; g;
+bar
+
+// slur from c+ of first chord to a& of second chord
+// and from c+ of first chord to d&+ of second chord
+1: 2cc+<ad+>; a&d&+;
+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; "<>" will suffice.
+<BR><PRE>
+// slur from c to d, and f to g
+1: c<>; d; f<>; g;
+bar
+</PRE><BR>
+<IMG SRC="mugex15.gif" ALT="Picture of Mup output"><BR>
+</P>
+<P>
+The < 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 > 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 "slurs" 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: </n> <\n> <n/> and <n\> 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</n><d>;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 "diam";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 "=" 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&
+3: 2c; e& =p g;
+
+// associate tag _end with note f
+2: 1f =_end;
+</PRE><BR>
+</P>
+<HR><P>
+ <A HREF="chordinp.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="chrdattr.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Octave marks
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="cres.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="pedal.html">next page --></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 "octave above" statement is
+used to specify playing higher than written, or "octave below" for playing
+lower than written. Each item must include a begintime
+and a text string. The text string is most typically "8va".
+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 "8va" til 1m + 1.3;
+bar
+1: 2a;c;
+2: 2f;e;
+3: 4f;;c;;
+octave below 2: 1 "8va";
+octave below 3: 1 "8va" til 2.5; 3 "15" til 4.5;
+bar
+</PRE><BR>
+<IMG SRC="mugex76.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+ <A HREF="cres.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="pedal.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Different margins for odd/even pages
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="mixtsig.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="tempochg.html">next page --></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>
+ <A HREF="mixtsig.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="tempochg.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup Parameters
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="fontfile.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="debug.html">next page --></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 "voice 5 2".
+If so, it will use that value. If not,
+it will see if the parameter was set in context "staff 5". 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& ; 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 "<" and ">" 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 & othertext & 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 "added" 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 "up" or "down," 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 "r" 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 "s" 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 "r"
+to indicate beams should span rests.
+It can optionally be followed by "s" 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 "<" and ">" 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 & othertext & 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 "<" and ">" 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 & othertext & chord, lyrics
+</P>
+<P><B>Context: </B>
+score, staff
+</P>
+<P><B>Example:</B><BR>
+betweenorder = mussym, lyrics, dyn & 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 "botmargin" 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 ("piano"), 3 ("cello")
+<BR>
+brace = 1-2 ("Primo", "I")
+<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 ("SATB")
+<BR>
+bracket = 10-12 ("Strings", "Str")
+<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 "drum"
+keyword, then the value of this clef parameter is
+only used for determining the placement of notes on the staff, with the
+drum (or "neutral") clef actually printed.
+Clef can be changed in
+<A HREF="midmeas.html">the middle of a measure</A>
+using a construct like <<staff clef=bass>> 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 <<staff defoct=5>> 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 "dyn."
+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 "top" 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 "barred"
+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 "grouped" 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 "fr" 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 "o",
+the "fr" 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 "y"
+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 "y" 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 (&), 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 "#" or "&," optionally followed by "major"
+or "minor." 0& and 0# are equivalent.
+If using the name of the key, the value is a letter "a" through "g,"
+optionally followed by a "#" or "&," optionally followed by "major" or "minor."
+The "major" and "minor" can be abbreviated to "maj" or "min."
+The "major" or "minor" 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&
+<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="Tenor/Bass" and label2="TB"
+</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 = "oboe"
+</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 = "Solo"
+</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 "y,"
+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 "n," 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., "norm" 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 "tonic"
+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 "shapename"]
+before the chord. It can also be
+<A HREF="shaped.html#note">overridden on an individual note</A>
+by putting hs "shapename" after the note.
+</P>
+<P><B>Value: </B>
+A string containing either 1 or 7 head shape names.
+</P>
+<P><B>Default value: </B>
+"norm"
+</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 = "righttri norm rect righttri norm rect diam"
+<BR>
+
+// This is the setting for a shaped notes system that uses 7 different shapes.
+<BR>
+noteheads = "isostri semicirc diam righttri norm rect pie"
+</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 "deserve" 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 "Ped" and "*".
+With the "pedstar" style, a "bounce" of the pedal is shown by a "* Ped"
+whereas with the "alt pedstar" style, only a "Ped" 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 <<score release=50>> 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 "n" 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 "n" 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 "n," so the "n" 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 "n" you can specify "drum" which
+means to use the drum clef (also sometimes called the "neutral" 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 "tab" 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 &. If there is more than
+one string having the same letter/accidental, they are distinguished by
+adding one or more single quote marks ("ticks"). 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 "tabnote"
+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 "n" or "drum";
+or for tablature staff, the keyword "tab" 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 "swing time," 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 "knows" 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 "swingunit," 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 "middle" 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 "cut" or "common." 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 "alternating"
+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 "up" or "down," 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 "added" 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 "nooverlap,"
+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 "shareone" 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 "overlap," 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 "opposing" 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 "free" or "floating" 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 "space" 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 "top"
+voice, voice 2 the "bottom" voice, and voice 3 the "middle" or "extra" 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>
+ <A HREF="fontfile.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="debug.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Piano pedal marks
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="octave.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="roll.html">next page --></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 "*". 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 "blip"--lifting and then immediately depressing the pedal
+(which is indicated on the printed music by a "^"), unless there is a "*",
+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>
+ <A HREF="octave.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="roll.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Phrase marks
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="mussym.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="cres.html">next page --></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, "above"
+indicates to Mup that the phrase is associated with voice 1,
+and "below" 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 "grace back up" 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 "nest" 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<>;a4;e4<>;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 "phrase" 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>
+ <A HREF="mussym.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="cres.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Automatic piano reduction
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="verses.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="slashmrk.html">next page --></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 & 5 1: @ // soprano
+define A 2 1 & 5 2: @ // alto
+define T 3 1 & 6 1: @ // tenor
+define B 4 1 & 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 & 6 2; \
+ 3 1 & 6 1; \
+ 2 1 & 5 2; \
+ 1 1 & 5 1 ] : @
+
+music
+
+M 2cafc+;cgec+;
+bar
+</PRE><BR>
+</P>
+<HR><P>
+ <A HREF="verses.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="slashmrk.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+"Mup commands for printing text
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="tags.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="linecurv.html">next page --></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> "<I>text</I>"
+<B>left</B> <I>location</I> "<I>text</I>"
+<B>right</B> <I>location</I> "<I>text</I>"
+<B>center</B> <I>location</I> "<I>text</I>"
+</PRE><BR>
+</P>
+<P>
+The <I>location</I> is optional. If the <I>location</I> is omitted, the "print"
+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 "nl"
+which means "next line." 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 "right" command containing a reference
+to an absolute location:
+<BR><PRE>
+right (25, 4) "something"
+</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 "something" will be placed such that the right edge of the final "g"
+will be 25 stepsizes from the left edge of the page. If "center" had been
+specified, the middle of the word "something" would be at the 25 stepsize point.
+</P>
+<P>
+Here are some other examples:
+<BR><PRE>
+print "Author unknown"
+center nl "subtitle"
+left (h.x - 1.5, h.n + 2.3) "Ad lib"
+right (_fine.e + time 3, _note.n + 5) "Duet"
+</PRE><BR>
+</P>
+<P>
+Another type of print command
+is "title." The full format of this command is:
+<BR><PRE>
+<B>title</B> <I>fontfamily font size "text1" "text2" "text3"</I>
+</PRE><BR>
+However, only the word "title" 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 "fontfamily"
+parameter.
+The <I>font</I>, if specified, has one of the values valid for the "font"
+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 "nl"
+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) "Sonata 12"
+title (18) "Song Without Words"
+title ital (12) "Text: John Doe" "Tune: Jane Doe"
+title "Suite in C" "Trumpet I" "Waltz"
+title "" "A. Composer"
+</PRE><BR>
+</P>
+<P>
+<A NAME="paragrph">The final command for printing text is</A>
+the "paragraph" 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 "justified" or "ragged."
+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>) "</B><I>string</I><B>"</B>
+<BR>
+Only the keyword "paragraph" and the string are required.
+Here are some example paragraphs:
+<BR><PRE>
+paragraph "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"
+
+ragged paragraph avantgarde ital (15) "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."
+
+justified paragraph (14) " 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."
+
+paragraph "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."
+</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 "block" context. The block context
+will typically contain one or more "paragraph" 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 "newscore" 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 "newpage" will cause a new page to be started.
+If a newscore or newpage includes a "leftmargin" specification,
+that will alter the left margin on the block text that follows.
+A "rightmargin" 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 "Notation in Simple and Compound Meters"
+title ""
+paragraph "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:"
+score time=3/4
+music
+1: c;;;
+bar
+block
+paragraph "whereas in 6/8 time
+(which is compound duple meter),
+a measure with 3 quarter notes should be notated thus:"
+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>"</B><I>raw PostScript</I><B>"</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 \" 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 "50 50 translate (file.eps) run"
+</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) "
+ 1 0 0 setrgbcolor
+ /NewCenturySchlbk-Italic findfont
+ 16 scalefont setfont
+ (Photocopying prohibited) show
+ "
+</PRE><BR>
+</P>
+<HR><P>
+ <A HREF="tags.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="linecurv.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Converting Mup files to other formats
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="muspaper.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="midi.html">next page --></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 "ps2pdf" tool that comes with Ghostscript can
+convert Mup output to PDF format, and the "ps2epsi" 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 "psutils" available on most Linux archives,
+that contains various Postscript tools. These include "psnup" 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 "psselect" 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>
+ <A HREF="muspaper.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="midi.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<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>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Rolls
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="pedal.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="tags.html">next page --></A>
+</P>
+
+<H2>
+Rolls
+</H2>
+<P>
+Rolls can be specified with the "roll" 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 "to"
+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 "down" can be placed
+after "roll." 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 "up" 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>
+ <A HREF="pedal.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="tags.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Running Mup
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="basics.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="cmdargs.html">next page --></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 "Mupmate" 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 "copy",
+right clicking somewhere on the desktop, and choosing "paste".
+</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 "Display"
+from the Run menu and use the viewer's print capabilities.
+Alternately you can use "Write PostScript File" from the Run menu
+to create a PostScript file that you can print as you would any other
+PostScript file.
+</P>
+<HR><P>
+ <A HREF="basics.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="cmdargs.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Shaped notes
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="tabstaff.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="textstr.html">next page --></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 "shaped note" music that is often used
+for "Sacred Harp" style music, sometimes also called "fasola notation,"
+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 "u?" (The "u" stands for "upside-down" 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>"norm"</TD> <TD>"4n 2n 1n dblwhole"</TD>
+</TR>
+<TR>
+<TD>"x"</TD> <TD>"xnote diamond diamond dwhdiamond"</TD>
+</TR>
+<TR>
+<TD>"allx"</TD> <TD>"xnote xnote xnote xnote"</TD>
+</TR>
+<TR>
+<TD>"diam"</TD> <TD>"filldiamond diamond diamond dwhdiamond"</TD>
+</TR>
+<TR>
+<TD>"blank"</TD> <TD>"blankhead blankhead blankhead blankhead"</TD>
+</TR>
+<TR>
+<TD>"righttri"</TD> <TD>"u?fillrighttriangle u?righttriangle u?righttriangle u?dwhrighttriangle"</TD>
+</TR>
+<TR>
+<TD>"isostri"</TD> <TD>"fillisostriangle isostriangle isostriangle dwhisostriangle"</TD>
+</TR>
+<TR>
+<TD>"rect"</TD> <TD>"fillrectangle rectangle rectangle dwhrectangle"</TD>
+</TR>
+<TR>
+<TD>"pie"</TD> <TD>"fillpiewedge piewedge piewedge dwhpiewedge"</TD>
+</TR>
+<TR>
+<TD>"semicirc"</TD> <TD>"fillsemicircle semicircle semicircle dwhsemicircle"</TD>
+</TR>
+<TR>
+<TD>"slash"</TD> <TD>"fillslashhead slashhead slashhead dwhslashhead"</TD>
+</TR>
+<TR>
+<TD>"allslash"</TD> <TD>"fillslashhead fillslashhead fillslashhead fillslashhead"</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 "x" or "allx"
+but you could override one of them:
+<BR><PRE>
+headshapes
+ "x" "xnote xnote diamond diamond"
+</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 = "norm"
+</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 "tonic" 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 = "righttri norm rect righttri norm rect diam"
+</PRE><BR>
+There are several shaped notes systems using 7 different shapes.
+One such system is specified by:
+<BR><PRE>
+noteheads = "isostri semicirc diam righttri norm rect pie"
+</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 = "isostri semicirc diam righttri norm rect pie"
+
+ // 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 "tonic"
+ // 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 "hs" followed by a head shape name from the headshapes context,
+inside square brackets.
+Thus
+<BR><PRE>
+ [hs "righttri"]
+</PRE><BR>
+would use the "righttri" 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 "fillrighttriangle" note head would be used,
+but if the chord was a half or whole note, a "righttriangle" note head would be
+used, and a "dwhrighttriangle" 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 "blank"; 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 "diam"; f a hs "x" 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 "allx."
+which is used for "muffled" notes.
+</P>
+<P>
+Here is a simple example of shaped notes, using the common 4-shape system.
+<BR><PRE>
+score
+ noteheads = "righttri norm rect righttri norm rect diam"
+ 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="isostri"
+music
+1: 4ec+;8;;2;1;
+bar
+
+score noteheads="rect"
+music
+1: 1gc+;4;2;8;;
+bar
+
+score noteheads="pie"
+music
+1: 8cf;;4;2;1;
+bar
+
+score noteheads="x"
+music
+1: 4ec+;8;;2;1;
+bar
+
+score noteheads="slash"
+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.
+ "reg" "4n 2n 2n 2n"
+ "other" "fillrectangle diamond isostriangle dblwhole"
+
+score
+ // Set notesheads, using an arbitrary mixture of builtin
+ // and user-defined head shapes.
+ noteheads="norm reg other reg reg other righttri"
+
+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 "pie" ]2ce; [hs "isostri"] c e g hs "righttri";
+endbar
+</PRE><BR>
+<IMG SRC="mugex64.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+ <A HREF="tabstaff.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="textstr.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Forcing shared noteheads
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="chant.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="mantup.html">next page --></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>
+ <A HREF="chant.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="mantup.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Diagonal slash marks
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="pianored.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="breathmk.html">next page --></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 = "allslash"
+</PRE><BR>
+or if you want to use hollow slashes for half notes and longer
+<BR><PRE>
+noteheads = "slash"
+</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 "allslash"; len 0 ]... ;;;
+bar
+</PRE><BR>
+<IMG SRC="mugex99.gif" ALT="Picture of Mup output"><BR>
+</P>
+<HR><P>
+ <A HREF="pianored.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="breathmk.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+"Tempo, dynamic marks, ornaments, etc."
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="textstr.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="textmark.html">next page --></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
+< crescendo "hairpin"
+> decrescendo "hairpin"
+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
+< yes yes yes above
+> 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 "between",
+staff numbers must be in pairs, separated by an "&", with the second
+staff number one greater than the first.
+</P>
+<P>
+The <I>staff</I> can also be specified by the keyword "all," 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:
+< between 3&4:
+pedal below 2:
+octave above 3:
+phrase 3,4:
+mussym above 2-3, 5:
+ital between 1&2, 3&4:
+</PRE><BR>
+</P>
+<P>
+<A NAME="dist">The</A>
+<I>distance</I> is optional. It is specified by the keyword "dist" 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 "normal dist";
+rom above 1 dist 4: 2 "dist 4"; // higher than usual
+rom above 1 dist 0! : 3 "forced 0"; // lower than normal
+mussym above 1 dist -2! : 4.5 "rr"; // 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 "beat"
+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 "beat" 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 "back up" 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] "Allegro";
+</PRE><BR>
+which would place the "Allegro" 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] "cresc.";
+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
+< not allowed required
+> 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 < >
+ lyrics
+ endings
+ rehearsal marks
+
+below (from top down)
+ phrase
+ mussym
+ octave
+ rom bold ital boldital < >
+ lyrics
+ pedal
+
+between (from bottom up)
+ mussym
+ rom bold ital boldital < >
+ 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 "above all" items of a given class will be above the
+items of that class for the top visible staff,
+and all "below all" 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>
+ <A HREF="textstr.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="textmark.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Tablature notation
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="lyrics.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="shaped.html">next page --></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 "tabnote
+staff." 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 "tab" 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 "tab." For example:
+<BR><PRE>
+stafflines = tab (e a d& 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 & 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 "stafflines = tab" 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 <>, 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 <\n>, </n>, <n\>, or <n/>.
+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<>; a6; d3<>; d2;
+bar
+
+2: b4</n>; e3<\n>; a2<n/>; e'5<n\>;
+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 "full" or a number and/or fraction.
+Some examples:
+<BR><PRE>
+2: e4 "full"; e "1/2"; 2e "1 1/2";
+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 "".
+Note that if both a fret and bend other than "" 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' "1/2" g "full" b "3/4"; e' ""; a2;
+bar
+
+2: a "1/2"; a "full"; a "1/2"; a "";
+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 "transpose" 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>
+ <A HREF="lyrics.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="shaped.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Location Tags
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="roll.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="prnttext.html">next page --></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 "center" coordinate of the object. This is not necessarily
+the geometric center, but more of a "logical center." 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 "normal" 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 "pre-defined" 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 "x" 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 "g"
+(_tag.w, _item.n) // west of tag "_tag" and
+ // north of tag "_item"
+</PRE><BR>
+The first example refers to the x,y coordinate of tag "g". 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 "_tag," while its vertical
+position is in line with the north side of the object having the tag "_item".
+In other words, if a line were drawn along the west side of the object
+tagged with "_tag" and another line were drawn along the top edge of the
+object with tag "_item", 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 "time". This
+is specified by using the keyword "time" 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 "q" 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 "q" 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 "0") and the first
+chord in the measure (at count "1"). 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 "+ time 2" (a half note) would mean 1.0 inch to the right, or
+specifying "- time 2" 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>
+ <A HREF="roll.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="prnttext.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Marking complicated tempo changes
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="oddeven.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="multsong.html">next page --></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 "swing time," 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 "size" 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 "straight 8ths = triplet quarter plus 8th"
+
+// print the basic notes and equal sign
+print (X, Y) "\(smup4n) \(smup4n) = \(smup4n) \(smup8n)"
+
+// 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) "\s(8)\f(TI)3" // 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>
+ <A HREF="oddeven.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="multsong.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup Text Marks
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="stuff.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="mussym.html">next page --></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 "fontfamily" 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 "all."
+</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 "chord", "analysis", "figbass", or "dyn".
+The "chord" modifier is typically used for marking chords that might be
+played by a guitar or other instrument. The "analysis" modifier is
+typically used when marking harmonic analysis like "IV" or "vii".
+The "figbass" 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 "dyn" modifier is to mark the text as something that specifies
+dynamics. Mup only uses it when deciding where to place the text;
+something marked "dyn" will be treated like crescendo
+and decrescendo "hairpins."
+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 ("#", "&", "x", "&&", and "n")
+are translated to the appropriate music character, while "o", "o/",
+and "^" are translated to "\(dim)", "\(halfdim)", and "\(triangle)"
+respectively. However, with "chord," the
+translation of "n" 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, "\\&" 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 "A" through "G"
+and any following accidentals will be transposed appropriately.
+The accidental can be either something like "#" or "&" or any of the special
+<A HREF="textstr.html#symlist">music characters</A>
+for accidentals (\(sharp), \(flat), etc.).
+If the staff is specified as "all," 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 "C"; 2 "G"; 3 "Dm"; 4 "G";
+rom analysis below 1: 1 "I"; 2 "V"; 3 "ii"; 4 "V";
+bar
+
+1: egc+;dgb;df#a;dgb;
+rom figbass below 1: 1 "6 3"; 2 "6 4"; 3 "3/"; 4 "6 4";
+bar
+
+1: 1cegb;
+rom chord above 1: 1 "C^7";
+bar
+1: 1ce&g&b&;
+rom chord above 1: 1 "Co/";
+bar
+1: 1ce&g&b&&;
+rom chord above 1: 1 "Co:7";
+bar
+1: 1e&g&b&;
+rom chord above 1: 1 "E&m";
+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 "~",
+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 "Andante ( \(smup4n) = 88 )";
+boldital (12) below 1: 1 "mf"; 3.5 "mp";
+newcentury bold (12) chord above 1: 1 "E&7"; 3 "B&9";
+ital between 1&2: 2 "rit.";
+palatino ital below 2: 2 "cresc." til 1m+2;
+bar
+1: 1egc+;
+2: 1c;
+bold (12) chord above 1: 1 "Cm";
+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 "y" chords will also have a grid printed.
+For this to work, a grid with the same name as the chord must be
+defined in "grids" 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 "chord" 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 "o" or "x"
+which will result in a circle or x respectively being printed above the
+grid, or a "-" 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
+ "C" " - 3 2 o 1 o "
+ "C5" " - 3 x o 1 3 "
+ "Em" " o 2 2 o o o "
+ "A&" "(4 6 6 5 4 4)"
+ "A11" " - o o o o o "
+music
+
+rom chord 1: 1 "C"; 2 "C5"; 3 "Em";
+1: 2c;e;
+bar
+
+rom chord 1: 1 "A&"; 3 "A11";
+1: 2a&;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 "A" chord in a chord statement, then
+transpose the staff up a major second, Mup will look for and use the grid
+definition called "B" 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, "Am" and "Am \b" 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>
+ <A HREF="stuff.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="mussym.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Text Strings
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="shaped.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="stuff.html">next page --></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>
+"A \"word\" in quotes"
+</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>
+"this is a string"
+"this is " + "a string"
+</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 "hat" or ^ (circumflex or "up-arrow")
+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 "railroad tracks" 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 "sm" to indicate a
+smaller version of the character. For example, "smup4n" is a small quarter
+note, as might be used for a "cue" 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 "Latin-1" 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 `` quotedblright ´´
+guillemotleft << guillemotright >>
+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´ aacute a´
+Acircumflex A^ acircumflex a^
+Adieresis A: adieresis a:
+Agrave A` agrave a`
+Aring Ao aring ao
+Atilde A~ atilde a~
+Ccedilla C, ccedilla c,
+Eacute E´ eacute e´
+Ecircumflex E^ ecircumflex e^
+Edieresis E: edieresis e:
+Egrave E` egrave e`
+Iacute I´ iacute i´
+Icircumflex I^ icircumflex i^
+Idieresis i: idieresis i:
+Igrave I` igrave i`
+Ntilde N~ ntilde n~
+Oacute O´ oacute o´
+Ocircumflex O^ ocircumflex o^
+Odieresis O: odieresis o:
+Ograve O` ograve o`
+Otilde O~ otilde o~
+Scaron Sv scaron sv
+Uacute U´ uacute u´
+Ucircumflex U^ ucircumflex u^
+Udieresis U: udieresis u:
+Ugrave U` ugrave u`
+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>
+"hello"
+"( \(up2n) = 100 )"
+"\f(TB)this will be bold. \f(TI)this will be italics"
+"A \f(TX)\s(+12)BIG\f(PV)\s(-12) word"
+"\f(newcentury boldital)Allegro"
+</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 "\n" 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>
+"Violins\nI&II"
+</PRE><BR>
+</P>
+<P>
+A "\b" 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, "My\b\b___" will line up
+much better than "M\b_y\b_".
+</P>
+<P>
+<A NAME="vert">Vertical motion within a string</A>
+can be specified using "\v(<I>N</I>)"
+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 "pile up" 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 <space> 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>
+"Text\:superscript subscript\: back to normal.";
+"This pile \:has\ literal spaces\ in\ it.";
+"This pile \:h\^as align\|ment spec\^ified.";
+</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>
+ "6\/"
+ "10\/"
+</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>
+ "\[This is in a box\]"
+ "\{This is in an ellipse\}"
+</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>
+ <A HREF="shaped.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="stuff.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Transposition
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="cadenza.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="verses.html">next page --></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>
+ <A HREF="cadenza.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="verses.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Tuplets
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="ichdattr.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="altinp.html">next page --></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 ("above" or "below").
+This is followed by a number or pair of numbers, and a semicolon.
+</P>
+<P>
+The "side" 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 "n" the number (and bracket) will not actually be
+printed.
+If it is followed by a "y" 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 "num" 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 "7" 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>
+ <A HREF="ichdattr.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="altinp.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Mup Utilities for displaying and printing output
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="cmdargs.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="gensyn.html">next page --></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> <Enter>
+<DD>
+Go to page number <I>num</I>.
+<DT>+ or <space> or <control-E> or <control-F>
+<DD>
+move forward on the page by about 1/8 of an inch
+(partial page mode only)
+<DT>- or <backspace> or <control-Y> or <control-B>
+<DD>
+move backward on the page by about 1/8 of an inch
+(partial page mode only)
+<DT>b or <control-U> or <control-P>
+<DD>
+move backward on the page by about an inch
+(partial page mode only)
+<DT>f or <Enter> or <control-D> or <control-N>
+<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>
+ <A HREF="cmdargs.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="gensyn.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<HTML>
+<HEAD><TITLE>
+Placing verses below the scores
+</TITLE></HEAD>
+<BODY>
+<P>
+ <A HREF="trnspose.html"><-- previous page</A>
+
+ <A HREF="index.html">Table of Contents</A> <A HREF="pianored.html">next page --></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 "print" or "paragraph" statements inside
+<A HREF="prnttext.html#block">a "block."</A>
+<BR><PRE>
+block
+print (_win.w + 30, _win.n - 15) "2. "
+print "\
+Here is the first line
+and the second line
+and the third line.
+"
+print (_win.w + 90, _win.n - 15) "3. "
+print "\
+Here is another verse's first line
+and its second line
+and its third line.
+"
+</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 "print" 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) "3. "
+print "\f(CR)\
+C D7 G7
+This is the first line
+C F
+of the next verse
+B\(smflat)
+of the song.
+"
+</PRE><BR>
+</P>
+<HR><P>
+ <A HREF="trnspose.html"><-- previous page</A> <A HREF="index.html">Table of Contents</A> <A HREF="pianored.html">next page --></A>
+</P>
+</BODY></HTML>
--- /dev/null
+<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 "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,
+<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 "up" 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 "Page 2 of 4 pages."
+<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 "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
+<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 "slash"
+<A HREF="uguide/shaped.html">note heads,</A>
+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.
+<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 "a major"
+or "c# minor."
+<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 "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.
+<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">"block" 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 "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.
+<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 "subbeams," 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 "gliss." 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 "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.
+<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 "alt pedstar" value for the
+<A HREF="uguide/param.html#pedstyle">pedstyle parameter</A>
+This is like the "pedstar" value
+except that when there is a pedal "bounce,"
+only a "Ped" is printed, rather than a "* Ped."
+<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">"include"</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 &) 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>
--- /dev/null
+
+ 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.
--- /dev/null
+
+# 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
--- /dev/null
+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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+
+/* 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);
+}
--- /dev/null
+
+/* 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);
+ }
+}
--- /dev/null
+/* 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;
+ }
+}
--- /dev/null
+
+/* 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));
+}
--- /dev/null
+
+/* 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);
+ }
+}
--- /dev/null
+
+/* 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;
+ }
+ }
+}
--- /dev/null
+
+/* 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);
+ }
+}
--- /dev/null
+/* 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
--- /dev/null
+
+/* 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.
+ */
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+
+/* 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) );
+}
--- /dev/null
+/* 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)
+};
--- /dev/null
+/* 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 */
--- /dev/null
+/* 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
--- /dev/null
+
+/* 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))) );
+}
--- /dev/null
+/* 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);
+}
+
+
--- /dev/null
+/* 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]);
+ }
+}
--- /dev/null
+
+/* 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;
+}
--- /dev/null
+
+/* 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);
+}
+
--- /dev/null
+
+/* 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);
+ }
+ }
+}
--- /dev/null
+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 = ✓
+
+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
--- /dev/null
+
+/* 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;
+ }
+}
--- /dev/null
+
+/* 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);
+}
--- /dev/null
+
+/* 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);
+}
--- /dev/null
+
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+
+/* 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 */
--- /dev/null
+/* 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 }
+ }
+};
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+
+/* 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)");
+ }
+}
--- /dev/null
+
+/* 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);
+ }
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+
+/* 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;
+ }
+ }
+}
--- /dev/null
+
+/* 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);
+}
--- /dev/null
+
+/* 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);
+ }
+ }
+ }
+}
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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]);
+ }
+}
--- /dev/null
+
+/* 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);
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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 */
+}
--- /dev/null
+
+/* 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);
+}
--- /dev/null
+/* 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;
+ }
+ }
+ }
+}
--- /dev/null
+/* 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;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+/* 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;
+ }
+ }
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+/* 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;
+}
--- /dev/null
+
+/* 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);
+ }
+ }
+ }
+}
--- /dev/null
+
+/* 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;
+}
--- /dev/null
+/* 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, ¬es[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;
+ }
+ }
+ }
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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;
+}
--- /dev/null
+
+/* 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);
+}
--- /dev/null
+/* 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;
+}
+
--- /dev/null
+/* 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 */
+
--- /dev/null
+
+/* 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
--- /dev/null
+
+/* 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
+
--- /dev/null
+
+/* 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');
+}
--- /dev/null
+
+/* 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
--- /dev/null
+
+/* 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
+}
--- /dev/null
+/* 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
+};
+
--- /dev/null
+
+/* 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
+}
--- /dev/null
+
+/* 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
--- /dev/null
+
+/* 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;
+}
--- /dev/null
+
+/* 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
--- /dev/null
+/* 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
+};
+
--- /dev/null
+
+/* 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
+
--- /dev/null
+/* 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);
+ }
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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();
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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;
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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();
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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);
+}
--- /dev/null
+/* 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
--- /dev/null
+/* 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());
+}
--- /dev/null
+/* 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
--- /dev/null
+#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
--- /dev/null
+/* 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.";
--- /dev/null
+/* 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. ",
+" ........ "};
--- /dev/null
+/* 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.. ",
+" ................. ",
+" ............ "};
--- /dev/null
+/* 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... ",
+" ......................... ",
+" ................... ",
+" ............... "};
--- /dev/null
+#include "resource.h"
+IDI_ICON ICON DISCARDABLE "mupicons.ico"
--- /dev/null
+/* 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)";
--- /dev/null
+#ifndef IDI_ICON
+#define IDI_ICON 101
+#endif
--- /dev/null
+/* 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";
--- /dev/null
+/* 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
--- /dev/null
+/* 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
--- /dev/null
+# 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