From: Mark Wooding Date: Mon, 22 Jan 2007 12:35:19 +0000 (+0000) Subject: Import upstream version 5.3. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/mup/commitdiff_plain/69695f3390a852259515c5e34005c291ef6c9e76 Import upstream version 5.3. --- 69695f3390a852259515c5e34005c291ef6c9e76 diff --git a/mup/docs/README0 b/mup/docs/README0 new file mode 100644 index 0000000..81a78c3 --- /dev/null +++ b/mup/docs/README0 @@ -0,0 +1,172 @@ + + Compiling Mup for UNIX + + 1. Compiling Mup for UNIX + + Mup has been compiled successfully on a wide variety of + UNIX-type systems, including Linux, UNIX SV_R4, and Solaris. + We cannot guarantee that it will work on your system, but it + generally ports with no more than minimal changes. + + Download the mup53src.tar.gz Mup source package file and + unpack it: + gunzip mup53src.tar.gz + tar xf mup53src.tar + + Alternately, you can download the RPM format Mup source + package and install it as you would any RPM package: + rpm -i mup-5.3-0.src.rpm + + Installing the source package will create a mup-5.3 + directory. Go to that directory. + cd mup-5.3 + There is a simple makefile provided, which should work on + most systems, so all you need to do is: + make install + You can edit the makefile if necessary for your environment. + Comments at the top of the makefile describe suggested + modifications if it doesn't work for you as is. Note that + if you want to install in a system directory (like the + default location /usr/bin) you will need to be root for the + installation step. Otherwise building Mup requires no + special privileges. + + If for some reason the makefile doesn't work, you can + compile Mup and any of the optional utility programs + (mupdisp, mkmupfnt, and mupmate) manually. For compling Mup + itself, generally, something like the following will work: + cd mup + cc -o mup *.c -lm + For most UNIX-like compilers, the "-o mup" will cause the + program to be put into a file called "mup," and the "-lm" + will cause the math library to be included (That's a lower- + case letter "el" not a one). You may also want to use other + options. For example, for many compilers "-O" (that's a + capital letter "oh" not a zero) will run the optimizer, and + "-s" will strip the resulting program to save disk space. + + Copy mup into your $HOME/bin or a similar directory in your + $PATH. + cp mup $HOME/bin/mup + + If you already have a means of displaying PostScript files, + such as gv, ghostview, or pageview, you can simply pipe the + output of Mup into your display program. Or you can use the + mupdisp program in connection with Ghostscript, which is + free. You can download Ghostscript from + http://www.cs.wisc.edu/~ghost, or + http://www.ghostscript.com/. We've found that on some + systems, Ghostscript compiles with lots of warnings, but it + works okay anyway. + + Once you have installed Ghostscript, compile the mupdisp + program for displaying Mup output on screen. See the comment + at the top of mupdisp.c for suggestions on compiler options + to try. + + Copy mupdisp into your $HOME/bin or similar directory. + cp mupdisp $HOME/bin/mupdisp + + The mupdisp program works on the AT386 $TERM type under UNIX + x86 or under X-windows. If you have a different display + type, you may need to write your own display functions. In + most cases, you'll only need to write 6 short functions, and + you can use the examples in at386.c, dos.c, or xterm.c for a + general template of the functions. You will also need to + update dispttyp.h and init.c appropriately. + + If you want to supply your own fonts to override the + standard Mup fonts, you can compile the mkmupfnt program: + cd mkmupfnt cc -o mkmupfnt mkmupfnt.c + + The Mupmate program provide a menu-driven interface on top + of Mup. It is built on top of the FLTK library, so you will + need to have the FLTK development package. You can get this + from http://www.fltk.org Get the latest version in the 1.1.x + series (we built with 1.1.7); don't get from the 2.x series. + Mupmate is written in C++, so you will need a C++ compiler, + such as g++. See the top level makefile for typical + compilation options. FLTK normally comes with its own copies + of libjpg, libpng, and libz (compression) libraries, but it + will usually work with the generic versions of those + libraries as well. You will also need standard X-windows + libraries: libX11, libXext, and libXpm. + + A shell script called "mupprnt" is included for printing Mup + files using Ghostscript. Copy mupprnt to your $HOME/bin or + other appropriate directory. + cp mupprnt $HOME/bin/mupprnt + You will need to set the GS_DEVICE shell variable to the + proper value for your printer. If you don't know what to set + it to, the comment at the top of mupprnt may help, or check + your Ghostscript documentation. You could also just use the + print option on your PostScript viewer such as gv. + + Once you have everything installed, you can remove the .tar + file if you wish, to free up disk space. + rm mup53src.tar + + Please let us know if you need any workarounds for compiling + on your system. We want to try to make Mup as portable as + possible. + + 2. Getting Mup running for the first time + + Once you get Mup to compile successfully, try running it. + The first time you run Mup, it should give you a message + indicating Mup is shareware, and asking you to read the Mup + license agreement. It will then tell you to create a + particular file. By creating this file, you agree to abide + by the Mup license, and Mup will be turned on for normal + operation. + + Try running Mup on the sample input files (sample.mup and + star.mup ). Verify that the output you get matches the + corresponding sample output files (sample.ps and star.ps ). + You will find differences in some of the numbers, comments, + timestamp, filenames, etc, but otherwise, in general the + PostScript output you get should be similar to the sample + output files provided, and if you display them, the results + should look pretty much identical. + + If Mup fails to run properly on the sample files, either + your system has uncovered a bug that we haven't seen yet or + your machine has some incompatibility. You can turn on + debugging, by running with the -dN option, where N is a + bitmap of debugging flags, to help pinpoint where bugs may + be. The Mup User's Guide explains the bits of the debugging + flags. If you get stuck, you may contact us at + support@arkkra.com and we will try to help. + + If you need to make any changes in order to get Mup to + compile and run successfully, please let us know. If you + find anything confusing, we'd like to know that too. We + want Mup to be as solid, portable, useful, and easy to use + as possible. + + Also, please let us know if there are ways we can improve + the Mup documentation. + + If you receive messages beginning with "internal error" this + usually indicates a program bug, so we'd like to know about + them. An exception is when you get a message about being + unable to allocate memory when there really isn't any memory + left. If you get other internal errors, please send us a + copy of an input file and any other information that may + help us reproduce the problem, so we can try to fix it in + the next Mup release. + + Mup is shareware. Once you get Mup up and running, you can + try it out for free to decide whether you want to use it or + not. If you like it, execute + mup -r + to get a copy of the shareware registration form. The + registration fee is $29. See the license file for license + details. + + Provide feedback (bugs reports, comments, suggestions, + questions) to: support@arkkra.com + + -------------------------------------------------- + + Arkkra Enterprises diff --git a/mup/docs/faq.txt b/mup/docs/faq.txt new file mode 100644 index 0000000..fd7cff2 --- /dev/null +++ b/mup/docs/faq.txt @@ -0,0 +1,307 @@ + + Mup Frequently Asked Questions (FAQ) + + 1. Frequent questions for those who have not yet used Mup + + 1.1 Q: What makes Mup unique? Why should I consider using + Mup? + + 1. Mup provides high quality music output at very low + cost. You can download Mup and try it out for + yourself. + + 2. Mup is available ready-to-run for several computer + operating systems, and is also available in source + form, so that it can be run on almost any kind of + computers, including Windows, Apple, Linux or Unix. + + 3. If you prefer a command line interface, Mup provides + that, and doesn't require using a mouse or learning a + new editor; you can just create a Mup input file using + any text editor of your choice. However, if you + prefer an interface with menus and integrated editor, + the companion Mupmate program provides that. + + 4. Mup input can be easily generated or manipulated by + another program. Input files are typically small, so + it doesn't take a long time to create them. Since they + are ordinary text they can easily be moved to other + systems, even if the other system uses a different + operating system. For example, it would be easy to + email a song in Mup format to a friend, and if they + had Mup, they could then print it out or play it via + MIDI. Since Mup output is standard PostScript or + standard MIDI, output files are also portable to + almost any operating system. + + 5. Mup handles page layout details, but provides ways to + alter the layout if you wish. It has the power to + handle complicated scores, and can produce + professional-quality output quickly. + + 6. Mup's ability to produce MIDI output can be very + helpful for "proof listening" to your music, which is + usually a very effective way to spot errors that you + might miss by just looking at the score, + + 1.2 Q: Will Mup run on my computer? + + We currently provide Mup in ready-to-run form for Windows + and Linux x86 systems. A port of Mup for the Macintosh is + available from + http://www.uni-paderborn.de/cs/Michael.Thies.html and a + version for OS/2 is available from http://homepages.tu- + darmstadt.de/~st002279/os2/html/mup.html + + If you use a different operating system, Mup source code is + also available, so if you have a C compiler, you can + probably compile and run Mup. It has been run using several + versions of UNIX on x86, Sun, Digital, Silicon Graphics, and + other systems. It has also been run under OS/2, as well as + on an Amiga. An ANSI-C compiler is recommended, but not + required. Under MS-DOS, you will need a memory extender, + and at least a 32-bit compiler is strongly recommended. Mup + will run on a 386, but at least a 486 is recommended for + best performance. If you try to compile Mup and have + problems, please let us know at support@arkkra.com We'd like + to make it portable to as many computer system types as + possible. The companion Mupmate program requires a C++ + compiler and the FLTK toolkit. + + 1.3 Q: How long will it take to learn how to use Mup? + + This will vary from person to person. A person who has + experience with computer languages will probably pick up Mup + more quickly, but such knowledge is not necessary. Mup has + a broad array of features, so if you want to learn how to + use every feature that Mup has to offer, this may take + several days. (The Mup User's Guide, which explains all the + features, and includes many examples, is about 150 pages + long.) However, once you get Mup installed, you can start + experimenting with Mup after reading the first few pages of + the User's Guide, and it should take no more than a few + hours to feel comfortable with the basics, enough to enter + simple songs and get professional-looking output. The + User's Guide includes many examples, and is provided both as + a PostScript file that you can print out on paper, and as + HTML files with hundreds of hypertext links, that you can + view with your Web browser. The Mup installation package + contains several sample files and a template file to help + you get started. You can also download sample songs from + ftp://ftp.arkkra.com/pub/music + + 1.4 Q: How long will it take to enter music? + + This will vary greatly, depending on a number of factors, + such as how complicated the music is, how much experience + you have had with using Mup, how fast you type, etc. An + experienced Mup user can typically enter simple music in + less than 15 minutes per page, but very complex music can + often take over an hour, especially if you like to make a + lot of adjustments to make things look just exactly the way + you want. + + 1.5 Q: How did Mup and Arkkra Enterprises come about? + + We are musicians and computer programmers who wanted a music + publication program that would produce very high-quality + output with a minimum amount of fuss. We wrote the Mup + program for our own use, and continue to use it for all our + own compositions. When other people expressed an interest in + getting a copy of Mup, we formed Arkkra Enterprises to set + up a Web site to make Mup available as shareware to anyone + who wants it. We rely on the shareware registration fee + that you pay to cover the cost of maintaining a Web site and + providing support to answer questions. We add new features + based on user suggestions, and once you register, we will + notify you of any future free upgrades. + + 1.6 Q: How do I pay for Mup? + + Fill out the registration form and send the form and (US) + $29 in cash, check, or money order to the address given on + the form. If you are writing a check from a bank outside + the United States, please make it out in the bank's local + currency in an amount equivalent to 29 U.S. dollars; our + bank will not accept US-dollar-denominated checks from non- + US banks. If you wish to pay via credit card, we have an + arrangement with setSystems to handle paying for Mup with a + credit card. They are able to handle transactions in many + different currencies. setSystems is part of Digital River, + a well-known e-commerce company. As soon as we receive your + payment, we will email the registration information to you. + Once you register, we will notify you via email of future + Mup versions, and you can upgrade to any future versions of + Mup for free. Once you have registered, you also can join + the Mup users mailing list if you wish, at no additional + charge. We only use your address to send you information + about Mup; it is our policy to not give out names, email, or + street addresses to anyone else. + + -------------------------------------------------- + + 2. Frequent questions from Mup users + + 2.1 Q. Is there a mailing list for Mup users? + + Yes. There is a "majordomo" mailing list available + exclusively to registered Mup users. It provides a forum + where you can ask or answer questions, get tips on how other + people are using Mup, etc. + + 2.2 Q. Can I put Mup output into some other document? + + There is a tool that comes with Ghostscript, called + "ps2epsi" that converts a PostScript file to an Encapsulated + PostScript file, which can then be imported into other + documents. + + 2.3 Q: Can Mup produce PDF files? + + Not directly, but since Mup produces PostScript output, you + can easily convert the output to PDF format using the ps2pdf + utility that comes with Ghostscript. + + 2.4 Q. Why is the first score indented differently than the + others? + + The first score of a piece of music is traditionally + indented somewhat more than subsequent scores, so that's + what Mup does by default. It does that by setting the + default label parameter to a few spaces, whereas it sets the + default for the label2 parameter to an empty string. If you + don't want the indentation, you can set + label="" + + 2.5 Q: Is is possible to specify a pickup measure? + + Yes. You use "space" on all voices. For example, + 1: 2.s; 4e; + 2: 2.s; 4c; + will produce a pickup measure with just a quarter note in + it. + + 2.6 Q: Is it possible to display a tempo marking of the + form '(N = 120)' where N is a note symbol, like a + quarter note? + + Yes. Try something like + rom above all: 1 "( \(sm4n) = 120 )"; + + 2.7 Q: Can Mup take a MIDI file as input? + + No. However, it is possible to write a program that reads a + MIDI file and outputs a file that can be input to Mup. Two + programs that do this, called "mtm" and "midi2mup" have been + donated by Mup users. They are limited, and not supported + by Arkkra Enterprises, but may be useful for some people. + Check out the programs donated by Mup users. + + 2.8 Q: What are some of the shorthands that can be used to + reduce typing? + + There are many shorthands available. Some of the most useful + are: + + - When the time value of a chord is the same as that of + the previous chord in the measure, it can be omitted. + If all pitch values of a chord are the same as the + previous chord, they can be omitted. For example: + 1: 4c; 4c; 4ceg; 4ceg; + is the same as + 1: 4c; ; ceg; ; + + - If several voices have the same music data, they can be + given on a single line. + 1-3 1-2: mr; + is equivalent to + 1 1: mr; + 1 2: mr; + 2 1: mr; + 2 2: mr; + 3 1: mr; + 3 2: mr; + A similar shorthand works for text and music symbols: + rom above 1-4: 3 "mf"; // staffs 1 through 4 + < below 2-3: 4 til 3m+2; // staffs 2 and 3 + mussym 1-5: 1 "ferm"; // staffs 1 through 5 + + - If several chords in a row have the same items in + square brackets before the chords, only the first must + have everything included. By giving an ellipsis after + the ] the items in brackets will be repeated for the + rest of the measure or until cancelled. Thus the + following lines are equivalent: + 1: [with .] c; [with .] d; [with .] e; + 1: [with .]... c; d; e; + + 2.9 Q: The Mupprnt command doesn't seem to work right. What + do I do? + + You may need to edit the mupprnt file to make sure the + variables and paths are set to match where things are + installed on your system. In particular, + + - GS_DIR needs to be set to the directory which contains + the Ghostscript font files (*.gsf) and the other + Ghostscript setup files (gs_*.ps). + + - GS_DEVICE needs to be set to the proper type to match + your printer type. + + - The path to Mup must be correct + + - The path to Ghostscript (gs or gs386 on MS-DOS/Windows + system) must be correct. + + - On MS-DOS/Windows systems, dos4gw.exe must be in your + PATH. + If you are using a viewer such as GSview or gv, you may want + to use its print feature rather than using mupprnt. + + 2.10 Q: On MS-DOS, the Mupdisp command comes back with + ghostscript error 1. What do I do? + + Check your config.sys file. You need to have a line like + files=10 + where the number after the equals sign is greater than or + equal to 9. + + Also, make sure gs386.exe exists and is in your PATH. If you + are running Mup from MS-DOS directly or from a DOS prompt + under Windows, make sure you installed the DOS version of + Ghostscript, not the Windows version. If you are using + Mupmate, or Winmup, make sure you installed the Windows + version of Ghostscript, not the MS-DOS version. + + 2.11 Q: If I use Mup for a language other than English, + will it handle the letters that are not used in + English? + + Mup handles most common non-ASCII characters. If your + keyboard does not allow you to enter them directly, you can + enter them by name, such as \(a:) for an 'a' with 2 dots + over it. The User's Guide section on text strings gives a + complete list of supported non-ASCII characters. + + 2.12 Q: Under Linux, Mupdisp says it can't open + /dev/console. What do I do? + + The svga library used by Mupdisp in non-X-windows mode + requires write permission to the console. To allow this: + + - Make Mupdisp setuid to root: + chown root mupdisp + chmod 4755 mupdisp + + 2.13 Q: What if I have more questions about Mup? + + Send us email at support@arkkra.com We welcome any comments + and questions about Mup. Normally, you should have no + problem contacting us this way. In the unlikely event you + get a "rejected" reply when sending email, this is because + excessive "spam" (junk mail) has been received from your + domain at some time in the past, and our Internet service + provider has installed a "spam blocker." In this case, you + will have to send email from another address or send paper + mail. diff --git a/mup/docs/license.txt b/mup/docs/license.txt new file mode 100644 index 0000000..8aa2155 --- /dev/null +++ b/mup/docs/license.txt @@ -0,0 +1,82 @@ + + Mup License + + At Arkkra Enterprises, we'd like all our customers to be + delighted with our products. To ensure that Mup and any + other products or services we provide are readily available + at the lowest possible cost to you, we need to establish + licensing terms. + + While there are other music publication programs on the + market, we believe Mup has unique features that you may find + very useful. Since different people may want different + things in a music publication program, you do not have to + pay for Mup until after you've had a chance to try it out + and evaluate it for yourself. If you have problems with + Mup, let us know and we will try to resolve them. If you + have paid your registration fee and we cannot resolve + problems to your satisfaction, we will gladly refund your + money. + + 1. Mup License + + Arkkra Enterprises disclaims all warranties relating to this + software, whether expressed or implied, including but not + limited to any implied warranties of merchantability and + fitness for a particular purpose, and all such warranties + are expressly and specifically disclaimed. Neither Arkkra + Enterprises nor anyone else who has been involved in the + creation, production, or delivery of this software shall be + liable for any indirect, consequential, or incidental + damages arising out of the use of or inability to use such + software even if Arkkra Enterprises has been advised of the + possibility of such damages of claims. In no event shall + Arkkra Enterprises' liability for any damages ever exceed + the price paid for the license to use the software, + regardless of the form of the claim. The person using the + software bears all risk as to the quality and performance of + the software. + + Some states do not allow the exclusion of the limit of + liability for consequential damages, so the above limitation + may not apply to you. + + This agreement shall be governed by the laws of the state of + Illinois and shall inure to the benefit of Arkkra + Enterprises, and any successors, administrators, heirs and + assigns. Any action or proceeding brought by either party + against the other arising out of or related to this + agreement shall be brought only in the state or federal + court of competent jurisdiction located in DuPage County, + Illinois. The parties hereby consent to in personam + jurisdiction of said courts. + + This software is licensed to you, for your own use. This is + copyrighted software. You are not obtaining title to the + software or any copyright rights. You may not sublicense, + rent, lease, convey, modify, or translate this software for + any purpose. + + You may make as many copies as you need for back-up + purposes. You may use this software on more than one + computer, provided there is no chance it will be used + simultaneously on more than one computer. If you need to + use this software on more than one computer simultaneously, + you will need to obtain a license for each copy or a site + license. + + You may make copies of this software for other parties under + the following terms: + + - The copy must be an exact copy as would be obtained + directly from Arkkra Enterprises, including this + license. It must clearly state that it is a copy, and + must give the address of Arkkra Enterprises. + + - The copy must be used by the obtaining party only for + the purpose of trialing the software. If after trialing + the software, the receiving party wishes to continue to + use the software, they must submit their license fee. + + - All limitations and disclaimers of this license apply + to the copy. diff --git a/mup/docs/mkmupfnt.1 b/mup/docs/mkmupfnt.1 new file mode 100644 index 0000000..f2438d3 --- /dev/null +++ b/mup/docs/mkmupfnt.1 @@ -0,0 +1,106 @@ +.TH mkmupfnt 1 "July 31, 1999" "Arkkra Enterprises" +.SH NAME +.PP +mkmupfnt - create fontfile for overriding Mup fonts +.SH SYNOPSIS +.PP +mkmupfnt \fIPostScript_font_name Mup_font_name outfile [file]\fP +.SH DESCRIPTION +.PP +The \fBmkmupfnt\fP program creates an \fIoutfile\fP that can be used +with the Mup "fontfile" statement to override a Mup font. +.PP +The \fIPostScript_font_name\fP is the name of the font you want Mup +to use. This would be something that could be given as a name +to the PostScript \fBfindfont\fP procedure. +.PP +The \fIMup_font_name\fP is the name of the Mup font you want to +override, either an abbreviated name, like "PR" or a full +name, like "palatino rom". +.PP +The \fIoutfile\fP is the file that will be generated, which will +contain character size and other information, to use with +Mup's "fontfile" statement. +.PP +The final optional \fIfile\fP argument is the name of a file that +contains PostScript to be placed at the end of the Mup PostScript prolog. +This might be useful if you have a font whose implementation PostScript could +not find on its own. For example, if you've written your own font +implementation, you could put it in the given \fIfile\fP. +The actual characters produced by the font need not be similar to those +in the font being replaced; they could be in some other alphabet, +or hieroglyphics or whatever you wish. However, see the CAVEATS section +for limitations. +.PP +An an example, suppose you want Mup to use the Helvetica-Narrow font +rather than the plain Helvetica font. You could use: +.br +.in +0.5i +mkmupfnt Helvetica-Narrow HR helvnarr +.in -0.5i +.br +to generate a Mup fontfile, then in your Mup program put: +.br +.in +0.5i +fontfile "helvnarr" +.in -0.5i +.br +Then anything that would normally be printed in Helvetica will come out +in Helvetica-Narrow instead. +.SH "FILE FORMAT" +.PP +Mup requires a \fIfontfile\fP to be in a fairly rigid format. +This section describes the format of the file that is produced by +mkmupfnt. +The file can contain comment lines, which have a '#' in column 1. +Otherwise the format is: +.br +.nf +.na +.in +0.3i +\fBMup font name:\fP \fIMup_font_name\fP +\fBPostScript font name:\fP \fIPostScript_font_name\fP +\fBSize data:\fP +\fB32\fP \fIwidth height ascent\fP +\fB33\fP \fIwidth height ascent\fP + \fI... similar lines for ASCII codes 34-126. + Dimension are given in 1/1000ths of an inch for a 12-point character. + All codes must be specified, and they must be in order.\fP +\fBPostScript:\fP + \fIZero or more lines of PostScript that will be copied + exactly as is to the end of the Mup PostScript prolog.\fP +.br +.in -0.3i +.fi +.ad +.SH FILES +.P +mkmupfnt.ps PostScript program that extracts font size information +.SH "SEE ALSO" +.PP +gs(1), mup(1). +.br +Mup \(em Music Publisher User's Guide +.SH "CAVEATS" +.PP +You must have ghostscript (gs or gs386.exe) in your PATH +and it must be built to include the "bit" device. +.PP +Mup uses certain fonts for certain things, such as +time signatures, octave marks, endings, tuplet numbers, etc. +(The fonts used include all the Times fonts and New Century bold, plus +Helvetica roman and Helvetica bold for tablature.) +If your override one of the fonts used for those things, they will +come out in your new font. On the one hand, if you don't like Mup's +choices, this provides you a way to get your own. On the other hand, +if you want to change most, but not all uses of a particular font, +it may not be possible to do that. +.PP +Only the ASCII characters 32-126 can be overridden. The non-ASCII +characters can not be overridden. +.PP +Mup only allows width values up to 1/2 inch for +a 12-point character. This program does not enforce that limitation. +.PP +This program has been tested with various Ghostscript fonts, +but may not work on just any arbitrary PostScript font. diff --git a/mup/docs/mkmupfnt.ps b/mup/docs/mkmupfnt.ps new file mode 100644 index 0000000..3527c5f --- /dev/null +++ b/mup/docs/mkmupfnt.ps @@ -0,0 +1,314 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.17.2 +%%CreationDate: Sat Dec 9 16:59:22 2006 +%%DocumentNeededResources: font Times-Roman +%%+ font Times-Bold +%%+ font Times-Italic +%%DocumentSuppliedResources: procset grops 1.17 2 +%%Pages: 2 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +%%BeginResource: procset grops 1.17 2 +/setpacking where{ +pop +currentpacking +true setpacking +}if +/grops 120 dict dup begin +/SC 32 def +/A/show load def +/B{0 SC 3 -1 roll widthshow}bind def +/C{0 exch ashow}bind def +/D{0 exch 0 SC 5 2 roll awidthshow}bind def +/E{0 rmoveto show}bind def +/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def +/G{0 rmoveto 0 exch ashow}bind def +/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/I{0 exch rmoveto show}bind def +/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def +/K{0 exch rmoveto 0 exch ashow}bind def +/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/M{rmoveto show}bind def +/N{rmoveto 0 SC 3 -1 roll widthshow}bind def +/O{rmoveto 0 exch ashow}bind def +/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/Q{moveto show}bind def +/R{moveto 0 SC 3 -1 roll widthshow}bind def +/S{moveto 0 exch ashow}bind def +/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/SF{ +findfont exch +[exch dup 0 exch 0 exch neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/MF{ +findfont +[5 2 roll +0 3 1 roll +neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def +/MANUAL{ +statusdict begin/manualfeed true store end +}bind def +/PLG{ +gsave newpath clippath pathbbox grestore +exch pop add exch pop +}bind def +/BP{ +/level0 save def +1 setlinecap +1 setlinejoin +72 RES div dup scale +LS{ +90 rotate +}{ +0 PL translate +}ifelse +1 -1 scale +}bind def +/EP{ +level0 restore +showpage +}bind def +/DA{ +newpath arcn stroke +}bind def +/SN{ +transform +.25 sub exch .25 sub exch +round .25 add exch round .25 add exch +itransform +}bind def +/DL{ +SN +moveto +SN +lineto stroke +}bind def +/DC{ +newpath 0 360 arc closepath +}bind def +/TM matrix def +/DE{ +TM currentmatrix pop +translate scale newpath 0 0 .5 0 360 arc closepath +TM setmatrix +}bind def +/RC/rcurveto load def +/RL/rlineto load def +/ST/stroke load def +/MT/moveto load def +/CL/closepath load def +/FL{ +currentgray exch setgray fill setgray +}bind def +/BL/fill load def +/LW/setlinewidth load def +/RE{ +findfont +dup maxlength 1 index/FontName known not{1 add}if dict begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +/Encoding exch def +dup/FontName exch def +currentdict end definefont pop +}bind def +/DEFS 0 def +/EBEGIN{ +moveto +DEFS begin +}bind def +/EEND/end load def +/CNT 0 def +/level1 0 def +/PBEGIN{ +/level1 save def +translate +div 3 1 roll div exch scale +neg exch neg exch translate +0 setgray +0 setlinecap +1 setlinewidth +0 setlinejoin +10 setmiterlimit +[]0 setdash +/setstrokeadjust where{ +pop +false setstrokeadjust +}if +/setoverprint where{ +pop +false setoverprint +}if +newpath +/CNT countdictstack def +userdict begin +/showpage{}def +}bind def +/PEND{ +clear +countdictstack CNT sub{end}repeat +level1 restore +}bind def +end def +/setpacking where{ +pop +setpacking +}if +%%EndResource +%%IncludeResource: font Times-Roman +%%IncludeResource: font Times-Bold +%%IncludeResource: font Times-Italic +grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 +def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron +/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent +/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen +/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon +/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O +/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex +/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y +/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft +/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl +/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen +/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft +/logicalnot/minus/registered/macron/degree/plusminus/twosuperior +/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior +/ordmasculine/guilsinglright/onequarter/onehalf/threequarters +/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE +/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex +/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn +/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla +/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis +/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash +/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def +/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE +/Times-Roman@0 ENC0/Times-Roman RE +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 358.84(mkmupfnt\(1\) mkmupfnt\(1\))72 48 R/F1 +10.95/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0 +(mkmupfnt - create font\214le for o)108 96 Q -.15(ve)-.15 G +(rriding Mup fonts).15 E F1(SYNOPSIS)72 112.8 Q F0(mkmupfnt)108 124.8 Q +/F2 10/Times-Italic@0 SF -.8(Po)2.5 G +(stScript_font_name Mup_font_name out\214le [\214le]).8 E F1 +(DESCRIPTION)72 141.6 Q F0(The)108 153.6 Q/F3 10/Times-Bold@0 SF +(mkmupfnt)2.862 E F0 .362(program creates an)2.862 F F2(out\214le)2.862 +E F0 .362(that can be used with the Mup "font\214le" statement to o) +2.862 F -.15(ve)-.15 G .361(rride a).15 F(Mup font.)108 165.6 Q(The)108 +182.4 Q F2 -.8(Po)3.854 G(stScript_font_name).8 E F0 1.354 +(is the name of the font you w)3.854 F 1.354(ant Mup to use. This w)-.1 +F 1.355(ould be something that)-.1 F(could be gi)108 194.4 Q -.15(ve) +-.25 G 2.5(na).15 G 2.5(san)-2.5 G(ame to the PostScript)-2.5 E F3 +(\214ndf)2.5 E(ont)-.25 E F0(procedure.)2.5 E(The)108 211.2 Q F2 +(Mup_font_name)3.5 E F0 1(is the name of the Mup font you w)3.5 F .999 +(ant to o)-.1 F -.15(ve)-.15 G .999(rride, either an abbre).15 F .999 +(viated name, lik)-.25 F(e)-.1 E("PR" or a full name, lik)108 223.2 Q +2.5(e")-.1 G(palatino rom".)-2.5 E(The)108 240 Q F2(out\214le)2.831 E F0 +.331(is the \214le that will be generated, which will contain character\ + size and other information, to use)2.831 F(with Mup')108 252 Q 2.5(s") +-.55 G(font\214le" statement.)-2.5 E .49(The \214nal optional)108 268.8 +R F2(\214le)2.99 E F0(ar)2.99 E .489(gument is the name of a \214le tha\ +t contains PostScript to be placed at the end of the)-.18 F .077 +(Mup PostScript prolog.)108 280.8 R .077(This might be useful if you ha) +5.077 F .378 -.15(ve a f)-.2 H .078 +(ont whose implementation PostScript could not).15 F .233 +(\214nd on its o)108 292.8 R .233(wn. F)-.25 F .233(or e)-.15 F .233 +(xample, if you')-.15 F .533 -.15(ve w)-.5 H .233(ritten your o).15 F +.232(wn font implementation, you could put it in the gi)-.25 F -.15(ve) +-.25 G(n).15 E F2(\214le)108 304.8 Q F0 5.103(.T)C .103(he actual chara\ +cters produced by the font need not be similar to those in the font bei\ +ng replaced; the)-5.103 F(y)-.15 E .496 +(could be in some other alphabet, or hieroglyphics or whate)108 316.8 R +-.15(ve)-.25 G 2.996(ry).15 G .496(ou wish. Ho)-2.996 F(we)-.25 E -.15 +(ve)-.25 G 1.296 -.4(r, s).15 H .496(ee the CA).4 F(VEA)-1.35 E .496 +(TS sec-)-1.11 F(tion for limitations.)108 328.8 Q 1.031(An an e)108 +345.6 R 1.031(xample, suppose you w)-.15 F 1.031 +(ant Mup to use the Helv)-.1 F(etica-Narro)-.15 E 3.531(wf)-.25 G 1.032 +(ont rather than the plain Helv)-3.531 F(etica)-.15 E(font. Y)108 357.6 +Q(ou could use:)-1.1 E(mkmupfnt Helv)144 369.6 Q(etica-Narro)-.15 E 2.5 +(wH)-.25 G 2.5(Rh)-2.5 G(elvnarr)-2.5 E +(to generate a Mup font\214le, then in your Mup program put:)108 381.6 Q +(font\214le "helvnarr")144 393.6 Q(Then an)108 405.6 Q(ything that w) +-.15 E(ould normally be printed in Helv)-.1 E +(etica will come out in Helv)-.15 E(etica-Narro)-.15 E 2.5(wi)-.25 G +(nstead.)-2.5 E F1(FILE FORMA)72 422.4 Q(T)-1.04 E F0 .037 +(Mup requires a)108 434.4 R F2(font\214le)2.537 E F0 .037(to be in a f) +2.537 F .037(airly rigid format.)-.1 F .036 +(This section describes the format of the \214le that is pro-)5.037 F +.068(duced by mkmupfnt.)108 446.4 R .068 +(The \214le can contain comment lines, which ha)5.068 F .368 -.15 +(ve a ')-.2 H .069(#' in column 1.).15 F .069(Otherwise the for)5.069 F +(-)-.2 E(mat is:)108 458.4 Q F3(Mup f)129.6 470.4 Q(ont name:)-.25 E F2 +(Mup_font_name)2.5 E F3 -.2(Po)129.6 482.4 S(stScript f).2 E(ont name:) +-.25 E F2 -.8(Po)2.5 G(stScript_font_name).8 E F3(Size data:)129.6 494.4 +Q(32)129.6 506.4 Q F2 5(width height ascent)7.5 F F3(33)129.6 518.4 Q F2 +5(width height ascent)7.5 F(... similar lines for ASCII codes 34-126.) +165.6 530.4 Q(Dimension ar)165.6 542.4 Q 2.5(eg)-.37 G +(iven in 1/1000ths of an inc)-2.5 E 2.5(hf)-.15 G(or a 12-point c)-2.5 E +(har)-.15 E(acter)-.15 E(.)-1.11 E +(All codes must be speci\214ed, and the)165.6 554.4 Q 2.5(ym)-.3 G +(ust be in or)-2.5 E(der)-.37 E(.)-1.11 E F3 -.2(Po)129.6 566.4 S +(stScript:).2 E F2(Zer)165.6 578.4 Q 2.5(oo)-.45 G 2.5(rm)-2.5 G(or)-2.5 +E 2.5(el)-.37 G(ines of P)-2.5 E(ostScript that will be copied)-.8 E -.2 +(ex)165.6 590.4 S(actly as is to the end of the Mup P).2 E(ostScript pr) +-.8 E(olo)-.45 E -.15(g.)-.1 G F1(FILES)72 607.2 Q F0 7.5 +(mkmupfnt.ps PostScript)108 619.2 R(program that e)2.5 E +(xtracts font size information)-.15 E F1(SEE ALSO)72 636 Q F0 +(gs\(1\), mup\(1\).)108 648 Q(Mup \212 Music Publisher User')108 660 Q +2.5(sG)-.55 G(uide)-2.5 E F1(CA)72 676.8 Q(VEA)-1.588 E(TS)-1.04 E F0 +-1.1(Yo)108 688.8 S 2.5(um)1.1 G(ust ha)-2.5 E .3 -.15(ve g)-.2 H +(hostscript \(gs or gs386.e).15 E -.15(xe)-.15 G 2.5(\)i).15 G 2.5(ny) +-2.5 G(our P)-2.5 E -1.11(AT)-.92 G 2.5(Ha)1.11 G(nd it must be b)-2.5 E +(uilt to include the "bit" de)-.2 E(vice.)-.25 E .79(Mup uses certain f\ +onts for certain things, such as time signatures, octa)108 705.6 R 1.09 +-.15(ve m)-.2 H .79(arks, endings, tuplet numbers,).15 F 2.544 +(etc. \(The)108 717.6 R .044(fonts used include all the T)2.544 F .044 +(imes fonts and Ne)-.35 F 2.544(wC)-.25 G .044(entury bold, plus Helv) +-2.544 F .045(etica roman and Helv)-.15 F(etica)-.15 E .43 +(bold for tablature.\))108 729.6 R .43(If your o)5.43 F -.15(ve)-.15 G +.43(rride one of the fonts used for those things, the).15 F 2.93(yw)-.15 +G .43(ill come out in your ne)-2.93 F(w)-.25 E(Arkkra Enterprises)72 768 +Q(July 31, 1999)131.105 E(1)201.915 E EP +%%Page: 2 2 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 358.84(mkmupfnt\(1\) mkmupfnt\(1\))72 48 R .862 +(font. On the one hand, if you don')108 84 R 3.362(tl)-.18 G(ik)-3.362 E +3.362(eM)-.1 G(up')-3.362 E 3.362(sc)-.55 G .862(hoices, this pro)-3.362 +F .862(vides you a w)-.15 F .862(ay to get your o)-.1 F .862(wn. On the) +-.25 F .826(other hand, if you w)108 96 R .826(ant to change most, b)-.1 +F .826 +(ut not all uses of a particular font, it may not be possible to do)-.2 +F(that.)108 108 Q(Only the ASCII characters 32-126 can be o)108 124.8 Q +-.15(ve)-.15 G(rridden. The non-ASCII characters can not be o).15 E -.15 +(ve)-.15 G(rridden.).15 E .682(Mup only allo)108 141.6 R .682 +(ws width v)-.25 F .682(alues up to 1/2 inch for a 12-point character) +-.25 F 3.182(.T)-.55 G .683(his program does not enforce that)-3.182 F +(limitation.)108 153.6 Q 2.064(This program has been tested with v)108 +170.4 R 2.064(arious Ghostscript fonts, b)-.25 F 2.064(ut may not w)-.2 +F 2.063(ork on just an)-.1 F 4.563(ya)-.15 G(rbitrary)-4.563 E +(PostScript font.)108 182.4 Q(Arkkra Enterprises)72 768 Q(July 31, 1999) +131.105 E(2)201.915 E EP +%%Trailer +end +%%EOF diff --git a/mup/docs/mup.1 b/mup/docs/mup.1 new file mode 100644 index 0000000..39f8645 --- /dev/null +++ b/mup/docs/mup.1 @@ -0,0 +1,219 @@ +.TH mup 1 "Sep 25, 2006" "Arkkra Enterprises" +.SH NAME +.PP +mup - music publisher +.SH SYNOPSIS +.PP +\fBmup\fP [\fB-c\fP\fIN\fP] [-C] [\fB-d\fP\fIN\fP] [\fB-D\fP \fIMACRO[=macro-def\fP]] +[\fB-e\fP \fIerrfile\fP] [-E] +[\fB-f\fP \fIoutfile\fP] [\fB-F\fP] [\fB-m\fP \fImidifile\fP] [\fB-M\fP] [\fB-o\fP \fIpagelist\fP] [\fB-p\fP\fIN\fP] +[\fB-v\fP] [\fB-x\fP \fIN\fP[,\fIM\fP] [\fIfile...\fP] +.SH DESCRIPTION +.PP +Mup is a program for producing printed music. +There is an optional companion program called Mupmate +that provides a more graphical user interface on top of Mup, +but this manual page describes the command line interface. +The Mup User's Guide should be consulted for details of the format of the +input file. +Options include: +.TP +\fB-c\fP \fIN\fP +Combine consecutive measures of all rests or spaces into multirests (multiple +measures of rest printed as a single measure, with the number of measures of +rest printed above the staff). +Any time there +are \fIN\fP or more measures in a row that consist entirely of rests or spaces, +they will be replaced by a multirest. The combining of measures +stops when there is a visible staff that contains notes, +lyrics, or other musical symbols, +when there are parameter changes on a visible staff or in score context, or +when there is a bar line other than an ordinary or invisible bar. +This option is most likely to be useful when printing a subset of staffs, +where the particular staff(s) you are printing have long periods of rests. +(See the -s option.) +.TP +\fB-C\fP +This option is only used in connection with the -E option. +It specifies that comments +are to be passed through rather than deleted. +.TP +\fB-d\fP \fIN\fP +Print debugging information. \fIN\fP is a bitmap. +.RS 4 +.TP +1 +parse phase information +.TP +2 +high level parse phase tracing +.TP +4 +low level parse phase tracing +.TP +8 +reserved +.TP +16 +high level placement phase tracing +.TP +32 +low level placement phase tracing +.TP +64 +reserved +.TP +128 +contents of the main internal list +.TP +256 +high level print phase tracing +.TP +512 +low level print phase tracing +.RE +.IP +\fIN\fP can be specified in decimal, octal +(by using a leading zero), or hex (by using a leading 0x). +This information is intended for debugging of +\fBMup\fP itself and thus is not likely to be of use to the average user. +.TP +\fB-D\fP \fIMACRO[=macro-def]\fP +Define the macro \fIMACRO\fP. The +macro name must consist of upper case letters, +digits, and underscores, beginning +with an upper case letter. The \fImacro_def\fP is optional, and gives the +text of the macro. If it contains any white space or other special characters, +it must be quoted (if quoting is supported by your operating system or shell). +.TP +\fB-e\fP \fIerrfile\fP +Place error messages into \fIerrfile\fP instead of writing them to the standard +error output stream. +.TP +\fB-E\fP +Rather than produce PostScript or MIDI output, just expand macros and +includes, and write the result to the standard output stream. +Comments in the input are deleted, unless the -C option is also specified. +.TP +\fB-f\fP \fIoutfile\fP +Place the output into \fIoutfile\fP instead of writing it to the +standard output. +.TP +\fB-F\fP +This is like the \fB-f\fP option, except the name of the output file is +derived from the name of the Mup input file. If the name of the Mup input +file ends with a ".mup" suffix, the generated PostScript output +file will end with a ".ps" suffix instead. +If the name of the Mup input file ends with +a ".MUP" suffix, the PostScript file will end with a ".PS" suffix. +Otherwise, a ".ps" suffix will be appended to the end of the Mup +input file name. If multiple input files are listed, the last is used. +If none are specified (input is read from standard input), +the name "stdin.ps" will be used for the output file. +.TP +\fB-m\fP \fImidifile\fP +Instead of generating PostScript output, +generate standard MIDI (Musical Instrument Digital Interface) output, +and put it in \fImidifile\fP. +This option also causes the macro "MIDI" to become defined. +.TP +\fB-M\fP +This is like the \fB-m\fP option, except the name of the MIDI file is +derived from the name of the Mup input file. If the name of the Mup input +file ends with a ".mup" suffix, the generated MIDI file will end with +a ".mid" suffix instead. If the name of the Mup input file ends with +a ".MUP" suffix, the MIDI file will end with a ".MID" suffix. +Otherwise, a ".mid" suffix will be appended to the end of the Mup +input file name. If multiple input files are listed, the last is used. +If none are specified (input is read from standard input), +the name "stdin.mid" will be used for the MIDI file. +.TP +\fB-o\fP \fIpagelist\fP +Print only the pages given in \fIpagelist\fP. The \fIpagelist\fP can be +a comma-separated list of numbers or ranges, where a range is two numbers +separated by a dash. For example, -o1,7-9,12-14 would print pages 1, 7, 8, +9, 12, 13, and 14. Pages will be printed in the order given. +They need not be in order, and a page +number may be included more than once. +Alternately, the \fIpagelist\fP can be the special +keyword "odd" or "even" which will cause all odd or even numbered pages +to be printed. This may be useful if you have a printer that only makes +single-sided copies, but you wish to print Mup output double-sided. You could +print odd-numbered pages, then turn the paper over and feed the pages +through again for the even-numbered pages. +.TP +\fB-p\fP\fIN\fP +Start numbering pages at \fIN\fP instead of at 1. +If \fB-o\fP and \fB-p\fP are used together, the page numbers given in the +\fB-o\fP\fIpagelist\fP must be the printed page numbers. For example, if you +use -p10 and want to print just the second page, +you would need to specify -o11. +.TP +\fB-r\fP +Print a copy of the Mup shareware registration form to the standard output. +.TP +\fB-s\fP\fIstafflist\fP +Only print the staffs that are included in \fIstafflist\fP. This can be a +comma-separated list of staff numbers or ranges, such as "1,5" or "1-3,7-8" +To further restrict to a single voice on a staff, add \fBv\fP\fIN\fP where +\fIN\fP is the voice number (1, 2, or 3), after the staff, as in "2v1,5v2" +You can't specify a list or range for voices; +if you only want to make two out of three voices visible, +you have to specify them separately, like "1v2,1v3". +No spaces are allowed in the list. +.TP +\fB-v\fP +Print the Mup version number and exit. This manual page is for version 5.3. +.TP +\fB-x\fP\fIM,N\fP +Extract measures \fIM\fP through \fIN\fP of the song. This allows you to print +or play a part of a song. The comma and second value are optional; +if not specified, the default is to go to the end of the piece. +Positive values specify the number of measures from the beginning of the piece, +while negative values are relative to the end, with -1 referring to the +last measure of the song. +So -x1,-1 means the entire song, if the song doesn't have a pickup measure. +If the song has a pickup measure, that is specified by 0. +So for a song with a pickup, -x0,-1 would mean the entire song, +and -x0,0 would mean just the pickup measure. +As other examples, -x-1,-1 means just the final measure of the song, +-x2 means starting after the first full measure, -x3,4 means only +measures 3 and 4, and -x6,6 means just measure 6. +The starting measure is not allowed to be inside an ending. +A common use for this option might be to generate a MIDI file +for just a few measures. For example, if you were +trying to tweak tempo values for a ritard in the last 2 measures of a song, +you could use -x-2 to listen to just those measures. +.PP +The options, if any, can be followed by one or more \fIfiles\fP in Mup format. +If no \fIfiles\fP are specified, standard input is read. +If several \fIfiles\fP are listed, they are effectively concatenated together +and treated as one big file. Since there are some things (such as header +and footer) that are only allowed to occur once, if you have several independent +pieces, mup should be called on each individually rather than trying to +print them all with one command. +If a specified file does not exist, and its name does not already end +with .mup or .MUP, then Mup will append .mup to the specified name and +attempt to open that. +.PP +On most systems, the environment variable MUPPATH can be set +to a list of paths in which to look for 'include' files. +The components are separated by a colon on Unix or Linux systems, and by a +semicolon on systems with DOS-like file naming conventions. +.PP +For more debugging, in addition to the -d option, +if the environment variable MUP_BB is set to "bcfghnsu" or any subset +of those letters, the generated output will include "bounding +boxes" for the things Mup internally calls bars (b), chords (c), feeds (f), +grpsyls (g), header/footer and top/bottom (h), +notes (n), staffs (s), and stuff (u). +While this is intended for use in debugging Mup itself, it may also +help you understand why Mup places things the way it does, +since in general, Mup only allows bounding boxes to overlap according +to specific rules. If viewed with a color PostScript viewer (not mupdisp), +these boxes will be in color. +.SH "SEE ALSO" +.PP +gs(1), mkmupfnt(1), mupdisp(1), mupmate(1), mupprnt(1). +.br +Mup \(em Music Publisher User's Guide diff --git a/mup/docs/mup.ps b/mup/docs/mup.ps new file mode 100644 index 0000000..3383401 --- /dev/null +++ b/mup/docs/mup.ps @@ -0,0 +1,463 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.17.2 +%%CreationDate: Sat Dec 9 16:59:22 2006 +%%DocumentNeededResources: font Times-Roman +%%+ font Times-Bold +%%+ font Times-Italic +%%DocumentSuppliedResources: procset grops 1.17 2 +%%Pages: 3 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +%%BeginResource: procset grops 1.17 2 +/setpacking where{ +pop +currentpacking +true setpacking +}if +/grops 120 dict dup begin +/SC 32 def +/A/show load def +/B{0 SC 3 -1 roll widthshow}bind def +/C{0 exch ashow}bind def +/D{0 exch 0 SC 5 2 roll awidthshow}bind def +/E{0 rmoveto show}bind def +/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def +/G{0 rmoveto 0 exch ashow}bind def +/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/I{0 exch rmoveto show}bind def +/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def +/K{0 exch rmoveto 0 exch ashow}bind def +/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/M{rmoveto show}bind def +/N{rmoveto 0 SC 3 -1 roll widthshow}bind def +/O{rmoveto 0 exch ashow}bind def +/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/Q{moveto show}bind def +/R{moveto 0 SC 3 -1 roll widthshow}bind def +/S{moveto 0 exch ashow}bind def +/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/SF{ +findfont exch +[exch dup 0 exch 0 exch neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/MF{ +findfont +[5 2 roll +0 3 1 roll +neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def +/MANUAL{ +statusdict begin/manualfeed true store end +}bind def +/PLG{ +gsave newpath clippath pathbbox grestore +exch pop add exch pop +}bind def +/BP{ +/level0 save def +1 setlinecap +1 setlinejoin +72 RES div dup scale +LS{ +90 rotate +}{ +0 PL translate +}ifelse +1 -1 scale +}bind def +/EP{ +level0 restore +showpage +}bind def +/DA{ +newpath arcn stroke +}bind def +/SN{ +transform +.25 sub exch .25 sub exch +round .25 add exch round .25 add exch +itransform +}bind def +/DL{ +SN +moveto +SN +lineto stroke +}bind def +/DC{ +newpath 0 360 arc closepath +}bind def +/TM matrix def +/DE{ +TM currentmatrix pop +translate scale newpath 0 0 .5 0 360 arc closepath +TM setmatrix +}bind def +/RC/rcurveto load def +/RL/rlineto load def +/ST/stroke load def +/MT/moveto load def +/CL/closepath load def +/FL{ +currentgray exch setgray fill setgray +}bind def +/BL/fill load def +/LW/setlinewidth load def +/RE{ +findfont +dup maxlength 1 index/FontName known not{1 add}if dict begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +/Encoding exch def +dup/FontName exch def +currentdict end definefont pop +}bind def +/DEFS 0 def +/EBEGIN{ +moveto +DEFS begin +}bind def +/EEND/end load def +/CNT 0 def +/level1 0 def +/PBEGIN{ +/level1 save def +translate +div 3 1 roll div exch scale +neg exch neg exch translate +0 setgray +0 setlinecap +1 setlinewidth +0 setlinejoin +10 setmiterlimit +[]0 setdash +/setstrokeadjust where{ +pop +false setstrokeadjust +}if +/setoverprint where{ +pop +false setoverprint +}if +newpath +/CNT countdictstack def +userdict begin +/showpage{}def +}bind def +/PEND{ +clear +countdictstack CNT sub{end}repeat +level1 restore +}bind def +end def +/setpacking where{ +pop +setpacking +}if +%%EndResource +%%IncludeResource: font Times-Roman +%%IncludeResource: font Times-Bold +%%IncludeResource: font Times-Italic +grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 +def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron +/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent +/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen +/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon +/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O +/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex +/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y +/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft +/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl +/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen +/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft +/logicalnot/minus/registered/macron/degree/plusminus/twosuperior +/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior +/ordmasculine/guilsinglright/onequarter/onehalf/threequarters +/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE +/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex +/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn +/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla +/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis +/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash +/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def +/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE +/Times-Roman@0 ENC0/Times-Roman RE +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 406.62(mup\(1\) mup\(1\))72 48 R/F1 10.95 +/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0(mup - music publisher)108 +96 Q F1(SYNOPSIS)72 112.8 Q/F2 10/Times-Bold@0 SF(mup)108 124.8 Q F0([) +3.88 E F2(-c)A/F3 10/Times-Italic@0 SF(N)A F0 3.88(][)C 1.38(-C] [)-3.88 +F F2(-d)A F3(N)A F0 3.88(][)C F2(-D)-3.88 E F3(MA)3.88 E(CR)-.3 E +(O[=macr)-.4 E(o-def)-.45 E F0 1.38(]] [)B F2(-e)A F3(err\214le)3.88 E +F0 3.88(][)C 1.38(-E] [)-3.88 F F2(-f)A F3(out\214le)3.88 E F0 3.88(][)C +F2(-F)-3.88 E F0 3.88(][)C F2(-m)-3.88 E F3(midi\214le)3.88 E F0 3.88 +(][)C F2(-M)-3.88 E F0 3.88(][)C F2(-o)-3.88 E F3(pa)108 136.8 Q -.1(ge) +-.1 G(list).1 E F0 2.5(][)C F2(-p)-2.5 E F3(N)A F0 2.5(][)C F2(-v)-2.5 E +F0 2.5(][)C F2(-x)-2.5 E F3(N)2.5 E F0([,)A F3(M)A F0 2.5(][)C F3 +(\214le)-2.5 E(...)-.15 E F0(])A F1(DESCRIPTION)72 153.6 Q F0 .563 +(Mup is a program for producing printed music.)108 165.6 R .564 +(There is an optional companion program called Mupmate)5.563 F .574 +(that pro)108 177.6 R .574(vides a more graphical user interf)-.15 F +.574(ace on top of Mup, b)-.1 F .573 +(ut this manual page describes the command)-.2 F 2.022(line interf)108 +189.6 R 4.522(ace. The)-.1 F 2.022(Mup User')4.522 F 4.522(sG)-.55 G +2.022(uide should be consulted for details of the format of the input \ +\214le.)-4.522 F(Options include:)108 201.6 Q F2(-c)108 218.4 Q F3(N)2.5 +E F0 1.544(Combine consecuti)19.06 F 1.843 -.15(ve m)-.25 H 1.543(easur\ +es of all rests or spaces into multirests \(multiple measures of rest) +.15 F 1.205(printed as a single measure, with the number of measures of\ + rest printed abo)144 230.4 R 1.505 -.15(ve t)-.15 H 1.205(he staf).15 F +3.705(f\). An)-.25 F(y)-.15 E 1.014(time there are)144 242.4 R F3(N) +3.514 E F0 1.013(or more measures in a ro)3.513 F 3.513(wt)-.25 G 1.013 +(hat consist entirely of rests or spaces, the)-3.513 F 3.513(yw)-.15 G +1.013(ill be)-3.513 F .967(replaced by a multirest. The combining of me\ +asures stops when there is a visible staf)144 254.4 R 3.468(ft)-.25 G +.968(hat con-)-3.468 F .718(tains notes, lyrics, or other musical symbo\ +ls, when there are parameter changes on a visible staf)144 266.4 R(f) +-.25 E .347(or in score conte)144 278.4 R .348 +(xt, or when there is a bar line other than an ordinary or in)-.15 F +.348(visible bar)-.4 F 5.348(.T)-.55 G .348(his option)-5.348 F 1.046 +(is most lik)144 290.4 R 1.046 +(ely to be useful when printing a subset of staf)-.1 F 1.046 +(fs, where the particular staf)-.25 F 1.045(f\(s\) you are)-.25 F +(printing ha)144 302.4 Q .3 -.15(ve l)-.2 H(ong periods of rests.).15 E +(\(See the -s option.\))5 E F2(-C)108 319.2 Q F0 1.154 +(This option is only used in connection with the -E option.)25.45 F +1.155(It speci\214es that comments are to be)6.155 F +(passed through rather than deleted.)144 331.2 Q F2(-d)108 348 Q F3(N) +2.5 E F0(Print deb)17.94 E(ugging information.)-.2 E F3(N)2.5 E F0 +(is a bitmap.)2.5 E 31(1p)128 364.8 S(arse phase information)-31 E 31 +(2h)128 381.6 S(igh le)-31 E -.15(ve)-.25 G 2.5(lp).15 G +(arse phase tracing)-2.5 E 31(4l)128 398.4 S .5 -.25(ow l)-31 H -2.15 +-.25(ev e).25 H 2.5(lp).25 G(arse phase tracing)-2.5 E 31(8r)128 415.2 S +(eserv)-31 E(ed)-.15 E 23.5(16 high)128 432 R(le)2.5 E -.15(ve)-.25 G +2.5(lp).15 G(lacement phase tracing)-2.5 E 23.5(32 lo)128 448.8 R 2.5 +(wl)-.25 G -2.15 -.25(ev e)-2.5 H 2.5(lp).25 G(lacement phase tracing) +-2.5 E 23.5(64 reserv)128 465.6 R(ed)-.15 E 18.5(128 contents)128 482.4 +R(of the main internal list)2.5 E 18.5(256 high)128 499.2 R(le)2.5 E +-.15(ve)-.25 G 2.5(lp).15 G(rint phase tracing)-2.5 E 18.5(512 lo)128 +516 R 2.5(wl)-.25 G -2.15 -.25(ev e)-2.5 H 2.5(lp).25 G +(rint phase tracing)-2.5 E F3(N)144 532.8 Q F0 .108(can be speci\214ed \ +in decimal, octal \(by using a leading zero\), or he)2.608 F 2.608(x\() +-.15 G .108(by using a leading 0x\).)-2.608 F(This)5.107 E .289 +(information is intended for deb)144 544.8 R .289(ugging of)-.2 F F2 +(Mup)2.789 E F0 .289(itself and thus is not lik)2.789 F .289 +(ely to be of use to the a)-.1 F -.15(ve)-.2 G -.2(r-).15 G(age user)144 +556.8 Q(.)-.55 E F2(-D)108 573.6 Q F3(MA)2.5 E(CR)-.3 E(O[=macr)-.4 E +(o-def])-.45 E F0 .576(De\214ne the macro)144 585.6 R F3(MA)3.076 E(CR) +-.3 E(O)-.4 E F0 3.076(.T)C .576 +(he macro name must consist of upper case letters, digits, and under) +-3.076 F(-)-.2 E 1.023(scores, be)144 597.6 R 1.023 +(ginning with an upper case letter)-.15 F 3.523(.T)-.55 G(he)-3.523 E F3 +(macr)3.523 E(o_def)-.45 E F0 1.023(is optional, and gi)3.523 F -.15(ve) +-.25 G 3.523(st).15 G 1.023(he te)-3.523 F 1.024(xt of the)-.15 F .807 +(macro. If it contains an)144 609.6 R 3.307(yw)-.15 G .807(hite space o\ +r other special characters, it must be quoted \(if quoting is)-3.307 F +(supported by your operating system or shell\).)144 621.6 Q F2(-e)108 +638.4 Q F3(err\214le)2.5 E F0(Place error messages into)144 650.4 Q F3 +(err\214le)2.5 E F0 +(instead of writing them to the standard error output stream.)2.5 E F2 +(-E)108 667.2 Q F0 1.078 +(Rather than produce PostScript or MIDI output, just e)26 F 1.078 +(xpand macros and includes, and write the)-.15 F .984 +(result to the standard output stream.)144 679.2 R .984 +(Comments in the input are deleted, unless the -C option is)5.984 F +(also speci\214ed.)144 691.2 Q(Arkkra Enterprises)72 768 Q(Sep 25, 2006) +131.94 E(1)202.75 E EP +%%Page: 2 2 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 406.62(mup\(1\) mup\(1\))72 48 R/F1 10 +/Times-Bold@0 SF(-f)108 84 Q/F2 10/Times-Italic@0 SF(out\214le)2.5 E F0 +(Place the output into)144 96 Q F2(out\214le)2.5 E F0 +(instead of writing it to the standard output.)2.5 E F1(-F)108 112.8 Q +F0 .598(This is lik)26.56 F 3.098(et)-.1 G(he)-3.098 E F1(-f)3.098 E F0 +.598(option, e)3.098 F .598(xcept the name of the output \214le is deri) +-.15 F -.15(ve)-.25 G 3.099(df).15 G .599(rom the name of the Mup)-3.099 +F 1.065(input \214le. If the name of the Mup input \214le ends with a "\ +.mup" suf)144 124.8 R 1.065(\214x, the generated PostScript)-.25 F 1.508 +(output \214le will end with a ".ps" suf)144 136.8 R 1.508 +(\214x instead.)-.25 F 1.509 +(If the name of the Mup input \214le ends with a)6.508 F .992 +(".MUP" suf)144 148.8 R .992 +(\214x, the PostScript \214le will end with a ".PS" suf)-.25 F 3.492 +(\214x. Otherwise,)-.25 F 3.492(a")3.492 G .992(.ps" suf)-3.492 F .991 +(\214x will be)-.25 F .609(appended to the end of the Mup input \214le \ +name. If multiple input \214les are listed, the last is used.)144 160.8 +R .71(If none are speci\214ed \(input is read from standard input\), th\ +e name "stdin.ps" will be used for the)144 172.8 R(output \214le.)144 +184.8 Q F1(-m)108 201.6 Q F2(midi\214le)2.5 E F0 .065(Instead of genera\ +ting PostScript output, generate standard MIDI \(Musical Instrument Dig\ +ital Inter)144 213.6 R(-)-.2 E -.1(fa)144 225.6 S +(ce\) output, and put it in).1 E F2(midi\214le)2.5 E F0 5(.T)C +(his option also causes the macro "MIDI" to become de\214ned.)-5 E F1 +(-M)108 242.4 Q F0 .488(This is lik)23.23 F 2.988(et)-.1 G(he)-2.988 E +F1(-m)2.988 E F0 .488(option, e)2.988 F .488 +(xcept the name of the MIDI \214le is deri)-.15 F -.15(ve)-.25 G 2.988 +(df).15 G .488(rom the name of the Mup)-2.988 F .164(input \214le. If t\ +he name of the Mup input \214le ends with a ".mup" suf)144 254.4 R .165 +(\214x, the generated MIDI \214le will)-.25 F .464 +(end with a ".mid" suf)144 266.4 R .464(\214x instead. If the name of t\ +he Mup input \214le ends with a ".MUP" suf)-.25 F .463(\214x, the)-.25 F +.151(MIDI \214le will end with a ".MID" suf)144 278.4 R 2.651 +(\214x. Otherwise,)-.25 F 2.651(a")2.651 G .151(.mid" suf)-2.651 F .151 +(\214x will be appended to the end of)-.25 F 1.045(the Mup input \214le\ + name. If multiple input \214les are listed, the last is used.)144 290.4 +R 1.045(If none are speci\214ed)6.045 F(\(input is read from standard i\ +nput\), the name "stdin.mid" will be used for the MIDI \214le.)144 302.4 +Q F1(-o)108 319.2 Q F2(pa)2.5 E -.1(ge)-.1 G(list).1 E F0 .723 +(Print only the pages gi)144 331.2 R -.15(ve)-.25 G 3.223(ni).15 G(n) +-3.223 E F2(pa)3.223 E -.1(ge)-.1 G(list).1 E F0 3.223(.T)C(he)-3.223 E +F2(pa)3.223 E -.1(ge)-.1 G(list).1 E F0 .723 +(can be a comma-separated list of numbers or)3.223 F .069 +(ranges, where a range is tw)144 343.2 R 2.569(on)-.1 G .069 +(umbers separated by a dash. F)-2.569 F .068(or e)-.15 F .068 +(xample, -o1,7-9,12-14 w)-.15 F .068(ould print)-.1 F 1.194 +(pages 1, 7, 8, 9, 12, 13, and 14. P)144 355.2 R 1.194 +(ages will be printed in the order gi)-.15 F -.15(ve)-.25 G 3.695 +(n. The).15 F 3.695(yn)-.15 G 1.195(eed not be in)-3.695 F(order)144 +367.2 Q 3.48(,a)-.4 G .98 +(nd a page number may be included more than once.)-3.48 F(Alternately) +5.979 E 3.479(,t)-.65 G(he)-3.479 E F2(pa)3.479 E -.1(ge)-.1 G(list).1 E +F0 .979(can be the)3.479 F .664(special k)144 379.2 R -.15(ey)-.1 G -.1 +(wo).15 G .664(rd "odd" or "e).1 F -.15(ve)-.25 G .664 +(n" which will cause all odd or e).15 F -.15(ve)-.25 G 3.165(nn).15 G +.665(umbered pages to be printed.)-3.165 F .202 +(This may be useful if you ha)144 391.2 R .502 -.15(ve a p)-.2 H .202 +(rinter that only mak).15 F .201(es single-sided copies, b)-.1 F .201 +(ut you wish to print)-.2 F .335(Mup output double-sided. Y)144 403.2 R +.335(ou could print odd-numbered pages, then turn the paper o)-1.1 F +-.15(ve)-.15 G 2.835(ra).15 G .335(nd feed)-2.835 F +(the pages through ag)144 415.2 Q(ain for the e)-.05 E -.15(ve)-.25 G +(n-numbered pages.).15 E F1(-p)108 432 Q F2(N)A F0 .245 +(Start numbering pages at)20.44 F F2(N)2.745 E F0 .245(instead of at 1.) +2.745 F(If)5.245 E F1(-o)2.745 E F0(and)2.745 E F1(-p)2.745 E F0 .245 +(are used together)2.745 F 2.744(,t)-.4 G .244(he page numbers gi)-2.744 +F -.15(ve)-.25 G(n).15 E .152(in the)144 444 R F1(-o)2.652 E F2(pa)A -.1 +(ge)-.1 G(list).1 E F0 .153(must be the printed page numbers. F)2.652 F +.153(or e)-.15 F .153(xample, if you use -p10 and w)-.15 F .153 +(ant to print)-.1 F(just the second page, you w)144 456 Q +(ould need to specify -o11.)-.1 E F1(-r)108 472.8 Q F0(Print a cop)28.23 +E 2.5(yo)-.1 G 2.5(ft)-2.5 G(he Mup share)-2.5 E -.1(wa)-.25 G(re re).1 +E(gistration form to the standard output.)-.15 E F1(-s)108 489.6 Q F2 +(staf)A(\215ist)-.18 E F0 .299(Only print the staf)144 501.6 R .298 +(fs that are included in)-.25 F F2(staf)2.798 E(\215ist)-.18 E F0 2.798 +(.T)C .298(his can be a comma-separated list of staf)-2.798 F 2.798(fn) +-.25 G(um-)-2.798 E .974(bers or ranges, such as "1,5" or "1-3,7-8" T) +144 513.6 R 3.474(of)-.8 G .974(urther restrict to a single v)-3.474 F +.975(oice on a staf)-.2 F .975(f, add)-.25 F F1(v)3.475 E F2(N)A F0 +(where)144 525.6 Q F2(N)2.828 E F0 .328(is the v)2.828 F .327 +(oice number \(1, 2, or 3\), after the staf)-.2 F .327 +(f, as in "2v1,5v2" Y)-.25 F .327(ou can')-1.1 F 2.827(ts)-.18 G .327 +(pecify a list or)-2.827 F 1.151(range for v)144 537.6 R 1.151 +(oices; if you only w)-.2 F 1.151(ant to mak)-.1 F 3.651(et)-.1 G 1.351 +-.1(wo o)-3.651 H 1.151(ut of three v).1 F 1.151(oices visible, you ha) +-.2 F 1.452 -.15(ve t)-.2 H 3.652(os).15 G(pecify)-3.652 E +(them separately)144 549.6 Q 2.5(,l)-.65 G(ik)-2.5 E 2.5(e")-.1 G 2.5 +(1v2,1v3". No)-2.5 F(spaces are allo)2.5 E(wed in the list.)-.25 E F1 +(-v)108 566.4 Q F0(Print the Mup v)27.67 E(ersion number and e)-.15 E +(xit. This manual page is for v)-.15 E(ersion 5.3.)-.15 E F1(-x)108 +583.2 Q F2(M,N)A F0 .565(Extract measures)10.17 F F2(M)3.065 E F0 +(through)3.065 E F2(N)3.065 E F0 .565(of the song. This allo)3.065 F +.565(ws you to print or play a part of a song. The)-.25 F .41 +(comma and second v)144 595.2 R .41 +(alue are optional; if not speci\214ed, the def)-.25 F .411 +(ault is to go to the end of the piece.)-.1 F(Positi)144 607.2 Q 1.409 +-.15(ve v)-.25 H 1.109(alues specify the number of measures from the be) +-.1 F 1.108(ginning of the piece, while ne)-.15 F -.05(ga)-.15 G(ti).05 +E -.15(ve)-.25 G -.25(va)144 619.2 S .775(lues are relati).25 F 1.075 +-.15(ve t)-.25 H 3.275(ot).15 G .775 +(he end, with -1 referring to the last measure of the song.)-3.275 F +.775(So -x1,-1 means)5.775 F .336(the entire song, if the song doesn') +144 631.2 R 2.836(th)-.18 G -2.25 -.2(av e)-2.836 H 2.836(ap)3.036 G +.336(ickup measure.)-2.836 F .336 +(If the song has a pickup measure, that)5.336 F .08 +(is speci\214ed by 0.)144 643.2 R .08 +(So for a song with a pickup, -x0,-1 w)5.08 F .08 +(ould mean the entire song, and -x0,0 w)-.1 F(ould)-.1 E 1.433 +(mean just the pickup measure.)144 655.2 R 1.433(As other e)6.433 F +1.432(xamples, -x-1,-1 means just the \214nal measure of the)-.15 F .226 +(song, -x2 means starting after the \214rst full measure, -x3,4 means o\ +nly measures 3 and 4, and -x6,6)144 667.2 R .126(means just measure 6.) +144 679.2 R .125(The starting measure is not allo)5.126 F .125 +(wed to be inside an ending.)-.25 F 2.625(Ac)5.125 G .125(ommon use) +-2.625 F .363 +(for this option might be to generate a MIDI \214le for just a fe)144 +691.2 R 2.863(wm)-.25 G .363(easures. F)-2.863 F .363(or e)-.15 F .364 +(xample, if you were)-.15 F .089(trying to tweak tempo v)144 703.2 R +.088(alues for a ritard in the last 2 measures of a song, you could use\ + -x-2 to lis-)-.25 F(ten to just those measures.)144 715.2 Q +(Arkkra Enterprises)72 768 Q(Sep 25, 2006)131.94 E(2)202.75 E EP +%%Page: 3 3 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 406.62(mup\(1\) mup\(1\))72 48 R .448 +(The options, if an)108 84 R 1.748 -.65(y, c)-.15 H .448(an be follo).65 +F .448(wed by one or more)-.25 F/F1 10/Times-Italic@0 SF(\214les)2.948 E +F0 .448(in Mup format.)2.948 F .448(If no)5.448 F F1(\214les)2.948 E F0 +.448(are speci\214ed, standard)2.948 F .092(input is read.)108 96 R .092 +(If se)5.092 F -.15(ve)-.25 G(ral).15 E F1(\214les)2.592 E F0 .092 +(are listed, the)2.592 F 2.592(ya)-.15 G .092(re ef)-2.592 F(fecti)-.25 +E -.15(ve)-.25 G .091 +(ly concatenated together and treated as one big \214le.).15 F .99(Sinc\ +e there are some things \(such as header and footer\) that are only all\ +o)108 108 R .991(wed to occur once, if you ha)-.25 F -.15(ve)-.2 G(se) +108 120 Q -.15(ve)-.25 G .777 +(ral independent pieces, mup should be called on each indi).15 F .777 +(vidually rather than trying to print them all)-.25 F .054 +(with one command.)108 132 R .054(If a speci\214ed \214le does not e) +5.054 F .054(xist, and its name does not already end with .mup or .MUP) +-.15 F(,)-1.11 E(then Mup will append .mup to the speci\214ed name and \ +attempt to open that.)108 144 Q 1.096(On most systems, the en)108 160.8 +R 1.096(vironment v)-.4 F 1.096(ariable MUPP)-.25 F -1.11(AT)-.92 G +3.596(Hc)1.11 G 1.096(an be set to a list of paths in which to look for) +-3.596 F .13('include' \214les.)108 172.8 R .13(The components are sepa\ +rated by a colon on Unix or Linux systems, and by a semicolon on)5.13 F +(systems with DOS-lik)108 184.8 Q 2.5<658c>-.1 G(le naming con)-2.5 E +-.15(ve)-.4 G(ntions.).15 E -.15(Fo)108 201.6 S 2.672(rm).15 G .172 +(ore deb)-2.672 F .171(ugging, in addition to the -d option, if the en) +-.2 F .171(vironment v)-.4 F .171(ariable MUP_BB is set to "bcfghnsu") +-.25 F .355(or an)108 213.6 R 2.855(ys)-.15 G .356(ubset of those lette\ +rs, the generated output will include "bounding box)-2.855 F .356 +(es" for the things Mup inter)-.15 F(-)-.2 E .465(nally calls bars \(b\ +\), chords \(c\), feeds \(f\), grpsyls \(g\), header/footer and top/bot\ +tom \(h\), notes \(n\), staf)108 225.6 R .465(fs \(s\),)-.25 F .367 +(and stuf)108 237.6 R 2.867(f\()-.25 G 2.867(u\). While)-2.867 F .367 +(this is intended for use in deb)2.867 F .368 +(ugging Mup itself, it may also help you understand wh)-.2 F(y)-.05 E +.315(Mup places things the w)108 249.6 R .315 +(ay it does, since in general, Mup only allo)-.1 F .314(ws bounding box) +-.25 F .314(es to o)-.15 F -.15(ve)-.15 G .314(rlap according).15 F +(to speci\214c rules. If vie)108 261.6 Q +(wed with a color PostScript vie)-.25 E(wer \(not mupdisp\), these box) +-.25 E(es will be in color)-.15 E(.)-.55 E/F2 10.95/Times-Bold@0 SF +(SEE ALSO)72 278.4 Q F0 +(gs\(1\), mkmupfnt\(1\), mupdisp\(1\), mupmate\(1\), mupprnt\(1\).)108 +290.4 Q(Mup \212 Music Publisher User')108 302.4 Q 2.5(sG)-.55 G(uide) +-2.5 E(Arkkra Enterprises)72 768 Q(Sep 25, 2006)131.94 E(3)202.75 E EP +%%Trailer +end +%%EOF diff --git a/mup/docs/mupdisp.1 b/mup/docs/mupdisp.1 new file mode 100644 index 0000000..1be9165 --- /dev/null +++ b/mup/docs/mupdisp.1 @@ -0,0 +1,127 @@ +.TH mupdisp 1 "November 4, 2006" "Arkkra Enterprises" +.SH NAME +.PP +mupdisp - display output from Mup music publisher program +.SH SYNOPSIS +.PP +mupdisp \fI[mup_options] file\fP +.SH DESCRIPTION +.PP +Mupdisp provides a way to view Mup output on your screen. +The \fIfile\fP is Mup input. Any other Mup options can be given, +except -f, -m, -M, -r, or -v, which don't produce print output. +.PP +Mupdisp will run under MS-DOS or will run under +UNIX with a TERM of AT386, linux, or xterm (under X windows). +.PP +When running under X windows, several standard X options are +available: +.TP +\fB-geometry\fP \fIXxY+M+N\fP +Sets the window size and/or location on the screen. The actual window +width will be determined by the width of the Mup output. The height +will be adjusted if necessary to be between 400 and the actual height +of the Mup output. The window placment specifications can be positive +or negative. The actual placement may be adjusted by your window manager. +.TP +\fB-fg\fP \fIcolor\fP or \fB-foreground\fP \fIcolor\fP +Specifies the foreground color to use. +.TP +\fB-bg\fP \fIcolor\fP or \fB-background\fP \fIcolor\fP +Specifies the background color to use. +.PP +These X options can also be set in your .Xdefaults file using resource names of +mupdisp.geometry, mupdisp.foreground, and mupdisp.background. Command +line arguments will override values in the .Xdefaults file. +As an example, you could add these lines to your .Xdefaults file: +.nf +.na +.ft CW +.in +1i + +mupdisp.foreground: navy +mupdisp.background: gray +mupdisp.geometry: 400x760+100-34 + +.in -1i +.ft P +.fi +.ad +.PP +The Mupdisp program begins in partial page mode, +which displays output at approximately actual size (depending +on the size of your monitor). In this mode, most likely +not all of the page fits on the +screen, so the scrolling commands can be used to move up and down to view +different parts of the page. In full page mode, a small version of the +entire page is displayed. This is useful +for seeing overall page layout, but is generally too small to see much detail. +This mode is now somewhat of a relic of the days when screens were typically +much smaller than they are today, and is thus becoming less useful. +.PP +If the environment variable MUPDISPMODE is set to some value, +Mupdisp will start in full page rather than partial page mode. +.PP +The commands are: +.TP +\fInum\fP +Go to page number \fInum\fP. +.TP ++ or or or +move forward on the page by about 1/8 of an inch +(partial page mode only) +.TP +- or or or +move backward on the page by about 1/8 of an inch +(partial page mode only) +.TP +b or or or +move backward on the page by about an inch +(partial page mode only) +.TP +f or or or or +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 +go to next page +.TP +p or +go to previous page +.TP +q or ZZ +quit +.TP +r +Repaint the page (useful for exiting help page) +.PP +When in X windows, the mouse can be used for scrolling. The left button scrolls +downward like the f command, while the right button scrolls backwards like +the b command. +.PP +Mupdisp supports page sizes of letter (8.5 x 11.0 inches), +note (7.5 x 10.0 inches), legal (8.5 x 14.0 inches), +A4 (8.26 x 11.69 inches), A5 (5.85 x 8.26 inches), +A6 (4.125 x 5.85 inches), flsa (8.5 x 13.0 inches), and +halfletter (5.5 x 8.5 inches). +.SH FILES +.P +$HOME/.Xdefaults default X window resource definitions +.SH "SEE ALSO" +.PP +gs(1), mup(1), mupmate(1), mupprnt(1). +.br +Mup \(em Music Publisher User's Guide +.SH "CAVEATS AND BUGS" +.PP +You must have mup in your PATH. +You must have ghostscript (gs or gs386.exe) in your PATH +and it must be built to include the "bit" device. +.PP +Resizing the window does not resize the full page view. diff --git a/mup/docs/mupdisp.ps b/mup/docs/mupdisp.ps new file mode 100644 index 0000000..fe483c7 --- /dev/null +++ b/mup/docs/mupdisp.ps @@ -0,0 +1,326 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.17.2 +%%CreationDate: Sat Dec 9 16:59:22 2006 +%%DocumentNeededResources: font Times-Roman +%%+ font Times-Bold +%%+ font Times-Italic +%%+ font Courier +%%DocumentSuppliedResources: procset grops 1.17 2 +%%Pages: 2 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +%%BeginResource: procset grops 1.17 2 +/setpacking where{ +pop +currentpacking +true setpacking +}if +/grops 120 dict dup begin +/SC 32 def +/A/show load def +/B{0 SC 3 -1 roll widthshow}bind def +/C{0 exch ashow}bind def +/D{0 exch 0 SC 5 2 roll awidthshow}bind def +/E{0 rmoveto show}bind def +/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def +/G{0 rmoveto 0 exch ashow}bind def +/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/I{0 exch rmoveto show}bind def +/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def +/K{0 exch rmoveto 0 exch ashow}bind def +/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/M{rmoveto show}bind def +/N{rmoveto 0 SC 3 -1 roll widthshow}bind def +/O{rmoveto 0 exch ashow}bind def +/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/Q{moveto show}bind def +/R{moveto 0 SC 3 -1 roll widthshow}bind def +/S{moveto 0 exch ashow}bind def +/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/SF{ +findfont exch +[exch dup 0 exch 0 exch neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/MF{ +findfont +[5 2 roll +0 3 1 roll +neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def +/MANUAL{ +statusdict begin/manualfeed true store end +}bind def +/PLG{ +gsave newpath clippath pathbbox grestore +exch pop add exch pop +}bind def +/BP{ +/level0 save def +1 setlinecap +1 setlinejoin +72 RES div dup scale +LS{ +90 rotate +}{ +0 PL translate +}ifelse +1 -1 scale +}bind def +/EP{ +level0 restore +showpage +}bind def +/DA{ +newpath arcn stroke +}bind def +/SN{ +transform +.25 sub exch .25 sub exch +round .25 add exch round .25 add exch +itransform +}bind def +/DL{ +SN +moveto +SN +lineto stroke +}bind def +/DC{ +newpath 0 360 arc closepath +}bind def +/TM matrix def +/DE{ +TM currentmatrix pop +translate scale newpath 0 0 .5 0 360 arc closepath +TM setmatrix +}bind def +/RC/rcurveto load def +/RL/rlineto load def +/ST/stroke load def +/MT/moveto load def +/CL/closepath load def +/FL{ +currentgray exch setgray fill setgray +}bind def +/BL/fill load def +/LW/setlinewidth load def +/RE{ +findfont +dup maxlength 1 index/FontName known not{1 add}if dict begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +/Encoding exch def +dup/FontName exch def +currentdict end definefont pop +}bind def +/DEFS 0 def +/EBEGIN{ +moveto +DEFS begin +}bind def +/EEND/end load def +/CNT 0 def +/level1 0 def +/PBEGIN{ +/level1 save def +translate +div 3 1 roll div exch scale +neg exch neg exch translate +0 setgray +0 setlinecap +1 setlinewidth +0 setlinejoin +10 setmiterlimit +[]0 setdash +/setstrokeadjust where{ +pop +false setstrokeadjust +}if +/setoverprint where{ +pop +false setoverprint +}if +newpath +/CNT countdictstack def +userdict begin +/showpage{}def +}bind def +/PEND{ +clear +countdictstack CNT sub{end}repeat +level1 restore +}bind def +end def +/setpacking where{ +pop +setpacking +}if +%%EndResource +%%IncludeResource: font Times-Roman +%%IncludeResource: font Times-Bold +%%IncludeResource: font Times-Italic +%%IncludeResource: font Courier +grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 +def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron +/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent +/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen +/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon +/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O +/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex +/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y +/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft +/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl +/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen +/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft +/logicalnot/minus/registered/macron/degree/plusminus/twosuperior +/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior +/ordmasculine/guilsinglright/onequarter/onehalf/threequarters +/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE +/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex +/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn +/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla +/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis +/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash +/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def +/Courier@0 ENC0/Courier RE/Times-Italic@0 ENC0/Times-Italic RE +/Times-Bold@0 ENC0/Times-Bold RE/Times-Roman@0 ENC0/Times-Roman RE +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 373.28(mupdisp\(1\) mupdisp\(1\))72 48 R/F1 +10.95/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0 +(mupdisp - display output from Mup music publisher program)108 96 Q F1 +(SYNOPSIS)72 112.8 Q F0(mupdisp)108 124.8 Q/F2 10/Times-Italic@0 SF +([mup_options] \214le)2.5 E F1(DESCRIPTION)72 141.6 Q F0 .054 +(Mupdisp pro)108 153.6 R .054(vides a w)-.15 F .053(ay to vie)-.1 F +2.553(wM)-.25 G .053(up output on your screen.)-2.553 F(The)5.053 E F2 +(\214le)2.553 E F0 .053(is Mup input. An)2.553 F 2.553(yo)-.15 G .053 +(ther Mup options)-2.553 F(can be gi)108 165.6 Q -.15(ve)-.25 G(n, e).15 +E(xcept -f, -m, -M, -r)-.15 E 2.5(,o)-.4 G 2.5(r-)-2.5 G 1.3 -.65(v, w) +-2.5 H(hich don').65 E 2.5(tp)-.18 G(roduce print output.)-2.5 E .453 +(Mupdisp will run under MS-DOS or will run under UNIX with a TERM of A) +108 182.4 R .453(T386, linux, or xterm \(under)-1.11 F 2.5(Xw)108 194.4 +S(indo)-2.5 E(ws\).)-.25 E(When running under X windo)108 211.2 Q +(ws, se)-.25 E -.15(ve)-.25 G(ral standard X options are a).15 E -.25 +(va)-.2 G(ilable:).25 E/F3 10/Times-Bold@0 SF(-geometry)108 228 Q F2 +(XxY+M+N)2.5 E F0 .66(Sets the windo)144 240 R 3.16(ws)-.25 G .659 +(ize and/or location on the screen. The actual windo)-3.16 F 3.159(ww) +-.25 G .659(idth will be determined)-3.159 F .814(by the width of the M\ +up output. The height will be adjusted if necessary to be between 400 a\ +nd)144 252 R .716(the actual height of the Mup output. The windo)144 264 +R 3.216(wp)-.25 G .716(lacment speci\214cations can be positi)-3.216 F +1.016 -.15(ve o)-.25 H 3.216(rn).15 G -.15(eg)-3.216 G(-).15 E(ati)144 +276 Q -.15(ve)-.25 G 2.5(.T).15 G +(he actual placement may be adjusted by your windo)-2.5 E 2.5(wm)-.25 G +(anager)-2.5 E(.)-.55 E F3(-fg)108 292.8 Q F2(color)2.5 E F0(or)2.5 E F3 +(-f)2.5 E(or)-.25 E(egr)-.18 E(ound)-.18 E F2(color)2.5 E F0 +(Speci\214es the fore)144 304.8 Q(ground color to use.)-.15 E F3(-bg)108 +321.6 Q F2(color)2.5 E F0(or)2.5 E F3(-backgr)2.5 E(ound)-.18 E F2 +(color)2.5 E F0(Speci\214es the background color to use.)144 333.6 Q +2.483(These X options can also be set in your .Xdef)108 350.4 R 2.484 +(aults \214le using resource names of mupdisp.geometry)-.1 F(,)-.65 E +(mupdisp.fore)108 362.4 Q .468 +(ground, and mupdisp.background. Command line ar)-.15 F .468 +(guments will o)-.18 F -.15(ve)-.15 G .468(rride v).15 F .468 +(alues in the .Xde-)-.25 F -.1(fa)108 374.4 S(ults \214le.).1 E(As an e) +5 E(xample, you could add these lines to your .Xdef)-.15 E +(aults \214le:)-.1 E/F4 10/Courier@0 SF 12(mupdisp.foreground: navy)180 +398.4 R 12(mupdisp.background: gray)180 410.4 R 24 +(mupdisp.geometry: 400x760+100-34)180 422.4 R F0 1.565 +(The Mupdisp program be)108 451.2 R 1.566(gins in partial page mode, wh\ +ich displays output at approximately actual size)-.15 F .446 +(\(depending on the size of your monitor\). In this mode, most lik)108 +463.2 R .445(ely not all of the page \214ts on the screen, so)-.1 F .503 +(the scrolling commands can be used to mo)108 475.2 R .803 -.15(ve u) +-.15 H 3.003(pa).15 G .503(nd do)-3.003 F .504(wn to vie)-.25 F 3.004 +(wd)-.25 G(if)-3.004 E .504(ferent parts of the page. In full page)-.25 +F .684(mode, a small v)108 487.2 R .683 +(ersion of the entire page is displayed.)-.15 F .683 +(This is useful for seeing o)5.683 F -.15(ve)-.15 G .683 +(rall page layout, b).15 F .683(ut is)-.2 F .968 +(generally too small to see much detail.)108 499.2 R .968 +(This mode is no)5.968 F 3.468(ws)-.25 G(ome)-3.468 E .969 +(what of a relic of the days when screens)-.25 F +(were typically much smaller than the)108 511.2 Q 2.5(ya)-.15 G +(re today)-2.5 E 2.5(,a)-.65 G(nd is thus becoming less useful.)-2.5 E +.965(If the en)108 528 R .965(vironment v)-.4 F .965 +(ariable MUPDISPMODE is set to some v)-.25 F .965 +(alue, Mupdisp will start in full page rather)-.25 F +(than partial page mode.)108 540 Q(The commands are:)108 556.8 Q F2(num) +108 573.6 Q F0()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 or )-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 or )-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 or ).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 or or ).15 E(mo)144 700.8 Q .3 -.15(ve f)-.15 H(orw).15 +E(ard on the page by about an inch \(partial page mode only\))-.1 E 2.5 +(ho)108 717.6 S 5.73 2.5(r? d)-2.5 H(isplay help screen)-2.5 E +(Arkkra Enterprises)72 768 Q(No)120.985 E -.15(ve)-.15 G(mber 4, 2006) +.15 E(1)191.795 E EP +%%Page: 2 2 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 373.28(mupdisp\(1\) mupdisp\(1\))72 48 R 28.22 +(mt)108 84 S(oggle between partial page and full page modes.)-28.22 E +2.5(no)108 100.8 S 2.5(r<)-2.5 G -.15(Pa)-2.5 G(geDo).15 E(wn>)-.25 E +(go to ne)144 112.8 Q(xt page)-.15 E 2.5(po)108 129.6 S 2.5(r<)-2.5 G +-.15(Pa)-2.5 G(geUp>).15 E(go to pre)144 141.6 Q(vious page)-.25 E 2.5 +(qo)108 158.4 S 2.5(rZ)-2.5 G 5.45(Zq)-2.5 G(uit)-5.45 E 32.67(rR)108 +175.2 S(epaint the page \(useful for e)-32.67 E(xiting help page\))-.15 +E .258(When in X windo)108 192 R .258 +(ws, the mouse can be used for scrolling. The left b)-.25 F .259 +(utton scrolls do)-.2 F(wnw)-.25 E .259(ard lik)-.1 F 2.759(et)-.1 G +.259(he f com-)-2.759 F(mand, while the right b)108 204 Q +(utton scrolls backw)-.2 E(ards lik)-.1 E 2.5(et)-.1 G(he b command.) +-2.5 E .119(Mupdisp supports page sizes of letter \(8.5 x 11.0 inches\)\ +, note \(7.5 x 10.0 inches\), le)108 220.8 R -.05(ga)-.15 G 2.619(l\() +.05 G .119(8.5 x 14.0 inches\),)-2.619 F .658(A4 \(8.26 x 11.69 inches\ +\), A5 \(5.85 x 8.26 inches\), A6 \(4.125 x 5.85 inches\), \215sa \(8.5\ + x 13.0 inches\), and)108 232.8 R(hal\215etter \(5.5 x 8.5 inches\).)108 +244.8 Q/F1 10.95/Times-Bold@0 SF(FILES)72 261.6 Q F0($HOME/.Xdef)108 +273.6 Q 5(aults def)-.1 F(ault X windo)-.1 E 2.5(wr)-.25 G +(esource de\214nitions)-2.5 E F1(SEE ALSO)72 290.4 Q F0 +(gs\(1\), mup\(1\), mupmate\(1\), mupprnt\(1\).)108 302.4 Q +(Mup \212 Music Publisher User')108 314.4 Q 2.5(sG)-.55 G(uide)-2.5 E F1 +(CA)72 331.2 Q(VEA)-1.588 E(TS AND B)-1.04 E(UGS)-.11 E F0 -1.1(Yo)108 +343.2 S 2.814(um)1.1 G .314(ust ha)-2.814 F .614 -.15(ve m)-.2 H .313 +(up in your P).15 F -1.11(AT)-.92 G 2.813(H. Y)1.11 F .313(ou must ha) +-1.1 F .613 -.15(ve g)-.2 H .313(hostscript \(gs or gs386.e).15 F -.15 +(xe)-.15 G 2.813(\)i).15 G 2.813(ny)-2.813 G .313(our P)-2.813 F -1.11 +(AT)-.92 G 2.813(Ha)1.11 G .313(nd it must)-2.813 F(be b)108 355.2 Q +(uilt to include the "bit" de)-.2 E(vice.)-.25 E(Resizing the windo)108 +372 Q 2.5(wd)-.25 G(oes not resize the full page vie)-2.5 E -.65(w.)-.25 +G(Arkkra Enterprises)72 768 Q(No)120.985 E -.15(ve)-.15 G(mber 4, 2006) +.15 E(2)191.795 E EP +%%Trailer +end +%%EOF diff --git a/mup/docs/mupfeat.txt b/mup/docs/mupfeat.txt new file mode 100644 index 0000000..6e22a1e --- /dev/null +++ b/mup/docs/mupfeat.txt @@ -0,0 +1,115 @@ + + Mup - Music Publication Program Highlights + + 1. The Mup Music Publication program + + Mup is a shareware music publication program. Mup Version + 5.3 is now available in source form as well as ready-to-run + for MS-DOS/Windows and Linux x86. There is also a Mac + version available. + + Music is described by a text file that you can create using + your favorite editor or the included Mupmate program. Mup + then determines how to lay out the music, and generates + PostScript output for displaying or printing it. It is a + powerful and flexible program, which has been used on + thousands of songs in a wide variety of styles, both + instrumental and vocal. + + Mup's features include: + + - Up to 40 staffs, which can include 1-line, 5-line, and + tablature staffs. Output can be restricted to any + subset of the staffs. Different staffs can be + different sizes. + + - Up to 3 independent voices per staff, up to 70 + simultaneous notes per voice. + + - Double whole to 256th notes, with any number of dots. + Tuplets. + + - Note styles of normal, grace, cue, X, diamond, plus + shaped notes. Optional parentheses around notes and/or + accidentals. + + - Cross-staff stems. + + - Time signatures of cut, common, or numerators from 1 to + 99 and denominators from 1 to 64. Complicated time + signatures, including numerators with two or more + numbers added together, or two or more fractions added + together, or alternating time signatures. + + - All standard clefs, including treble, treble8, 8treble, + French violin, soprano, mezzosoprano, alto, tenor, + baritone, and bass, as well as the drum (neutral) clef. + Clefs can be changed in the middle of measures. + + - Barline styles of single, double, dashed, dotted, end, + repeats, or none. + + - 8th note and shorter notes can have either flags or + beams; beams can be cross-staff. + + - Guitar grids + + - Lyrics can be placed above, below, or between staffs. + Unlimited number of verses, with control of font and + size. + + - Headers and footers. + + - Staffs can be grouped with braces or brackets. + + - Automatic transposition of music and chord marks per + staff. + + - First and subsequent endings. + + - Optional rehearsal marks and/or automatic measure + numbering. Rehearsal marks can be boxed, circled, or + plain. + + - Crescendo/decrescendo marks. + + - Rolls, ornaments, fermatas, accents. + + - Measure repeats. + + - Ties, slurs, phrase marks, octave marks, piano pedal + marks, etc. Ties, slurs, and phrase marks can be + solid, dotted, or dashed. + + - Suport for figured bass, analysis, and chords. + + - Optional MIDI file output. (Very useful for "proof- + listening" to your songs to check for input mistakes!) + + - PostScript output for printing on any PostScript + compatible output device. Can be used with + Ghostscript. + + - All standard PostScript fonts supported, in 1 to 100 + point size, including most common non-English + characters. + + - Input is a text file, for easy portability between + computer systems. + + - Macros and 'include' files. + + - General 'if' clauses that can be used to generate + different outputs based on values of parameters. + + - Mup will determine how to lay out the music, but there + are numerous user controls available to fine-tune the + output to meet your specific needs. + + - Comprehensive User's Guide provided in both PostScript + and HTML formats, including many examples. + + - Mup is available via ftp to try out for free. If you + like it and want to keep it, the shareware registration + is far lower than the cost of most music publication + software. diff --git a/mup/docs/mupmate.1 b/mup/docs/mupmate.1 new file mode 100644 index 0000000..b9239cd --- /dev/null +++ b/mup/docs/mupmate.1 @@ -0,0 +1,69 @@ +.TH mupmate 1 "November 4, 2006" "Arkkra Enterprises" +.SH NAME +.PP +mupmate - user interface for Mup music publisher +.SH SYNOPSIS +.PP +mupmate [\fIfile\fP] +.SH DESCRIPTION +.PP +.P +You can create a Mup file using any ordinary text editor. +On Windows, Notepad is a typical choice; on Linux, editors like +vim and emacs are commonly used. But if you prefer to be able to +edit, display, and play from a single integrated and more graphical +interface, a helper program called "mupmate" is provided. Mupmate is currently +only supported on Windows and Linux. However, since the source code is +available, and it is based on the cross-platform FLTK toolkit, it +can probably be made to run on any system supported by FLTK fairly easily. +If you prefer to use the Mup program directly rather than via mupmate, +you can. The Mupmate program just helps lead you through some of the steps. +.PP +Once you have installed Mup and Mupmate on Windows, double clicking +a .mup file in Windows explorer will run Mupmate on that file. +Or, you can run Mupmate by going to the Start menu, and choosing +Programs, then Arkkra, and then Mupmate. If you would like an icon +on the desktop, you can create one by right clicking +the Mupmate choice in the Arkkra menu, +choosing "copy", right clicking somewhere on the desktop, and choosing "paste." +.PP +On Linux, you can just type the mupmate command, +optionally followed by the name of a Mup input file. +Or you can add mupmate to your favorite window manager's menus. +.P +Mupmate provides five top level menus: File, Edit, Run, Config, and Help. +The File menu provides commands for opening new files and saving the +file you are working on, as well as exit the program. The Edit menu +provides the kinds of things you would expect in a editor: commands to find +a pattern, or find and replace; to select text; to copy, cut, and paste; +to go to a specific line; and to undo the previous operation, if you make +a mistake or change you mind. +The Run menu lets you set runtime options, +and then run the Mup program on your input in various +ways. You can either just generate a PostScript or MIDI file, +or display the PostScript or play the MIDI. +The Config menu lets you specify what application program you want +to use to view PostScript files and which you want to use to play MIDI files, +and well as specify locations for other Mup files. Mupmate will try to +find reasonable default values, but you may want to check that they are +what you want, and tweak them if they aren't. +The Config menu also provides a way for you to fill in the Mup registration +form if you wish to send in a paper form rather than registering online +via credit card, as well as a place to entry the registration key you +will receive once you have paid. +The Help menu lets you browse the Mup User's Guide, view some startup hints, +or see the current version number of Mup and Mupmate. +.SH "SEE ALSO" +.PP +gs(1), mup(1). +.br +Mup \(em Music Publisher User's Guide +.SH "CAVEATS" +.PP +Mupmate is currently only supported on Windows and Linux or similar. +.PP +Mupmate does not directly provide a print facility. Almost any PostScript +viewer already provides this ability, so you can simply select "Display" +from the Run menu and use the viewer's print capabilities. +Alternately you can use the "Write PostScript File" from the Run menu +and then print the resulting file. diff --git a/mup/docs/mupmate.ps b/mup/docs/mupmate.ps new file mode 100644 index 0000000..e9bd14a --- /dev/null +++ b/mup/docs/mupmate.ps @@ -0,0 +1,301 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.17.2 +%%CreationDate: Sat Dec 9 16:59:22 2006 +%%DocumentNeededResources: font Times-Roman +%%+ font Times-Bold +%%+ font Times-Italic +%%DocumentSuppliedResources: procset grops 1.17 2 +%%Pages: 1 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +%%BeginResource: procset grops 1.17 2 +/setpacking where{ +pop +currentpacking +true setpacking +}if +/grops 120 dict dup begin +/SC 32 def +/A/show load def +/B{0 SC 3 -1 roll widthshow}bind def +/C{0 exch ashow}bind def +/D{0 exch 0 SC 5 2 roll awidthshow}bind def +/E{0 rmoveto show}bind def +/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def +/G{0 rmoveto 0 exch ashow}bind def +/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/I{0 exch rmoveto show}bind def +/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def +/K{0 exch rmoveto 0 exch ashow}bind def +/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/M{rmoveto show}bind def +/N{rmoveto 0 SC 3 -1 roll widthshow}bind def +/O{rmoveto 0 exch ashow}bind def +/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/Q{moveto show}bind def +/R{moveto 0 SC 3 -1 roll widthshow}bind def +/S{moveto 0 exch ashow}bind def +/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/SF{ +findfont exch +[exch dup 0 exch 0 exch neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/MF{ +findfont +[5 2 roll +0 3 1 roll +neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def +/MANUAL{ +statusdict begin/manualfeed true store end +}bind def +/PLG{ +gsave newpath clippath pathbbox grestore +exch pop add exch pop +}bind def +/BP{ +/level0 save def +1 setlinecap +1 setlinejoin +72 RES div dup scale +LS{ +90 rotate +}{ +0 PL translate +}ifelse +1 -1 scale +}bind def +/EP{ +level0 restore +showpage +}bind def +/DA{ +newpath arcn stroke +}bind def +/SN{ +transform +.25 sub exch .25 sub exch +round .25 add exch round .25 add exch +itransform +}bind def +/DL{ +SN +moveto +SN +lineto stroke +}bind def +/DC{ +newpath 0 360 arc closepath +}bind def +/TM matrix def +/DE{ +TM currentmatrix pop +translate scale newpath 0 0 .5 0 360 arc closepath +TM setmatrix +}bind def +/RC/rcurveto load def +/RL/rlineto load def +/ST/stroke load def +/MT/moveto load def +/CL/closepath load def +/FL{ +currentgray exch setgray fill setgray +}bind def +/BL/fill load def +/LW/setlinewidth load def +/RE{ +findfont +dup maxlength 1 index/FontName known not{1 add}if dict begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +/Encoding exch def +dup/FontName exch def +currentdict end definefont pop +}bind def +/DEFS 0 def +/EBEGIN{ +moveto +DEFS begin +}bind def +/EEND/end load def +/CNT 0 def +/level1 0 def +/PBEGIN{ +/level1 save def +translate +div 3 1 roll div exch scale +neg exch neg exch translate +0 setgray +0 setlinecap +1 setlinewidth +0 setlinejoin +10 setmiterlimit +[]0 setdash +/setstrokeadjust where{ +pop +false setstrokeadjust +}if +/setoverprint where{ +pop +false setoverprint +}if +newpath +/CNT countdictstack def +userdict begin +/showpage{}def +}bind def +/PEND{ +clear +countdictstack CNT sub{end}repeat +level1 restore +}bind def +end def +/setpacking where{ +pop +setpacking +}if +%%EndResource +%%IncludeResource: font Times-Roman +%%IncludeResource: font Times-Bold +%%IncludeResource: font Times-Italic +grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 +def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron +/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent +/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen +/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon +/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O +/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex +/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y +/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft +/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl +/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen +/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft +/logicalnot/minus/registered/macron/degree/plusminus/twosuperior +/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior +/ordmasculine/guilsinglright/onequarter/onehalf/threequarters +/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE +/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex +/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn +/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla +/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis +/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash +/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def +/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE +/Times-Roman@0 ENC0/Times-Roman RE +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 367.74(mupmate\(1\) mupmate\(1\))72 48 R/F1 +10.95/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0 +(mupmate - user interf)108 96 Q(ace for Mup music publisher)-.1 E F1 +(SYNOPSIS)72 112.8 Q F0(mupmate [)108 124.8 Q/F2 10/Times-Italic@0 SF +(\214le)A F0(])A F1(DESCRIPTION)72 141.6 Q F0 -1.1(Yo)108 153.6 S 3.67 +(uc)1.1 G 1.17(an create a Mup \214le using an)-3.67 F 3.67(yo)-.15 G +1.17(rdinary te)-3.67 F 1.17(xt editor)-.15 F 6.17(.O)-.55 G 3.67(nW) +-6.17 G(indo)-4.07 E 1.17(ws, Notepad is a typical choice; on)-.25 F +.084(Linux, editors lik)108 165.6 R 2.584(ev)-.1 G .085(im and emacs ar\ +e commonly used. But if you prefer to be able to edit, display)-2.584 F +2.585(,a)-.65 G .085(nd play)-2.585 F 1.62(from a single inte)108 177.6 +R 1.619(grated and more graphical interf)-.15 F 1.619 +(ace, a helper program called "mupmate" is pro)-.1 F(vided.)-.15 E .466 +(Mupmate is currently only supported on W)108 189.6 R(indo)-.4 E .467 +(ws and Linux. Ho)-.25 F(we)-.25 E -.15(ve)-.25 G 1.267 -.4(r, s).15 H +.467(ince the source code is a).4 F -.25(va)-.2 G(ilable,).25 E .164 +(and it is based on the cross-platform FL)108 201.6 R .164 +(TK toolkit, it can probably be made to run on an)-.92 F 2.663(ys)-.15 G +.163(ystem supported)-2.663 F .98(by FL)108 213.6 R .98(TK f)-.92 F .98 +(airly easily)-.1 F 5.98(.I)-.65 G 3.48(fy)-5.98 G .98(ou prefer to use\ + the Mup program directly rather than via mupmate, you can.)-3.48 F +(The Mupmate program just helps lead you through some of the steps.)108 +225.6 Q .38(Once you ha)108 242.4 R .68 -.15(ve i)-.2 H .38 +(nstalled Mup and Mupmate on W).15 F(indo)-.4 E .379 +(ws, double clicking a .mup \214le in W)-.25 F(indo)-.4 E .379(ws e)-.25 +F(xplorer)-.15 E .902(will run Mupmate on that \214le.)108 254.4 R(Or) +5.902 E 3.402(,y)-.4 G .903 +(ou can run Mupmate by going to the Start menu, and choosing Pro-)-3.402 +F .705(grams, then Arkkra, and then Mupmate.)108 266.4 R .705(If you w) +5.705 F .705(ould lik)-.1 F 3.205(ea)-.1 G 3.205(ni)-3.205 G .704 +(con on the desktop, you can create one by)-3.205 F .598 +(right clicking the Mupmate choice in the Arkkra menu, choosing "cop)108 +278.4 R .598(y", right clicking some)-.1 F .598(where on the)-.25 F +(desktop, and choosing "paste.")108 290.4 Q .512 +(On Linux, you can just type the mupmate command, optionally follo)108 +307.2 R .512(wed by the name of a Mup input \214le.)-.25 F +(Or you can add mupmate to your f)108 319.2 Q -.2(avo)-.1 G(rite windo) +.2 E 2.5(wm)-.25 G(anager')-2.5 E 2.5(sm)-.55 G(enus.)-2.5 E .665 +(Mupmate pro)108 336 R .665(vides \214v)-.15 F 3.165(et)-.15 G .665 +(op le)-3.165 F -.15(ve)-.25 G 3.165(lm).15 G .665 +(enus: File, Edit, Run, Con\214g, and Help.)-3.165 F .665 +(The File menu pro)5.665 F .665(vides com-)-.15 F .555 +(mands for opening ne)108 348 R 3.055<778c>-.25 G .555(les and sa)-3.055 +F .555(ving the \214le you are w)-.2 F .554(orking on, as well as e)-.1 +F .554(xit the program. The Edit)-.15 F .917(menu pro)108 360 R .917 +(vides the kinds of things you w)-.15 F .917(ould e)-.1 F .918 +(xpect in a editor: commands to \214nd a pattern, or \214nd and)-.15 F +.232(replace; to select te)108 372 R .232(xt; to cop)-.15 F 1.532 -.65 +(y, c)-.1 H .232 +(ut, and paste; to go to a speci\214c line; and to undo the pre).65 F +.231(vious operation, if)-.25 F 1.082(you mak)108 384 R 3.582(eam)-.1 G +(istak)-3.582 E 3.582(eo)-.1 G 3.582(rc)-3.582 G 1.082(hange you mind.) +-3.582 F 1.083 +(The Run menu lets you set runtime options, and then run the)6.083 F +.346(Mup program on your input in v)108 396 R .345(arious w)-.25 F .345 +(ays. Y)-.1 F .345 +(ou can either just generate a PostScript or MIDI \214le, or dis-)-1.1 F +1.273(play the PostScript or play the MIDI.)108 408 R 1.273 +(The Con\214g menu lets you specify what application program you)6.273 F +-.1(wa)108 420 S .199(nt to use to vie).1 F 2.698(wP)-.25 G .198 +(ostScript \214les and which you w)-2.698 F .198 +(ant to use to play MIDI \214les, and well as specify loca-)-.1 F .859 +(tions for other Mup \214les. Mupmate will try to \214nd reasonable def) +108 432 R .86(ault v)-.1 F .86(alues, b)-.25 F .86(ut you may w)-.2 F +.86(ant to check)-.1 F .437(that the)108 444 R 2.937(ya)-.15 G .437 +(re what you w)-2.937 F .437(ant, and tweak them if the)-.1 F 2.937(ya) +-.15 G(ren')-2.937 E 2.937(t. The)-.18 F .437(Con\214g menu also pro) +2.937 F .437(vides a w)-.15 F .437(ay for you)-.1 F .95 +(to \214ll in the Mup re)108 456 R .951 +(gistration form if you wish to send in a paper form rather than re)-.15 +F .951(gistering online via)-.15 F .441(credit card,)108 468 R .441 +(as well as a place to entry the re)5.441 F .44(gistration k)-.15 F .74 +-.15(ey y)-.1 H .44(ou will recei).15 F .74 -.15(ve o)-.25 H .44 +(nce you ha).15 F .74 -.15(ve p)-.2 H 2.94(aid. The).15 F(Help)2.94 E +.243(menu lets you bro)108 480 R .243(wse the Mup User')-.25 F 2.743(sG) +-.55 G .243(uide, vie)-2.743 F 2.743(ws)-.25 G .244 +(ome startup hints, or see the current v)-2.743 F .244(ersion number of) +-.15 F(Mup and Mupmate.)108 492 Q F1(SEE ALSO)72 508.8 Q F0 +(gs\(1\), mup\(1\).)108 520.8 Q(Mup \212 Music Publisher User')108 532.8 +Q 2.5(sG)-.55 G(uide)-2.5 E F1(CA)72 549.6 Q(VEA)-1.588 E(TS)-1.04 E F0 +(Mupmate is currently only supported on W)108 561.6 Q(indo)-.4 E +(ws and Linux or similar)-.25 E(.)-.55 E .159 +(Mupmate does not directly pro)108 578.4 R .159(vide a print f)-.15 F +(acility)-.1 E 2.659(.A)-.65 G .159(lmost an)-2.659 F 2.659(yP)-.15 G +.158(ostScript vie)-2.659 F .158(wer already pro)-.25 F .158 +(vides this abil-)-.15 F(ity)108 590.4 Q 3.25(,s)-.65 G 3.25(oy)-3.25 G +.751(ou can simply select "Display" from the Run menu and use the vie) +-3.25 F(wer')-.25 E 3.251(sp)-.55 G .751(rint capabilities.)-3.251 F +(Alter)5.751 E(-)-.2 E(nately you can use the "Write PostScript File" f\ +rom the Run menu and then print the resulting \214le.)108 602.4 Q +(Arkkra Enterprises)72 768 Q(No)120.985 E -.15(ve)-.15 G(mber 4, 2006) +.15 E(1)191.795 E EP +%%Trailer +end +%%EOF diff --git a/mup/docs/mupprnt.1 b/mup/docs/mupprnt.1 new file mode 100644 index 0000000..0a9141c --- /dev/null +++ b/mup/docs/mupprnt.1 @@ -0,0 +1,29 @@ +.TH mupprnt 1 "Oct 27, 1995" "Arkkra Enterprises" +.SH NAME +.PP +mupprnt - print output from Mup music publisher +.SH SYNOPSIS +.PP +mupprnt \fI[mup_options] file\fP +.SH DESCRIPTION +.PP +mupprnt provides a way to print Mup output on your printer. +The \fIfile\fP is Mup input. Any other Mup options can be given, +except -f, -m, -r, or -v, which don't produce print output. +.PP +Under UNIX, if the environment variable COPIES is set to a number, +that number of copies will be printed. Otherwise only 1 copy will be printed. +.PP +.PP +The GS_DEVICE shell variable must be set to the proper value for your printer +type. Mupprnt is a shell script (under UNIX) or batch script (under MS-DOS), +so you can customize it if you wish. +.SH "SEE ALSO" +.PP +gs(1), mup(1), mupdisp(1). +.br +Mup \(em Music Publisher User's Guide +.SH "CAVEATS AND BUGS" +.PP +You must have mup in your PATH. +You must have ghostscript (gs or gs386.exe) in your PATH. diff --git a/mup/docs/mupprnt.ps b/mup/docs/mupprnt.ps new file mode 100644 index 0000000..d33bf40 --- /dev/null +++ b/mup/docs/mupprnt.ps @@ -0,0 +1,236 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.17.2 +%%CreationDate: Sat Dec 9 16:59:22 2006 +%%DocumentNeededResources: font Times-Roman +%%+ font Times-Bold +%%+ font Times-Italic +%%DocumentSuppliedResources: procset grops 1.17 2 +%%Pages: 1 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +%%BeginResource: procset grops 1.17 2 +/setpacking where{ +pop +currentpacking +true setpacking +}if +/grops 120 dict dup begin +/SC 32 def +/A/show load def +/B{0 SC 3 -1 roll widthshow}bind def +/C{0 exch ashow}bind def +/D{0 exch 0 SC 5 2 roll awidthshow}bind def +/E{0 rmoveto show}bind def +/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def +/G{0 rmoveto 0 exch ashow}bind def +/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/I{0 exch rmoveto show}bind def +/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def +/K{0 exch rmoveto 0 exch ashow}bind def +/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/M{rmoveto show}bind def +/N{rmoveto 0 SC 3 -1 roll widthshow}bind def +/O{rmoveto 0 exch ashow}bind def +/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/Q{moveto show}bind def +/R{moveto 0 SC 3 -1 roll widthshow}bind def +/S{moveto 0 exch ashow}bind def +/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/SF{ +findfont exch +[exch dup 0 exch 0 exch neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/MF{ +findfont +[5 2 roll +0 3 1 roll +neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def +/MANUAL{ +statusdict begin/manualfeed true store end +}bind def +/PLG{ +gsave newpath clippath pathbbox grestore +exch pop add exch pop +}bind def +/BP{ +/level0 save def +1 setlinecap +1 setlinejoin +72 RES div dup scale +LS{ +90 rotate +}{ +0 PL translate +}ifelse +1 -1 scale +}bind def +/EP{ +level0 restore +showpage +}bind def +/DA{ +newpath arcn stroke +}bind def +/SN{ +transform +.25 sub exch .25 sub exch +round .25 add exch round .25 add exch +itransform +}bind def +/DL{ +SN +moveto +SN +lineto stroke +}bind def +/DC{ +newpath 0 360 arc closepath +}bind def +/TM matrix def +/DE{ +TM currentmatrix pop +translate scale newpath 0 0 .5 0 360 arc closepath +TM setmatrix +}bind def +/RC/rcurveto load def +/RL/rlineto load def +/ST/stroke load def +/MT/moveto load def +/CL/closepath load def +/FL{ +currentgray exch setgray fill setgray +}bind def +/BL/fill load def +/LW/setlinewidth load def +/RE{ +findfont +dup maxlength 1 index/FontName known not{1 add}if dict begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +/Encoding exch def +dup/FontName exch def +currentdict end definefont pop +}bind def +/DEFS 0 def +/EBEGIN{ +moveto +DEFS begin +}bind def +/EEND/end load def +/CNT 0 def +/level1 0 def +/PBEGIN{ +/level1 save def +translate +div 3 1 roll div exch scale +neg exch neg exch translate +0 setgray +0 setlinecap +1 setlinewidth +0 setlinejoin +10 setmiterlimit +[]0 setdash +/setstrokeadjust where{ +pop +false setstrokeadjust +}if +/setoverprint where{ +pop +false setoverprint +}if +newpath +/CNT countdictstack def +userdict begin +/showpage{}def +}bind def +/PEND{ +clear +countdictstack CNT sub{end}repeat +level1 restore +}bind def +end def +/setpacking where{ +pop +setpacking +}if +%%EndResource +%%IncludeResource: font Times-Roman +%%IncludeResource: font Times-Bold +%%IncludeResource: font Times-Italic +grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 +def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron +/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent +/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen +/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon +/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O +/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex +/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y +/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft +/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl +/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen +/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft +/logicalnot/minus/registered/macron/degree/plusminus/twosuperior +/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior +/ordmasculine/guilsinglright/onequarter/onehalf/threequarters +/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE +/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex +/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn +/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla +/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis +/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash +/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def +/Times-Italic@0 ENC0/Times-Italic RE/Times-Bold@0 ENC0/Times-Bold RE +/Times-Roman@0 ENC0/Times-Roman RE +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 374.4(mupprnt\(1\) mupprnt\(1\))72 48 R/F1 10.95 +/Times-Bold@0 SF -.219(NA)72 84 S(ME).219 E F0 +(mupprnt - print output from Mup music publisher)108 96 Q F1(SYNOPSIS)72 +112.8 Q F0(mupprnt)108 124.8 Q/F2 10/Times-Italic@0 SF +([mup_options] \214le)2.5 E F1(DESCRIPTION)72 141.6 Q F0 .127 +(mupprnt pro)108 153.6 R .127(vides a w)-.15 F .127 +(ay to print Mup output on your printer)-.1 F 5.127(.T)-.55 G(he)-5.127 +E F2(\214le)2.627 E F0 .127(is Mup input. An)2.627 F 2.626(yo)-.15 G +.126(ther Mup options)-2.626 F(can be gi)108 165.6 Q -.15(ve)-.25 G +(n, e).15 E(xcept -f, -m, -r)-.15 E 2.5(,o)-.4 G 2.5(r-)-2.5 G 1.3 -.65 +(v, w)-2.5 H(hich don').65 E 2.5(tp)-.18 G(roduce print output.)-2.5 E +.095(Under UNIX, if the en)108 182.4 R .095(vironment v)-.4 F .095 +(ariable COPIES is set to a number)-.25 F 2.596(,t)-.4 G .096 +(hat number of copies will be printed.)-2.596 F(Otherwise only 1 cop)108 +194.4 Q 2.5(yw)-.1 G(ill be printed.)-2.5 E .822(The GS_DEVICE shell v) +108 216 R .821(ariable must be set to the proper v)-.25 F .821 +(alue for your printer type.)-.25 F .821(Mupprnt is a shell)5.821 F(scr\ +ipt \(under UNIX\) or batch script \(under MS-DOS\), so you can customi\ +ze it if you wish.)108 228 Q F1(SEE ALSO)72 244.8 Q F0 +(gs\(1\), mup\(1\), mupdisp\(1\).)108 256.8 Q +(Mup \212 Music Publisher User')108 268.8 Q 2.5(sG)-.55 G(uide)-2.5 E F1 +(CA)72 285.6 Q(VEA)-1.588 E(TS AND B)-1.04 E(UGS)-.11 E F0 -1.1(Yo)108 +297.6 S 2.5(um)1.1 G(ust ha)-2.5 E .3 -.15(ve m)-.2 H(up in your P).15 E +-1.11(AT)-.92 G 2.5(H. Y)1.11 F(ou must ha)-1.1 E .3 -.15(ve g)-.2 H +(hostscript \(gs or gs386.e).15 E -.15(xe)-.15 G 2.5(\)i).15 G 2.5(ny) +-2.5 G(our P)-2.5 E -1.11(AT)-.92 G(H.)1.11 E(Arkkra Enterprises)72 768 +Q(Oct 27, 1995)132.22 E(1)203.03 E EP +%%Trailer +end +%%EOF diff --git a/mup/docs/mupqref.ps b/mup/docs/mupqref.ps new file mode 100644 index 0000000..e2f1b28 --- /dev/null +++ b/mup/docs/mupqref.ps @@ -0,0 +1,2896 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.17.2 +%%CreationDate: Mon Dec 4 22:55:33 2006 +%%DocumentNeededResources: font Times-Bold +%%+ font Times-Italic +%%+ font Times-Roman +%%+ font Courier +%%+ font Times-BoldItalic +%%+ font NewCenturySchlbk-BoldItalic +%%+ font NewCenturySchlbk-Roman +%%DocumentSuppliedResources: file extlist.ps +%%+ file muschar.ps +%%+ procset grops 1.17 2 +%%Pages: 6 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises +% All rights reserved + +% Mup PostScript Prolog 5.3 for use with Mup 5.3 + +% lwid is used as the width of a standard (thin) line in the music +% character definitions. +/lwid 70 def +/halflwid lwid 2 div def + +% Define the following for use in do_upshortnote, do_dnshortnote, and +% do_shortrest; it has to be done outside of the music font definition. +/utildict 10 dict def +utildict begin + /setnumflags { /numflags exch def } def + /sethooksm1 { /hooksm1 exch def } def + /setoffsets { /offsets exch def } def + /setx { /x exch def } def + /sety { /y exch def } def +end + +% Define a music character font. Each music character is defined as if it +% were a normal ASCII character in a strange font where "A" looks like a +% treble clef, "B" looks like a bass clef, etc. + +/mfont0 100 dict def +mfont0 begin + /FontType 3 def + /FontMatrix [ .001 0 0 0.001 0 0 ] def + /FontBBox [ -2000 -4030 2000 4030 ] def + /FontName (Mfont0) def + + % set up Encoding vector with standard names + /Encoding 256 array def + StandardEncoding Encoding copy + pop + + % the following definitions are used for quarter rests + /topx -170 def /topy 950 def + /cor1x 250 def /cor1y 450 def + /cor2x -300 def /cor2y 200 def + /cor3x 250 def /cor3y -400 def + + % the following definitions are used for double sharps + /limit 300 halflwid add def + /off 70 def + /inbendsmall limit 200 sub def + /inbendbig limit 20 sub def + /outbendsmall 100 def + /outbendbig outbendsmall off add def + + %%%%% define routines that will be used by multiple characters %%%%% + /do_1n { + gsave + newpath -10 rotate 1.6 1 scale + 0 0 325 0 360 arc %outer ellipse + 1 1.6 div 1 scale 10 rotate %back to original + 35 rotate 0.85 1.1 scale + 0 0 275 0 360 arc %inner ellipse + eofill + grestore + } def + /do_upflag { + -315 0 moveto + -300 100 -100 480 0 600 curveto + 300 960 350 1500 200 1700 curveto + 130 1700 lineto + 350 1200 50 650 -315 600 curveto + fill + } def + /do_flat { + -250 -400 moveto %outer edge of loop + 500 0 350 650 -250 160 curveto + -250 160 lwid sub lineto %inner edge of loop + 100 400 300 0 -250 -400 lwid add curveto + fill + + lwid setlinewidth %stem + -250 1100 moveto -250 -400 lineto stroke + } def + /do_diamond { + newpath + 420 0 moveto 0 300 lineto -420 0 lineto + 0 -300 lineto closepath + 259 -29 moveto -41 185 lineto -259 29 lineto + 41 -185 lineto closepath + eofill + } def + /do_2n { + gsave + newpath 25 rotate 1.4 1 scale + 0 0 315 0 360 arc %outer ellipse + 1 1.4 div 1 scale %back to original + 1.3 0.5 scale + 0 0 310 0 360 arc %inner ellipse + eofill + grestore + } def + /do_4n { + gsave + newpath 25 rotate 1.35 1 scale + 0 0 310 0 360 arc fill + grestore + } def + /do_com { + newpath + 330 250 150 0 360 arc fill %knob at upper right + 465 300 moveto %outer boundary + 410 500 200 635 0 635 curveto + -750 635 -750 -635 0 -635 curveto + 350 -635 480 -300 500 -100 curveto + 430 -100 lineto %inner boundary + 380 -300 250 -565 0 -565 curveto + -450 -565 -450 565 0 565 curveto + 200 565 370 350 395 300 curveto + fill + } def + /do_ferm { + 0 0 800 lwid sub 0 180 arc %inner arc + -800 0 lineto + 0 270 lwid sub 800 180 0 arcn %outer arc + 800 0 lineto fill + 0 120 120 0 360 arc fill %the dot + } def + /do_mor { + gsave + 0.7 1 scale %scrunch the following horizontally + 45 rotate %to pretend all lines horz or vertical + 0 1 1 { + pop %we don't need the loop variable + %one half of the mordent + 0 40 moveto 350 40 lineto 350 -460 lineto + 750 -460 lineto 750 -540 lineto + 150 -540 lineto 150 -40 lineto + 0 -40 lineto fill + 180 rotate %to do the other half + } for + grestore + } def + /do_turn { + gsave + 0 1 1 { + pop %we don't need the loop variable + 0 -100 moveto %outer boundary + 200 -400 625 -400 625 0 curveto + 625 200 500 325 300 325 curveto + 300 185 lineto %inner boundary + 450 255 555 150 555 0 curveto + 555 -350 250 -250 0 100 curveto + fill + 300 255 70 0 360 arc fill %knob on end + 180 rotate %to do the other half + } for + grestore + } def + + /do_upshortnote { + utildict begin + setnumflags %set numflags from the stack + gsave + -330 0 translate %half a flag width + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto + 370 2100 numflags 2 sub flagsep mul add lineto stroke + 670 2100 numflags 2 sub flagsep mul add translate + 1 -1 scale %reflect across X axis + 0 1 numflags 1 sub { + do_upflag %do an upflag + pop %we don't need the loop variable + 0 flagsep translate + } for + grestore + end + } def + + /do_dnshortnote { + utildict begin + setnumflags %set numflags from the stack + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto + -370 -2100 numflags 2 sub flagsep mul sub lineto stroke + gsave + -70 -2100 numflags 2 sub flagsep mul sub translate + 0 1 numflags 1 sub { + do_upflag %do an upflag + pop %we don't need the loop variable + 0 flagsep translate + } for + grestore + end + } def + + /do_shortrest { + utildict begin + sety setx setoffsets sethooksm1 %set variable from the stack + gsave + -105.8 offsets mul -600 offsets mul translate + 0 1 hooksm1 { %loop once per hook + newpath + 1 setlinewidth + gsave + 1 1.2 scale + -150 300 1.2 div 140 0 360 arc fill %the dot + grestore + lwid setlinewidth + -50 700 550 255 315 arc %rest of the hook + hooksm1 lt { stroke 105.8 600 translate } if + } for + x y lineto stroke + grestore + end + } def + + + % subsidiary dictionary of character definitions + /CharStrings 128 dict def + CharStrings begin + + /.notdef {} def + + % Here are the definitions of the characters. A stepsize here + % is 300 units (assuming the character is drawn at its default + % size). + + % gclef + /A { + newpath + %start with inner curl, inside boundary + -50 -300 moveto + -450 600 700 700 750 0 curveto + 750 -800 -700 -800 -700 200 curveto + -700 900 500 1400 520 2250 curveto + 520 2900 300 3000 200 3000 curveto + 100 3000 -400 2500 -200 1800 curveto + 350 -600 lineto + 720 -1600 0 -1650 -400 -1400 curveto + + %go back to start, drawing the other boundary + -400 -1480 lineto + 0 -1700 800 -1700 430 -600 curveto + -120 1800 lineto + -300 2400 200 2800 250 2800 curveto + 400 2800 430 2700 430 2450 curveto + 430 1800 -900 1200 -900 300 curveto + -750 -900 800 -900 850 0 curveto + 900 1100 -750 900 -120 -300 curveto fill + + %circle at the bottom + -300 -1250 250 0 360 arc fill + } def + + % fclef + /B { + newpath + %start with outside boundary, at bottom + -1000 -1700 moveto + 100 -1100 500 -600 450 0 curveto + 450 850 -1100 850 -950 0 curveto + + %go back to start, drawing the other boundary + -880 0 lineto + -920 400 -600 560 -300 560 curveto + 0 560 150 400 150 0 curveto + 150 -400 100 -900 -1000 -1620 curveto fill + + %circle at the left + newpath + -700 0 250 0 360 arc fill + + %do the two dots after the main curve + 700 -300 100 0 360 arc fill + 700 300 100 0 360 arc fill + } def + + % cclef + /C { + gsave + %do upper curved part, then scale to do mirror image + 0 1 1 { + pop %we don't need the loop variable + %outer boundary of curve + -170 0 moveto 100 300 lineto + 400 -200 750 300 750 650 curveto + 750 1100 450 1235 250 1235 curveto + 0 1235 -143 1100 -143 950 curveto + + %inner boundary of curve + 0 950 lineto + 0 1100 30 1165 250 1165 curveto + 300 1165 450 1100 450 650 curveto + 450 400 400 -100 100 400 curveto + -270 0 lineto fill + %stroke + %-270 0 moveto 100 400 lineto + %400 -100 450 400 450 650 curveto + %450 1100 300 1165 250 1165 curveto + %30 1165 0 1100 0 950 curveto + %stroke + + %elliptical ball at end of curve + gsave + 1.3 1 scale + 10 950 120 0 360 arc fill + grestore + 1 -1 scale %reflect across X axis + } for + grestore + + % two vertical lines on the left + 300 setlinewidth -600 -1200 halflwid sub moveto + -600 1200 halflwid add lineto stroke + lwid setlinewidth -300 -1200 halflwid sub moveto + -300 1200 halflwid add lineto stroke + } def + + % dblwhole + /D { + do_1n %do a whole note + lwid setlinewidth + -490 -600 moveto -490 600 lineto stroke + 490 -600 moveto 490 600 lineto stroke + } def + + % 1n + /E { + do_1n %do a whole note + } def + + % 2n + /F { + do_2n %do a half note + } def + + % 4n + /G { + do_4n %do a quarter note head + } def + + % upflag + /H { + do_upflag %do an upflag + } def + + % dnflag + /I { + gsave + 1 -1 scale %reflect across X axis + do_upflag %do an upflag + grestore + } def + + % dwhrest + /J { + 300 setlinewidth + 0 0 moveto 0 600 lineto stroke + } def + + % 1rest + /K { + lwid setlinewidth + -750 600 moveto 750 600 lineto stroke + 300 setlinewidth + -400 450 moveto 400 450 lineto stroke + } def + + % 2rest + /L { + lwid setlinewidth + -750 0 moveto 750 0 lineto stroke + 300 setlinewidth + -400 150 moveto 400 150 lineto stroke + } def + + % 4rest + /M { + newpath + cor3x cor3y halflwid add moveto + %-400 -200 -450 -650 50 -950 lwid add curveto + -450 -50 -450 -650 50 -950 lwid add curveto + -150 -650 -100 -250 cor3x cor3y halflwid sub curveto + fill + + cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto + cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto + fill + + lwid setlinewidth + topx topy moveto cor1x cor1y lineto stroke + cor2x cor2y moveto cor3x cor3y lineto stroke + } def + + % 8rest + /N { + 0 0 0 -600 do_shortrest + } def + + % 16rest + /O { + 1 1 100 -1200 do_shortrest + } def + + % 32rest + /P { + 2 1 0 -1800 do_shortrest + } def + + % 64rest + /Q { + 3 2 -80 -2100 do_shortrest + } def + + % 128rest + /R { + 4 2 -150 -2700 do_shortrest + } def + + % 256rest + /S { + 5 3 -280 -3300 do_shortrest + } def + + % dot + /T { + newpath + 0 0 120 0 360 arc fill + } def + + % nat + /U { + % fill crossbars so that we can do parallelograms + -235 -470 moveto -235 -270 lineto + 235 -130 lineto 235 -330 lineto fill + -235 130 moveto -235 330 lineto + 235 470 lineto 235 270 lineto fill + + % vertical strokes + lwid setlinewidth + -200 -380 moveto -200 850 lineto stroke + 200 -850 moveto 200 380 lineto stroke + } def + + % sharp + /V { + % fill crossbars so that we can do parallelograms + -325 -480 moveto -325 -280 lineto + 325 -120 lineto 325 -320 lineto fill + -325 120 moveto -325 320 lineto + 325 480 lineto 325 280 lineto fill + + % vertical strokes + lwid setlinewidth + -150 -930 moveto -150 880 lineto stroke + 150 -880 moveto 150 930 lineto stroke + } def + + % flat + /W { + do_flat %do a flat + } def + + % dblsharp + /X { + gsave + 0 1 3 { %loop once for each of 4 sticks + pop %we don't need the loop variable + 0 off neg moveto + outbendbig outbendsmall lineto + inbendbig inbendsmall lineto + limit limit lineto + inbendsmall inbendbig lineto + outbendsmall outbendbig lineto + off neg 0 lineto + fill + -90 rotate + } for + grestore + } def + + % dblflat + /Y { + -290 580 290 { %loop once for each flat + + gsave + 1 setlinewidth + 0 translate %translate left/right (loop var) + do_flat %do a flat + grestore + + } for + } def + + % xnote + /Z { + gsave + 1.15 1 scale 120 setlinewidth 1 setlinecap %round + -300 -300 moveto 300 300 lineto stroke + -300 300 moveto 300 -300 lineto stroke + grestore + } def + + % dwhdiamond + /a { + do_diamond %do a diamond + lwid setlinewidth + -420 -600 moveto -420 600 lineto stroke + 420 -600 moveto 420 600 lineto stroke + } def + + % diamond + /b { + do_diamond %do a diamond + } def + + % filldiamond + /c { + 420 0 moveto 0 300 lineto + -420 0 lineto 0 -300 lineto fill + } def + + % up2n + /d { + lwid setlinewidth + 380 0 moveto 380 2100 lineto stroke + do_2n %do a half note + } def + + % dn2n + /e { + lwid setlinewidth + -380 0 moveto -380 -2100 lineto stroke + do_2n %do a half note + } def + + % up4n + /f { + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto 370 2100 lineto stroke + } def + + % dn4n + /g { + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto -370 -2100 lineto stroke + } def + + % up8n + /h { + gsave + -330 0 translate % half a flag width + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto 370 2100 lineto stroke + 670 2100 translate + 1 -1 scale %reflect across X axis + do_upflag %do an upflag + grestore + } def + + % dn8n + /i { + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto -370 -2100 lineto stroke + gsave + -70 -2100 translate + do_upflag %do an upflag + grestore + } def + + % up16n + /j { + 2 do_upshortnote + } def + + % dn16n + /k { + 2 do_dnshortnote + } def + + % up32n + /l { + 3 do_upshortnote + } def + + % dn32n + /m { + 3 do_dnshortnote + } def + + % up64n + /n { + 4 do_upshortnote + } def + + % dn64n + /o { + 4 do_dnshortnote + } def + + % up128n + /p { + 5 do_upshortnote + } def + + % dn128n + /q { + 5 do_dnshortnote + } def + + % up256n + /r { + 6 do_upshortnote + } def + + % dn256n + /s { + 6 do_dnshortnote + } def + + % com + /t { + do_com %do a common time symbol + } def + + % cut + /u { + do_com %do a common time symbol + lwid setlinewidth + 0 -900 moveto 0 900 lineto stroke + } def + + % begped + /v { + lwid setlinewidth + -200 600 moveto -200 0 lineto 200 0 lineto stroke + } def + + % pedal + /w { + lwid setlinewidth + -500 0 moveto -450 0 lineto 0 600 lineto + 450 0 lineto 500 0 lineto stroke + } def + + % endped + /x { + lwid setlinewidth + 200 600 moveto 200 0 lineto -200 0 lineto stroke + } def + + % dnbow + /y { + lwid setlinewidth + -350 0 moveto -350 900 lineto stroke + 350 0 moveto 350 900 lineto stroke + 200 setlinewidth + -350 800 moveto 350 800 lineto stroke + } def + + % upbow + /z { + lwid setlinewidth + -300 900 moveto 0 0 lineto 300 900 lineto stroke + } def + + % wedge + /one { + 0 0 moveto -150 500 lineto 150 500 lineto fill + } def + + % uwedge + /two { + -150 0 moveto 150 0 lineto 0 500 lineto fill + } def + + % ferm + /three { + newpath + do_ferm %do a right side up fermata + } def + + % uferm + /four { + newpath + gsave + 0 270 lwid sub 800 add translate %baseline at bottom + 180 rotate %upside down + do_ferm %do a right side up fermata + grestore + } def + + % sign + /five { + gsave + %do upper left curved part, upper right dot; + %then rotate 180 to do other half + 0 1 1 { + pop %we don't need the loop variable + 0 100 moveto %inner boundary + -1000 300 -400 750 -200 700 curveto + -200 800 lineto %outer boundary + -550 900 -1100 100 0 -100 curveto + fill + %dot at end of curve + -200 700 100 0 360 arc fill + %dot in upper right quadrant + 500 200 70 0 360 arc fill + 180 rotate + } for + grestore + + %slash through middle + lwid setlinewidth + -400 -800 moveto 400 800 lineto stroke + } def + + % coda + /six { + newpath + gsave + 0.6 1 scale + 0 0 550 0 360 arc %outside boundary + 1 0.6 div 1 scale %back to original + 0.9 1 scale + 0 0 650 0 360 arc %inside boundary + eofill + grestore + lwid setlinewidth + 0 -850 moveto 0 850 lineto stroke + -800 0 moveto 800 0 lineto stroke + } def + + % mor + /seven { + do_mor %do a mordent + } def + + % invmor + /eight { + do_mor %do a mordent + lwid setlinewidth + 0 -450 moveto 0 450 lineto stroke + } def + + % turn + /nine { + do_turn %do a turn + } def + + % invturn + /zero { + gsave + 1 -1 scale %reflect across X axis + do_turn %do a turn + grestore + } def + + % acc_gt + /numbersign { + lwid setlinewidth + -500 300 moveto 500 0 lineto -500 -300 lineto stroke + } def + + % acc_hat + /dollar { + newpath + -365 0 moveto 0 860 lineto 365 0 lineto + 150 0 lineto -75 530 lineto -300 0 lineto fill + } def + + % acc_uhat + /quotedbl { + newpath + 365 860 moveto 0 0 lineto -365 860 lineto + -150 860 lineto 75 330 lineto 300 860 lineto fill + } def + + % tr + /asterisk { + %vertical bar of t + -350 1000 moveto -550 200 lineto + -612.5 -50 -212.5 -50 -160 200 curveto + -230 200 lineto + -300 50 -420 50 -400 200 curveto + -200 1000 lineto fill + + %crossbar of t and vertical bar of r + -700 600 moveto -160 600 lineto + 20 600 30 520 60 440 curveto + -50 0 lineto 70 0 lineto 180 440 lineto + 190 480 100 670 -150 670 curveto + -690 670 lineto fill + + %horizontal curve of r + 100 480 moveto + 300 630 450 700 650 550 curveto + 560 480 lineto + 450 630 300 560 100 390 curveto + fill + + %knob at end of r + 600 460 100 0 360 arc fill + } def + + % leg + /comma { + 100 setlinewidth + -400 0 moveto 400 0 lineto stroke + } def + + % rr + /hyphen { + 100 setlinewidth + -400 0 moveto 0 1000 lineto stroke + 0 0 moveto 400 1000 lineto stroke + } def + + % measrpt + /period { + newpath -450 400 150 0 360 arc fill + newpath 450 -400 150 0 360 arc fill + 200 setlinewidth + -550 -600 moveto 550 600 lineto stroke + } def + + % copyright + /slash { + lwid setlinewidth + newpath 0 400 400 0 360 arc stroke + newpath 0 400 200 45 315 arc stroke + } def + + % dim + /quoteleft { + 50 setlinewidth + newpath 0 640 220 0 360 arc stroke + } def + + % halfdim + /quoteright { + 50 setlinewidth + newpath 0 640 220 0 360 arc stroke + newpath -340 300 moveto 340 980 lineto stroke + } def + + % triangle + /asciicircum { + 50 setlinewidth + newpath -340 -10 moveto 0 710 lineto + 340 -10 lineto closepath stroke + } def + + % qwhrest + /ampersand { + 300 setlinewidth + 0 -600 moveto 0 600 lineto stroke + } def + + % ll1rest + /exclam { + 310 setlinewidth + -400 455 moveto 400 450 lineto stroke + } def + + % ll2rest + /at { + 310 setlinewidth + -400 145 moveto 400 150 lineto stroke + } def + end + + /BuildChar { + + exch begin + Encoding exch get + + dup + Mcbbox0 exch get + aload pop setcachedevice + + CharStrings exch get + exec + end + } def +end + + +% Define another music character font, since there are too many to fit in one +% font. It works the same way as the first one. + +/mfont1 100 dict def +mfont1 begin + /FontType 3 def + /FontMatrix [ .001 0 0 0.001 0 0 ] def + /FontBBox [ -2000 -4030 2000 4030 ] def + /FontName (Mfont1) def + + % set up Encoding vector with standard names + /Encoding 256 array def + StandardEncoding Encoding copy + pop + + %%%%% define routines that will be used by multiple characters %%%%% + + /do_dwh_bars { + % the two bars surrounding a double whole note + lwid setlinewidth + -420 -600 moveto -420 600 lineto stroke + 420 -600 moveto 420 600 lineto stroke + } def + /do_righttriangle { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto + 350 150 moveto -140 150 lineto 350 -213 lineto + eofill + } def + /do_fillrighttriangle { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto + fill + } def + /do_rectangle { + newpath + 420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto + 350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto + eofill + } def + /do_isostriangle { + newpath + 0 300 moveto -420 -270 lineto 420 -270 lineto + 0 182 moveto -245 -150 lineto 245 -150 lineto + eofill + } def + /do_piewedge { + newpath + 0 -300 moveto 0 -244 514 35 145 arc + 0 -209 moveto 0 -244 394 43 137 arc + eofill + } def + /do_semicircle { + newpath + gsave + 1 1.357 scale 420 199 moveto 0 199 420 180 360 arc + 1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc + eofill + grestore + } def + /do_slashhead { + newpath + lwid setlinewidth + -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto + closepath stroke + } def + + % subsidiary dictionary of character definitions + /CharStrings 128 dict def + CharStrings begin + + /.notdef {} def + + % Here are the definitions of the characters. A stepsize here + % is 300 units (assuming the character is drawn at its default + % size). + + % dwhrighttriangle + /A { + do_righttriangle + do_dwh_bars + } def + + % righttriangle + /B { + do_righttriangle + } def + + % fillrighttriangle + /C { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto + 420 -300 lineto + fill + } def + + % udwhrighttriangle + /D { + gsave + 180 rotate + do_righttriangle + do_dwh_bars + grestore + } def + + % urighttriangle + /E { + gsave + 180 rotate + do_righttriangle + grestore + } def + + % ufillrighttriangle + /F { + gsave + 180 rotate + do_fillrighttriangle + grestore + } def + + % dwhrectangle + /G { + do_rectangle + do_dwh_bars + } def + + % rectangle + /H { + do_rectangle + } def + + % fillrectangle + /I { + newpath + 420 270 moveto -420 270 lineto -420 -270 lineto + 420 -270 lineto + fill + } def + + % dwhisostriangle + /J { + do_isostriangle + do_dwh_bars + } def + + % isostriangle + /K { + do_isostriangle + } def + + % fillisostriangle + /L { + newpath + 0 300 moveto -420 -270 lineto 420 -270 lineto + fill + } def + + % dwhpiewedge + /M { + do_piewedge + do_dwh_bars + } def + + % piewedge + /N { + do_piewedge + } def + + % fillpiewedge + /O { + newpath + 0 -300 moveto 0 -244 514 35 145 arc + fill + } def + + % dwhsemicircle + /P { + do_semicircle + do_dwh_bars + } def + + % semicircle + /Q { + do_semicircle + } def + + % fillsemicircle + /R { + newpath + gsave + 1 570 420 div scale + 420 199 moveto 0 199 420 180 360 arc + fill + grestore + } def + + % dwhslashhead + /S { + do_slashhead + lwid setlinewidth + -650 -600 moveto -650 600 lineto stroke + 650 -600 moveto 650 600 lineto stroke + } def + + % slashhead + /T { + do_slashhead + } def + + % fillslashhead + /U { + newpath + 200 setlinewidth + -550 -600 moveto 550 600 lineto stroke + } def + + % blankhead + /V { + %print nothing + } def + end + + /BuildChar { + + exch begin + Encoding exch get + + dup + Mcbbox1 exch get + aload pop setcachedevice + + CharStrings exch get + exec + end + } def +end + + +% General routines for printing any music character, invoked by each music +% character's specific routine below. The scaling factor (default 1) needs +% to be multiplied by 10 to get the actual size. These routines restore the +% preexisting current font when they are done. + +/printmchar0 { + gsave + /musicchar exch def + /Mfont0 findfont exch 10 mul scalefont setfont moveto + musicchar show + grestore +} def +/printmchar1 { + gsave + /musicchar exch def + /Mfont1 findfont exch 10 mul scalefont setfont moveto + musicchar show + grestore +} def + +% Define each music character name to be a routine that prints the character. +% Each character is to be invoked as in this example: +% 100 200 1 gclef % at (100, 200), scale to default size & print + +/gclef { (A) printmchar0 } def +/fclef { (B) printmchar0 } def +/cclef { (C) printmchar0 } def +/dblwhole { (D) printmchar0 } def +/1n { (E) printmchar0 } def +/2n { (F) printmchar0 } def +/4n { (G) printmchar0 } def +/upflag { (H) printmchar0 } def +/dnflag { (I) printmchar0 } def +/dwhrest { (J) printmchar0 } def +/1rest { (K) printmchar0 } def +/2rest { (L) printmchar0 } def +/4rest { (M) printmchar0 } def +/8rest { (N) printmchar0 } def +/16rest { (O) printmchar0 } def +/32rest { (P) printmchar0 } def +/64rest { (Q) printmchar0 } def +/128rest { (R) printmchar0 } def +/256rest { (S) printmchar0 } def +/dot { (T) printmchar0 } def +/nat { (U) printmchar0 } def +/sharp { (V) printmchar0 } def +/flat { (W) printmchar0 } def +/dblsharp { (X) printmchar0 } def +/dblflat { (Y) printmchar0 } def +/xnote { (Z) printmchar0 } def +/dwhdiamond { (a) printmchar0 } def +/diamond { (b) printmchar0 } def +/filldiamond { (c) printmchar0 } def +/up2n { (d) printmchar0 } def +/dn2n { (e) printmchar0 } def +/up4n { (f) printmchar0 } def +/dn4n { (g) printmchar0 } def +/up8n { (h) printmchar0 } def +/dn8n { (i) printmchar0 } def +/up16n { (j) printmchar0 } def +/dn16n { (k) printmchar0 } def +/up32n { (l) printmchar0 } def +/dn32n { (m) printmchar0 } def +/up64n { (n) printmchar0 } def +/dn64n { (o) printmchar0 } def +/up128n { (p) printmchar0 } def +/dn128n { (q) printmchar0 } def +/up256n { (r) printmchar0 } def +/dn256n { (s) printmchar0 } def +/com { (t) printmchar0 } def +/cut { (u) printmchar0 } def +/begped { (v) printmchar0 } def +/pedal { (w) printmchar0 } def +/endped { (x) printmchar0 } def +/dnbow { (y) printmchar0 } def +/upbow { (z) printmchar0 } def +/wedge { (1) printmchar0 } def +/uwedge { (2) printmchar0 } def +/ferm { (3) printmchar0 } def +/uferm { (4) printmchar0 } def +/sign { (5) printmchar0 } def +/coda { (6) printmchar0 } def +/mor { (7) printmchar0 } def +/invmor { (8) printmchar0 } def +/turn { (9) printmchar0 } def +/invturn { (0) printmchar0 } def +/acc_gt { (#) printmchar0 } def +/acc_hat { ($) printmchar0 } def +/acc_uhat { (") printmchar0 } def +/tr { (*) printmchar0 } def +/leg { (,) printmchar0 } def +/rr { (-) printmchar0 } def +/measrpt { (.) printmchar0 } def +/copyright { (/) printmchar0 } def +/dim { (`) printmchar0 } def +/halfdim { (') printmchar0 } def +/triangle { (^) printmchar0 } def +/qwhrest { (&) printmchar0 } def +/ll1rest { (!) printmchar0 } def +/ll2rest { (@) printmchar0 } def +/dwhrighttriangle { (A) printmchar1 } def +/righttriangle { (B) printmchar1 } def +/fillrighttriangle { (C) printmchar1 } def +/udwhrighttriangle { (D) printmchar1 } def +/urighttriangle { (E) printmchar1 } def +/ufillrighttriangle { (F) printmchar1 } def +/dwhrectangle { (G) printmchar1 } def +/rectangle { (H) printmchar1 } def +/fillrectangle { (I) printmchar1 } def +/dwhisostriangle { (J) printmchar1 } def +/isostriangle { (K) printmchar1 } def +/fillisostriangle { (L) printmchar1 } def +/dwhpiewedge { (M) printmchar1 } def +/piewedge { (N) printmchar1 } def +/fillpiewedge { (O) printmchar1 } def +/dwhsemicircle { (P) printmchar1 } def +/semicircle { (Q) printmchar1 } def +/fillsemicircle { (R) printmchar1 } def +/dwhslashhead { (S) printmchar1 } def +/slashhead { (T) printmchar1 } def +/fillslashhead { (U) printmchar1 } def +/blankhead { (V) printmchar1 } def + + +% Define routines for Mup output other than music characters. + +/stepsize 3 def % define a step size as 3 points (at default magnification) + +% x1 y1 x2 lines dist staffscale staff +% draw a staff starting at x1, y1 and extending to x2 with "lines" +% lines, 2*dist*stepsize apart, scaled by staffscale +/staff { + /staffscale exch def + /dist exch def + /lines exch def + /x2 exch def + /y1 exch def + /x1 exch def + 0.7 staffscale mul sb setlinewidth + 1 lines sub 2 lines 1 sub { % loop from bottom line to top line + dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto + stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke + } for +} def + +% x y1 y2 bracket draw a bracket; y1 is the top +/bracket { + /y2 exch def + /y1 exch def + /x exch def + gsave + 3 setlinewidth + x 2 sub y1 1 add moveto + x 2 sub y2 1 sub lineto + stroke + x 2 sub y1 1 add moveto + x 1 sub y1 1 add x 3 add y1 1 add x 5 add y1 6 add curveto + x 6 add y1 5 add lineto + x 5 add y1 2 add x 1 add y1 2 sub x 2 sub y1 2 sub curveto + fill + x 2 sub y2 1 sub moveto + x 1 sub y2 1 sub x 3 add y2 1 sub x 5 add y2 6 sub curveto + x 6 add y2 5 sub lineto + x 5 add y2 2 sub x 1 add y2 2 add x 2 sub y2 2 add curveto + fill + grestore +} def + +% x y1 y2 brace draw a brace; y1 is the top +/brace { + /y2 exch def + /y1 exch def + /x exch def + gsave + x 9 sub y1 y2 add 2 div translate + /topy y1 y2 sub 2 div 1 sub def + 0 1 1 { + pop + %0 topy moveto 0 0 lineto stroke + 0 0 moveto + 16 topy 0.2 mul -11 topy 0.6 mul 8 topy curveto + 8.7 topy lineto + -7 topy 0.7 mul 20 topy 0.3 mul 1 0 curveto + fill + 1 -1 scale % flip to do bottom half + } for + grestore +} def + +% endx endy wavy staffscale draw a wavy line from current point to here, +% scaled by staffscale +/wavy { + /staffscale exch def + /endy exch def % define the end point of the line + /endx exch def + currentpoint % line starts at current point + /begy exch def % define the beginning point of the line + /begx exch def + gsave + /dx endx begx sub def % find delta x and delta y + /dy endy begy sub def + /r dx dx mul dy dy mul add sqrt def % hypotenuse + /theta dy dx atan def % angle with positive x axis + begx begy translate % change axes so that we can draw the line + theta rotate % from (0, 0) to (r, 0) + staffscale staffscale scale % scale everything by staffscale + /scaledr r staffscale div def % but scale r in reverse to keep length + + % Each outer loop draws one cycle of the squiggle. It continues until + % we are at or beyond the desired end point. + 0 0 moveto + 0 6 scaledr { + gsave + % first loop draws left half of squiggle; second draws right + 0 1 1 { + 0.0 0.4 moveto + 2.0 1.9 3.4 2.3 3.9 0.0 curveto + 2.1 0.0 lineto + 1.9 0.8 1.4 0.7 0.0 -0.4 curveto + fill + pop 180 rotate -6 0 translate + } for + grestore + + pop 6 0 translate % shift axes right one squiggle + } for + + grestore +} def + +% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid +% print a guitar grid diagram +/grid { + /grid_positions exch def % 0="o", -1="x", -2=nothing, positive=dot + /curver exch def % right string for curve, 0 if none + /curvel exch def % left string for curve, 0 if none + /numvert exch def % vertical position to print fretno, 0 if none + /fretno exch def % fret no. to print at right, 0 if none + /frets exch def % number of fret lines + /space exch def % points between two neighboring lines + /y exch def % y coord of top fret line + /x exch def % x coord of left strings + + gsave + /strings grid_positions length def % number of strings + /lmarky 0.4 space mul y add def % lowest Y of a "o" or "x" + space 10 div setlinewidth + 2 setlinecap + + % draw the lines of the grid + 0 1 strings 1 sub { % loop from left string to right string + dup space mul x add y moveto + space mul x add frets 1 sub space mul y exch sub lineto stroke + } for + 0 -1 1 frets sub { % loop from top fret (nut) to bottom fret + dup space mul y add x exch moveto + space mul y add strings 1 sub space mul x add exch lineto stroke + } for + + % draw the curved line if there is one + curvel 0 gt { + % within strings curvel to curver, find smallest positive fret + /minfret 1000 def + curvel 1 curver { + /strno exch def + /grid_p grid_positions strno 1 sub get def + grid_p 0 gt grid_p minfret lt and { + /minfret grid_p def + } if + } for + + % if curve goes above top fret, other marks must be higher + minfret 1 eq { + /hmarky 1.2 space mul y add def + } { + /hmarky lmarky def + } ifelse + + /strdiff curver curvel sub def + space 8 div setlinewidth + + % set endpoint coords of curve; higher if curve is short + /curvex1 curvel 1 sub space mul x add def + /curvex2 curver 1 sub space mul x add def + /curvey 1 minfret sub space mul y add def + strdiff 3 lt { + /curvey 0.2 strdiff div space mul curvey add def + } if + + % move to left end, set other points, draw curve + curvex1 curvey moveto + + curvex1 curvex2 curvex1 sub 3 div add + curvey space 0.4 strdiff sqrt mul mul add + + curvex2 curvex2 curvex1 sub 3 div sub + curvey space 0.4 strdiff sqrt mul mul add + + curvex2 curvey curveto stroke + } if + + space 10 div setlinewidth + + % draw dots and x and o marks + 0 1 strings 1 sub { % loop from left string to right string + /strno exch def % first string is 0 + /grid_p grid_positions strno get def + /strx strno space mul x add def + + % set Y of mark higher if curved line covers this string + strno 1 add curvel ge strno 1 add curver le and { + /marky hmarky def + } { + /marky lmarky def + } ifelse + + grid_p -1 eq { % draw an X above the string + /xhwid space 3 div def + strx xhwid sub marky xhwid sub moveto + strx xhwid add marky xhwid add lineto stroke + strx xhwid sub marky xhwid add moveto + strx xhwid add marky xhwid sub lineto stroke + } if + grid_p 0 eq { % draw a circle above the string + strx marky space 0.3 mul 0 360 arc stroke + } if + grid_p 1 ge { % draw a dot by the proper fret + strx y grid_p space mul sub space 3 div add + space 3 div 0 360 arc fill + } if + } for + + % print "X fr" if requested + fretno 0 gt { + /Palatino-Roman findfont space 1.9 mul scalefont setfont + x strings 0.5 sub space mul add + y space numvert 0.3 add mul sub moveto + fretno 2 string cvs show ( fr) show + } if + grestore +} def + +% x1 y1 x2 y2 whitebox draw a white rectangle with opposite +% corners of (x1,y1) and (x2,y2) +/whitebox { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + 1.0 setgray + newpath + x1 y1 moveto + x1 y2 lineto + x2 y2 lineto + x2 y1 lineto + closepath + fill + stroke + 0.0 setgray +} def + + +/LineNum 0 def +/InputFile (unknown) def + +% n linenum +/linenum { + /LineNum exch def +} def + +% (inputfilename) inputfile +/inputfile { + /InputFile exch def +} def + +% find size of Encoding and make a dictionary +% that size for bounding box information +mfont0 begin +/dictsize Encoding length def +mfont0 /Mcbbox0 dictsize dict put + +% temporarily redefine printmchar0 to get code +5 dict begin +/printmchar0 { {} forall } def + +Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put +Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put +Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put +Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put +Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put +Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put +Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put +Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put +Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put +Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put +Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put +Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put +Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put +Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put +Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put +Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put +Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put +Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put +Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put +Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put +Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put +Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put +Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put +Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put +Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put +Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put +Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put +Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put +Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put +Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put +Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put +Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put +Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put +Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put +Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put +Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put +Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put +Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put +Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put +Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put +Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put +Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put +Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put +Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put +Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put +Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put +Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put +Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put +Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put +Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put +Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put +Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put +Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put +Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put +Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put +Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put +Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put +Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put +Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put +Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put +Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put +Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put +Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put +Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put +Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put +Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put +Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put +Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put +Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put +Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put +Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put +Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put + +end +end + +/Mfont0 mfont0 definefont + + +% find size of Encoding and make a dictionary +% that size for bounding box information +mfont1 begin +/dictsize Encoding length def +mfont1 /Mcbbox1 dictsize dict put + +% temporarily redefine printmchar1 to get code +5 dict begin +/printmchar1 { {} forall } def + +Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put +Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put +Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put +Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put + +end +end + +/Mfont1 mfont1 definefont + +/makeExtEncoding { + /extendedencoding 256 array def + StandardEncoding extendedencoding copy + extendedencoding 32 /exclamdown put + extendedencoding 33 /cent put + extendedencoding 34 /sterling put + extendedencoding 35 /yen put + extendedencoding 36 /quotedblleft put + extendedencoding 37 /guillemotleft put + extendedencoding 38 /guillemotright put + extendedencoding 39 /guilsinglleft put + extendedencoding 40 /guilsinglright put + extendedencoding 41 /dagger put + extendedencoding 42 /daggerdbl put + extendedencoding 43 /bullet put + extendedencoding 44 /quotedblbase put + extendedencoding 45 /quotedblright put + extendedencoding 46 /questiondown put + extendedencoding 47 /grave put + extendedencoding 48 /acute put + extendedencoding 49 /macron put + extendedencoding 50 /breve put + extendedencoding 51 /dotaccent put + extendedencoding 52 /dieresis put + extendedencoding 53 /ring put + extendedencoding 54 /cedilla put + extendedencoding 55 /hungarumlaut put + extendedencoding 56 /ogonek put + extendedencoding 57 /caron put + extendedencoding 58 /emdash put + extendedencoding 59 /AE put + extendedencoding 60 /ae put + extendedencoding 61 /ordfeminine put + extendedencoding 62 /ordmasculine put + extendedencoding 63 /Lslash put + extendedencoding 64 /lslash put + extendedencoding 65 /Oslash put + extendedencoding 66 /oslash put + extendedencoding 67 /OE put + extendedencoding 68 /oe put + extendedencoding 69 /dotlessi put + extendedencoding 70 /germandbls put + extendedencoding 71 /Aacute put + extendedencoding 72 /aacute put + extendedencoding 73 /Acircumflex put + extendedencoding 74 /acircumflex put + extendedencoding 75 /Adieresis put + extendedencoding 76 /adieresis put + extendedencoding 77 /Agrave put + extendedencoding 78 /agrave put + extendedencoding 79 /Aring put + extendedencoding 80 /aring put + extendedencoding 81 /Atilde put + extendedencoding 82 /atilde put + extendedencoding 83 /Ccedilla put + extendedencoding 84 /ccedilla put + extendedencoding 85 /Eacute put + extendedencoding 86 /eacute put + extendedencoding 87 /Ecircumflex put + extendedencoding 88 /ecircumflex put + extendedencoding 89 /Edieresis put + extendedencoding 90 /edieresis put + extendedencoding 91 /Egrave put + extendedencoding 92 /egrave put + extendedencoding 93 /Iacute put + extendedencoding 94 /iacute put + extendedencoding 95 /Icircumflex put + extendedencoding 96 /icircumflex put + extendedencoding 97 /Idieresis put + extendedencoding 98 /idieresis put + extendedencoding 99 /Igrave put + extendedencoding 100 /igrave put + extendedencoding 101 /Ntilde put + extendedencoding 102 /ntilde put + extendedencoding 103 /Oacute put + extendedencoding 104 /oacute put + extendedencoding 105 /Ocircumflex put + extendedencoding 106 /ocircumflex put + extendedencoding 107 /Odieresis put + extendedencoding 108 /odieresis put + extendedencoding 109 /Ograve put + extendedencoding 110 /ograve put + extendedencoding 111 /Otilde put + extendedencoding 112 /otilde put + extendedencoding 113 /Scaron put + extendedencoding 114 /scaron put + extendedencoding 115 /Uacute put + extendedencoding 116 /uacute put + extendedencoding 117 /Ucircumflex put + extendedencoding 118 /ucircumflex put + extendedencoding 119 /Udieresis put + extendedencoding 120 /udieresis put + extendedencoding 121 /Ugrave put + extendedencoding 122 /ugrave put + extendedencoding 123 /Ydieresis put + extendedencoding 124 /ydieresis put + extendedencoding 125 /Zcaron put + extendedencoding 126 /zcaron put + extendedencoding 127 /space put +} def + +/makeExtendedFont { + findfont + dup length dict /newdict exch def + { 1 index /FID ne + { newdict 3 1 roll put } + { pop pop } + ifelse + } forall + newdict /Encoding extendedencoding put + newdict /UniqueID newdict /UniqueID get 1 add put + newdict definefont pop +} def +/flagsep 1.60 300 mul def % 1.60 stepsizes +/scv 149508 def /sf 962 string def +/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def +[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa +[ 961 ] 1341740116 fa +[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa +[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa +[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa +[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa +[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa +[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa +[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa +[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa +[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa +[ 795 ] 1622189328 fa +[ 463 45 40 41 50 45 84 ] 304180545 fa +[ 494 40 41 49 45 43 84 ] 251711819 fa +[ 149 203 37 144 ] 358262127 fa +[ 456 142 52 ] 95949173 fa +[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa +[ 839 5 13 12 13 13 48 ] 1943250302 fa +[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa +[ 798 1 3 1 ] 1277775234 fa +[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa +[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa +[ 193 49 180 8 17 134 ] 831070621 fa +[ 353 366 ] 1033403809 fa +[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa +[ 423 8 109 ] 508918194 fa +[ 328 6 30 6 31 6 269 ] 212071871 fa +[ 390 357 2 ] 1671244225 fa +[ 500 ] 347047368 fa +[ 558 ] 1276946910 fa +[ 651 ] 2109048312 fa +[ 644 ] 1914352160 fa +[ 520 ] 471204394 fa +[ 512 5 2 ] 1930983991 fa +[ 665 ] 154021439 fa +[ 513 ] 777103941 fa +[ 514 ] 260959830 fa +[ 530 239 ] 1284535922 fa +[ 510 ] 1982423675 fa +[ 150 ] 1969948305 fa +[ 511 7 134 ] 1407991454 fa +[ 144 371 ] 1896661664 fa +[ 464 52 ] 1444653737 fa +[ 509 81 ] 1712172720 fa +[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa +[ 954 ] 1802916616 fa +[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa +[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa +[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa +[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa +[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa +[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa +[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa +[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa +[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa +[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa +[ 960 ] 75399990 fa +[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa +[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa +[ 901 ] 422446918 fa +[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa +[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa +[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa +[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa +[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa +[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa +[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa +[ 780 32 ] 847653755 fa +[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa +[ 724 83 7 ] 1643402114 fa +[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa +[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa +[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa +[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa +[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa +[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa +[ 944 8 ] 1770206109 fa +[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa +[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa +[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa +[ 912 9 11 ] 273962927 fa +[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa +[ 130 683 ] 1406620603 fa +[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa +[ 861 13 9 4 12 8 17 3 ] 1447963591 fa +[ 67 143 8 128 115 435 19 2 ] 477757388 fa +[ 490 35 ] 1151262673 fa +[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa +[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa +sf cvx exec +%%BeginResource: procset grops 1.17 2 +/setpacking where{ +pop +currentpacking +true setpacking +}if +/grops 120 dict dup begin +/SC 32 def +/A/show load def +/B{0 SC 3 -1 roll widthshow}bind def +/C{0 exch ashow}bind def +/D{0 exch 0 SC 5 2 roll awidthshow}bind def +/E{0 rmoveto show}bind def +/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def +/G{0 rmoveto 0 exch ashow}bind def +/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/I{0 exch rmoveto show}bind def +/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def +/K{0 exch rmoveto 0 exch ashow}bind def +/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/M{rmoveto show}bind def +/N{rmoveto 0 SC 3 -1 roll widthshow}bind def +/O{rmoveto 0 exch ashow}bind def +/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/Q{moveto show}bind def +/R{moveto 0 SC 3 -1 roll widthshow}bind def +/S{moveto 0 exch ashow}bind def +/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/SF{ +findfont exch +[exch dup 0 exch 0 exch neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/MF{ +findfont +[5 2 roll +0 3 1 roll +neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def +/MANUAL{ +statusdict begin/manualfeed true store end +}bind def +/PLG{ +gsave newpath clippath pathbbox grestore +exch pop add exch pop +}bind def +/BP{ +/level0 save def +1 setlinecap +1 setlinejoin +72 RES div dup scale +LS{ +90 rotate +}{ +0 PL translate +}ifelse +1 -1 scale +}bind def +/EP{ +level0 restore +showpage +}bind def +/DA{ +newpath arcn stroke +}bind def +/SN{ +transform +.25 sub exch .25 sub exch +round .25 add exch round .25 add exch +itransform +}bind def +/DL{ +SN +moveto +SN +lineto stroke +}bind def +/DC{ +newpath 0 360 arc closepath +}bind def +/TM matrix def +/DE{ +TM currentmatrix pop +translate scale newpath 0 0 .5 0 360 arc closepath +TM setmatrix +}bind def +/RC/rcurveto load def +/RL/rlineto load def +/ST/stroke load def +/MT/moveto load def +/CL/closepath load def +/FL{ +currentgray exch setgray fill setgray +}bind def +/BL/fill load def +/LW/setlinewidth load def +/RE{ +findfont +dup maxlength 1 index/FontName known not{1 add}if dict begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +/Encoding exch def +dup/FontName exch def +currentdict end definefont pop +}bind def +/DEFS 0 def +/EBEGIN{ +moveto +DEFS begin +}bind def +/EEND/end load def +/CNT 0 def +/level1 0 def +/PBEGIN{ +/level1 save def +translate +div 3 1 roll div exch scale +neg exch neg exch translate +0 setgray +0 setlinecap +1 setlinewidth +0 setlinejoin +10 setmiterlimit +[]0 setdash +/setstrokeadjust where{ +pop +false setstrokeadjust +}if +/setoverprint where{ +pop +false setoverprint +}if +newpath +/CNT countdictstack def +userdict begin +/showpage{}def +}bind def +/PEND{ +clear +countdictstack CNT sub{end}repeat +level1 restore +}bind def +end def +/setpacking where{ +pop +setpacking +}if +%%EndResource +%%IncludeResource: font Times-Bold +%%IncludeResource: font Times-Italic +%%IncludeResource: font Times-Roman +%%IncludeResource: font Courier +%%IncludeResource: font Times-BoldItalic +%%IncludeResource: font NewCenturySchlbk-BoldItalic +%%IncludeResource: font NewCenturySchlbk-Roman +grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 +def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron +/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent +/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen +/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon +/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O +/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex +/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y +/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft +/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl +/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen +/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft +/logicalnot/minus/registered/macron/degree/plusminus/twosuperior +/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior +/ordmasculine/guilsinglright/onequarter/onehalf/threequarters +/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE +/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex +/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn +/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla +/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis +/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash +/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def +/NewCenturySchlbk-Roman@0 ENC0/NewCenturySchlbk-Roman RE +/NewCenturySchlbk-BoldItalic@0 ENC0/NewCenturySchlbk-BoldItalic RE +/Times-BoldItalic@0 ENC0/Times-BoldItalic RE/Courier@0 ENC0/Courier RE +/Times-Roman@0 ENC0/Times-Roman RE/Times-Italic@0 ENC0/Times-Italic RE +/Times-Bold@0 ENC0/Times-Bold RE +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 11/Times-Bold@0 SF(Mup V)195.888 43 Q(ersion 5.3 Statement Summary) +-1.1 E/F1 11/Times-Italic@0 SF(conte)36 56 Q(xt)-.22 E(staf)36 69 Q +(fs voices & staf)-.198 E(fs voices)-.198 E F0(:)A F1 -.165(ch)2.75 G +(or).165 E(d)-.407 E F0(;)2.75 E F1(....)2.75 E F0([)36 82 Q F1(staf)A +(fs voices & staf)-.198 E(fs voices)-.198 E F0(;)A F1(staf)2.75 E +(fs voices)-.198 E F0 2.75(]:)C F1 -.165(ch)C(or).165 E(d)-.407 E F0(;) +2.75 E F1(....)2.75 E F0(lyrics)36 95 Q F1(place staf)2.75 E(f)-.198 E +F0(:)2.75 E F1(time_valuelist)2.75 E F0([)2.75 E F1(ver)2.75 E(ses)-.11 +E F0 2.75(]")2.75 G F1(te)-2.75 E(xt)-.22 E F0(";)A F1(...)2.75 E +(linetype bartype)36 108 Q F0(pad)2.75 E F1(num ending_mark)2.75 E F0 +-.198(re)2.75 G(hearsal).198 E F1(fontfamily font)2.75 E F0(\()2.75 E F1 +(size)A F0(\))A F1 -.407(re)2.75 G(hear).407 E(sal_mark)-.11 E F0(mnum=) +2.75 E F1(num)A F0(=)2.75 E F1(ta)A(g)-.11 E F0(hidechanges)2.75 E F1 +(par)36 121 Q(ameter)-.165 E F0(=)A F1(value)A F0(multir)36 134 Q(est) +-.198 E F1(num)2.75 E F0(newscor)36 147 Q 2.75(el)-.198 G(eftmar)-2.75 E +(gin=)-.11 E F1(num)A F0(rightmar)2.75 E(gin=)-.11 E F1(num)A F0 +(newpage leftmar)36 160 Q(gin=)-.11 E F1(num)A F0(rightmar)2.75 E(gin=) +-.11 E F1(num)A(fontfamily font)36 173 Q F0(\()2.75 E F1(size)A F0(\))A +F1(modi\214er place staf)2.75 E(fs)-.198 E F0(dist)2.75 E F1(num)2.75 E +F0 2.75(!:)2.75 G F1(beat)A F0(")2.75 E F1(te)A(xt)-.22 E F0 2.75("t)C +(il)-2.75 E F1(num)2.75 E F0(m+)A F1(num)A F0(;)A F1(....)2.75 E F0 +(mussym \()36 186 Q F1(size)A/F2 11/Times-Roman@0 SF(\))A F1(place staf) +2.75 E(fs)-.198 E F0(:)2.75 E F1(beat)2.75 E F0(")2.75 E F1(mus_symbol)A +F0 2.75("t)C(il)-2.75 E F1(num)2.75 E F0(m+)A F1(num)A F0(;)A F1(....) +2.75 E(linetype)36 199 Q F0(phrase)2.75 E F1(place staf)2.75 E(fs)-.198 +E F0(:)2.75 E F1(beat til num)2.75 E F0(m+)A F1(num)A F0(;)A F1(....) +2.75 E F0(octa)36 212 Q -.11(ve)-.275 G F1(place staf)2.86 E(fs)-.198 E +F0(:)2.75 E F1(beat)2.75 E F0(")2.75 E F1(te)A(xt)-.22 E F0 2.75("t)C +(il)-2.75 E F1(num)2.75 E F0(m+)A F1(num)A F0(;)A F1(....)2.75 E F0 +(pedal)36 225 Q F1(place staf)2.75 E(fs)-.198 E F0(:)2.75 E F1(beat)2.75 +E F0 2.75(*;)2.75 G F1(....)A(cr)36 238 Q(es_mark place staf)-.407 E(fs) +-.198 E F0(:)2.75 E F1(beat til num)2.75 E F0(m+)A F1(num)A F0(;)A F1 +(....)2.75 E F0(midi)36 251 Q F1(staf)2.75 E(fs voices)-.198 E F0(:)2.75 +E F1(beat)2.75 E F0(")2.75 E F1(midi_k)A -.33(ey)-.11 G(wor).33 E(d) +-.407 E F0(=)A F1(value)A F0(";)A F1(....)2.75 E F0 -.198(ro)36 264 S +(ll).198 E F1(dir)2.75 E(ection staf)-.407 E(fnum voicenum)-.198 E F0 +(to)2.75 E F1(staf)2.75 E(fnum voicenum)-.198 E F0(:)2.75 E F1(beat)2.75 +E F0(;)2.75 E F1(....)2.75 E(printcmd location)36 277 Q F0(")2.75 E F1 +(te)A(xt)-.22 E F0(")A(title)36 290 Q F1(fontfamily font)2.75 E F0(\() +2.75 E F1(size)A F0 2.75(\)")C F1(te)-2.75 E(xt)-.22 E F0 2.75("")C F1 +(te)-2.75 E(xt)-.22 E F0 2.75("")C F1(te)-2.75 E(xt)-.22 E F0(")A F1 +(justifytype)36 303 Q F0(paragraph)2.75 E F1(fontfamily font)2.75 E F0 +(\()2.75 E F1(size)A F0 2.75(\)")C F1(te)-2.75 E(xt)-.22 E F0(")A F1 +(linetype)36 316 Q F0(line)2.75 E F1(location)2.75 E F0(to)2.75 E F1 +(location)2.75 E F0(with)2.75 E F1(fontfamily font)2.75 E F0(\()2.75 E +F1(size)A F0 2.75(\)")C F1(te)-2.75 E(xt)-.22 E F0(")A F1(linetype)36 +329 Q F0(cur)2.75 E -.11(ve)-.11 G F1(location)2.86 E F0(to)2.75 E F1 +(location)2.75 E F0(to)2.75 E F1(location ....)2.75 E(linetype)36 342 Q +F0(cur)2.75 E -.11(ve)-.11 G F1(location)2.86 E F0(to)2.75 E F1 +(location)2.75 E F0 -.22(bu)2.75 G(lge).22 E F1(num ....)2.75 E F0 +(de\214ne)36 355 Q F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME)-.297 E F0(\()A +F1(mac_par)A(ams)-.165 E F0(\))A F1(macr)2.75 E(o_de\214nition)-.495 E +F0(@)2.75 E(ifdef)36 368 Q F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME .....) +-.297 E F0(else)2.75 E F1(.....)2.75 E F0(endif)2.75 E(ifndef)36 381 Q +F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME .....)-.297 E F0(else)2.75 E F1 +(.....)2.75 E F0(endif)2.75 E(undef)36 394 Q F1(MA)2.75 E(CR)-.33 E(O_N) +-.44 E(AME)-.297 E F0(if)36 407 Q F1 -.22(ex)2.75 G(pr).22 E +(ession .....)-.407 E F0(else)2.75 E F1(.....)2.75 E F0(endif)2.75 E +(include ")36 420 Q F1(\214lename)A F0(")A -.275(fo)36 433 S(nt\214le ") +.275 E F1(\214lename)A F0(")A(//)36 446 Q F1(comment\212arbitr)2.75 E +(ary te)-.165 E(xt that will be ignor)-.22 E(ed.)-.407 E F0 -1.012(Va) +211.877 472 S(lues used in Mup statements)1.012 E F1(accidental)36 485 Q +F0(#)40.574 E F2(,)A F0(&)2.75 E F2(,)A F0(x)2.75 E F2(,)A F0(&&)2.75 E +F2 2.75(,o)C(r)-2.75 E F0(n)2.75 E F1(bartype)36 498 Q F0(bar)52.795 E +F2(,)A F0(dblbar)2.75 E F2(,)A F0 -.198(re)2.75 G(peatstart).198 E F2(,) +A F0 -.198(re)2.75 G(peatend).198 E F2(,)A F0 -.198(re)2.75 G(peatboth) +.198 E F2(,)A F0(endbar)2.75 E F2(,)A F0(in)2.75 E(visbar)-.44 E F2 2.75 +(,o)C(r)-2.75 E F0 -.198(re)2.75 G(start).198 E F1(beat)36 511 Q F2(num\ +ber from 0.0 to time signature denominator plus 1.0, optionally follo) +67.458 E(wed)-.275 E(by ho)122.4 524 Q 2.75(wm)-.275 G(an)-2.75 E 2.75 +(yg)-.165 G(race notes to back up from there, as a ne)-2.75 E -.055(ga) +-.165 G(ti).055 E .33 -.165(ve n)-.275 H(umber in parentheses,).165 E +(and an of)122.4 537 Q(fset as a signed number in square brack)-.275 E +(ets)-.11 E F1 -.165(ch)36 550 S(or).165 E(d)-.407 E F0(<<)61.309 E F1 +(conte)A(xt par)-.22 E(ameter=value)-.165 E F0(>> [)A F1 -.165(ch)C(or) +.165 E(d_style)-.407 E F0(])A F1(time_value pitc)2.75 E +(h\(es\) note_attrib)-.165 E(utes inter)-.22 E(-c)-.22 E(hor)-.165 E +(d_attr)-.407 E F2 -.495(Tu)122.4 563 S(plets speci\214ed by).495 E F0 +({)8.25 E F1 -.165(ch)2.75 G(or).165 E(d)-.407 E F0(;)2.75 E F1(....) +2.75 E F0(})2.75 E F1(side num tupstyle)2.75 E 2.75(,t)-.11 G(ime_value) +-2.75 E F0(;)2.75 E F2(On tablature staf)122.4 576 Q(f, the)-.275 E F1 +(pitc)2.75 E(h)-.165 E F2(is:)2.75 E F1(string fr)2.75 E(et)-.407 E F0 +(")2.75 E F1(bend)A F0(")A F1(bend)36 589 Q F0(full)65.016 E F2 2.75(,o) +C(r)-2.75 E F1(num)2.75 E F2(and/or a fraction as)2.75 E F1(num)2.75 E +F0(/)A F1(num)A -.165(ch)36 602 S(or).165 E(d_style)-.407 E F2 +(one or more \(semicolon-separated\) from the follo)35.646 E(wing:)-.275 +E F0(grace)122.4 615 Q F2(,)A F0(cue)2.75 E F2(,)A F0(xnote)2.75 E F2(,) +A F0(diam)2.75 E F2(,)A F0(with)2.75 E F1(withlist)2.75 E F2(,)A F0(pad) +2.75 E F1(num)2.75 E F2(,)A F0(slash)2.75 E F1(num)2.75 E F2(,)A F1 +(stemdir)2.75 E F2(,)A F0(len)2.75 E F1(num)2.75 E F2(,)A F0(dist)2.75 E +F1(num)2.75 E F2(,)A F0(ho)122.4 628 Q F1(num)2.75 E F2(,)A F0(hs ")2.75 +E F1(headshape)A F0(")A F2 2.75(,o)C(r)-2.75 E F0(=)2.75 E F1(ta)A(g) +-.11 E F2(Putting)122.4 641 Q F0(...)2.75 E F2(after the)2.75 E F0(]) +2.75 E F2(will repeat the)2.75 E F1 -.165(ch)2.75 G(or).165 E(d_style) +-.407 E F2(until)2.75 E F0([-])2.75 E F2(or end of measure.)2.75 E F1 +(clef)36 654 Q F0(tr)70.516 E(eble)-.198 E F2(,)A F0(soprano)2.75 E F2 +(,)A F0(mezzosoprano)2.75 E F2(,)A F0(alto)2.75 E F2(\(these ha)5.5 E +.33 -.165(ve d)-.22 H(ef).165 E(ault octa)-.11 E .33 -.165(ve o)-.22 H +2.75(f4).165 G(\))-2.75 E F0(tr)122.4 667 Q(eble8)-.198 E F2(,)A F0 +(tenor)2.75 E F2(,)A F0(baritone)2.75 E F2(,)A F0(bass)2.75 E F2 +(\(these ha)5.5 E .33 -.165(ve d)-.22 H(ef).165 E(ault octa)-.11 E .33 +-.165(ve o)-.22 H 2.75(f3).165 G(\))-2.75 E F0(fr)122.4 680 Q +(enchviolin)-.198 E F2(,)A F0(8tr)2.75 E(eble)-.198 E F2(\(these ha)2.75 +E .33 -.165(ve d)-.22 H(ef).165 E(ault octa)-.11 E .33 -.165(ve o)-.22 H +2.75(f5).165 G(\))-2.75 E F1(conte)36 693 Q(xt)-.22 E F0(scor)54.852 E +(e)-.198 E F2(,)A F0(staff)2.75 E F1(staf)2.75 E(fnum)-.198 E F2(,)A F0 +-.11(vo)2.75 G(ice).11 E F1(staf)2.75 E(fnum voicenum)-.198 E F2(,)A F0 +(music)2.75 E F2(,)A F0(top)2.75 E F2(,)A F0(bottom)2.75 E F2(,)A F0 +(top2)2.75 E F2(,)A F0(bottom2)2.75 E F2(,)A F0(header)122.4 706 Q F2(,) +A F0 -.275(fo)2.75 G(oter).275 E F2(,)A F0(header2)2.75 E F2(,)A F0 +-.275(fo)2.75 G(oter2).275 E F2(,)A F0(grids)2.75 E F2 2.75(,o)C(r)-2.75 +E F0(headshapes)2.75 E F1(cr)36 719 Q(es_mark)-.407 E F0(<)40.376 E F2 +(\(crescendo\) or)2.75 E F0(>)2.75 E F2(\(decrescendo\))2.75 E F1(dir)36 +732 Q(ection)-.407 E F0(up)47.086 E F2(or)2.75 E F0(do)2.75 E(wn)-.11 E +F1(ending_mark)36 745 Q F0(ending ")28.353 E F1(te)A(xt)-.22 E F0(")A F2 +(or)5.5 E F0(endending)2.75 E F1 -.22(ex)36 758 S(pr).22 E(ession)-.407 +E F2(can contain)39.98 E F0 2.75 +(de\214ned\(\) \(\) + - ~ ! * / % ^ & | << >> < > <= >= == != && || ?:) +2.75 F F1(\214lename)36 771 Q F2 +(path to a \214le on your system; uses MUPP)49.132 E -1.221(AT)-1.012 G +2.75(Ht)1.221 G 2.75<6f8c>-2.75 G(nd, if not in current directory)-2.75 +E(and not absolute path)122.4 784 Q EP +%%Page: 2 2 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 9/Times-Roman@0 SF 2.25(-2-)262.503 44.5 S/F1 11/Times-Italic@0 SF +(font)36 70.5 Q/F2 11/Times-Bold@0 SF -.198(ro)69.284 G(m).198 E/F3 11 +/Times-Roman@0 SF(,)A F2(ital)2.75 E F3(,)A F2(bold)2.75 E F3 2.75(,o)C +(r)-2.75 E F2(boldital)2.75 E F1(fontfamily)36 83.5 Q F2 -2.31 -.275 +(av a)41.784 H(ntgarde).275 E F3(,)A F2(bookman)2.75 E F3(,)A F2 +(courier)2.75 E F3(,)A F2(helv)2.75 E(etica)-.11 E F3(,)A F2(newcentury) +2.75 E F3(,)A F2(palatino, or times)2.75 E F1(fr)36 96.5 Q(et)-.407 E F3 +(number from 0 to 99)71.528 E F1(he)36 109.5 Q(x_data)-.22 E F3 -2.365 +-.275(ev e)46.294 H 2.75(nn).275 G(umber of he)-2.75 E(xadecimal digits) +-.165 E F1(inter)36 122.5 Q(-c)-.22 E(hor)-.165 E 12.942 +(d_attr tieslur_style)-.407 F F2(tie)2.75 E F1(dir)2.75 E(ection)-.407 E +F3(,)A F1(tieslur_style)2.75 E F2(slur)2.75 E F1(dir)2.75 E(ection)-.407 +E F3(,)A F2(bm)2.75 E F3(,)A F2(bm with staff)2.75 E F1(side)2.75 E F3 +(,)A F2(ebm)2.75 E F3(,)A F2(esbm)2.75 E F3(,)A F2(slope)122.4 135.5 Q +F1(num)2.75 E F3 2.75(,o)C(r)-2.75 E F2(alt)2.75 E F1(num)2.75 E +(interval)36 148.5 Q F2(perfect)52.179 E F3(,)A F2(major)2.75 E F3(,)A +F2(minor)2.75 E F3(,)A F2(augmented)2.75 E F3 2.75(,o)C(r)-2.75 E F2 +(diminished)2.75 E F1(justifytype)36 161.5 Q F2(justi\214ed)41.179 E F3 +2.75(,o)C(r)-2.75 E F2(ragged)2.75 E F1(linetype)36 174.5 Q F2(medium) +51.574 E F3(,)A F2(wide)2.75 E F3(,)A F2(dashed)2.75 E F3 2.75(,o)C(r) +-2.75 E F2(dotted)2.75 E F3(\(if omitted,)2.75 E F1(linetype)2.75 E F3 +(is narro)2.75 E(w\))-.275 E F1(location)36 187.5 Q F2(\()50.342 E F1 +(ta)2.75 E(g)-.11 E F2(.)A F1(X)A F2(+)2.75 E F1(steps)2.75 E F2 2.75 +(+t)2.75 G(ime)-2.75 E F1(time_value)2.75 E F2(,)A F1(ta)2.75 E(g)-.11 E +F2(.)A F1(Y)A F2(+)2.75 E F1(steps)2.75 E F2(\))2.75 E F1(mac_par)36 +200.5 Q(ams)-.165 E F3 +(comma-separated list of parameter names, same naming rules as)29.739 E +F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME)-.297 E(MA)36 213.5 Q(CR)-.33 E +(O_N)-.44 E(AME)-.297 E F3 +(upper case letters, digits, and/or underscores, be)14.141 E +(ginning with a letter)-.165 E F1(macr)36 226.5 Q(o_de\214nition)-.495 E +F3(arbitrary te)11.732 E(xt that will be used where)-.165 E -.165(ve) +-.275 G(r).165 E F1(MA)2.75 E(CR)-.33 E(O_N)-.44 E(AME)-.297 E F3 +(appears in input)2.75 E F1(midi_k)36 239.5 Q -.33(ey)-.11 G(wor).33 E +(d)-.407 E F3(an)24.921 E 2.75(yo)-.165 G 2.75(ft)-2.75 G(he follo)-2.75 +E(wing:)-.275 E F2(tempo=)122.4 252.5 Q F1(num)A F2(pr)46.262 E(ogram=) +-.198 E F1(num)A F2(parameter=)34.239 E F1(num)A F2(,)A F1(num)A F2 +(port=)4.418 E F1(num)A F2(on)122.4 265.5 Q -.11(ve)-.44 G(locity=).11 E +F1(num)A F2(offv)28.475 E(elocity=)-.11 E F1(num)A F2(channel=)26.825 E +F1(num)A F2(chanpr)38.914 E(essur)-.198 E(e=)-.198 E F1(num)A F2 +(seqnum=)122.4 278.5 Q F1(num)A F2(text=)38.914 E F1(te)A(xt)-.22 E F2 +(copyright=)61.156 E F1(te)A(xt)-.22 E F2(name=)33.645 E F1(te)A(xt)-.22 +E F2(instrument=)122.4 291.5 Q F1(num)A F2(mark)23.646 E(er=)-.11 E F1 +(te)A(xt)-.22 E F2(cue=)43.545 E F1(te)A(xt)-.22 E F2(hex=)62.982 E F1 +(he)A(x_data)-.22 E(modi\214er)36 304.5 Q F2(chord)49.737 E F3(,)A F2 +(analysis)2.75 E F3(,)A F2(\214gbass)2.75 E F3 2.75(,o)C 2.75(ro)-2.75 G +(mitted)-2.75 E F1(mus_symbol)36 317.5 Q F3 +(musical symbol; see chart on page 6 for complete list.)32.016 E F1 +(note_attrib)36 330.5 Q(utes)-.22 E F3(one or more of the follo)20.004 E +(wing:)-.275 E F1(tieslur_style)2.75 E F2(~)2.75 E F1(dir)2.75 E(ection) +-.407 E F3(\(tie\),)2.75 E F1(tieslur_style)2.75 E F2 2.75(<>)2.75 G F1 +(dir)A(ection\) \(slur\),)-.407 E F2(?)122.4 343.5 Q F3(\(small\),)2.75 +E F2(^)2.75 E F1(pitc)A(h)-.165 E F3(\(bend\),)2.75 E F2(hs ")2.75 E F1 +(headshape)A F2(")A F3 2.75(,o)C(r)-2.75 E F2(=)2.75 E F1(ta)A(g)-.11 E +(num)36 356.5 Q F3(some number; v)67.458 E(alid v)-.275 E +(alues depend on where it appears)-.275 E F1(octave)36 369.5 Q F3 +(number from)57.69 E F2(0)2.75 E F3(to)2.75 E F2(9)2.75 E F3 +(or one or more)2.75 E F2(+)2.75 E F3(or)2.75 E F2(-)2.75 E F3(signs) +2.75 E F1(par)36 382.5 Q(ameter)-.165 E F3 +(See parameter table on page 5 for complete list)40.739 E F1(pitc)36 +395.5 Q(h)-.165 E F3(letter from)64.565 E F2(a)2.75 E F3(to)2.75 E F2(g) +2.75 E F3 2.75(,o)C(ptionally follo)-2.75 E(wed by)-.275 E F1 +(accidental)2.75 E F3(and/or)2.75 E F1(octave)2.75 E F3(,)A(or)122.4 +408.5 Q F2(r)2.75 E F3(\(rest\),)2.75 E F2(s)2.75 E F3(\(space\),)2.75 E +F2(us)2.75 E F3(\(uncollapseable space\), or)2.75 E F2 -.11(rp)2.75 G(t) +.11 E F3(\(repeat\))2.75 E F1(place)36 421.5 Q F2(abo)62.574 E -.11(ve) +-.11 G F3(,).11 E F2(belo)2.75 E(w)-.11 E F3 2.75(,o)C(r)-2.75 E F2 +(between)2.75 E F3 2.75(.I)C(f)-2.75 E F2(between)2.75 E F3(,)A F1(staf) +2.75 E(fs)-.198 E F3(must be of the form)2.75 E F1(num)2.75 E F2(&)A F1 +(num)A(printcmd)36 434.5 Q F2(left)46.679 E F3(,)A F2(right)2.75 E F3(,) +A F2(center)2.75 E F3(,)A F2(print)2.75 E F3(or)2.75 E F2(postscript) +2.75 E F1 -.407(re)36 447.5 S(hear).407 E(sal_mark)-.11 E F2(let)16.649 +E F3(,)A F2(num)2.75 E F3(,)A F2(mnum)2.75 E F3 2.75(,o)C(r)-2.75 E F2 +(")2.75 E F1(te)A(xt)-.22 E F2(")A F1(side)36 460.5 Q F2(abo)68.679 E +-.11(ve)-.11 G F3(or)2.86 E F2(belo)2.75 E(w)-.11 E F1(size)36 473.5 Q +F3(number from 1 to 100 \(points\))69.9 E F1(staf)36 486.5 Q(fnum)-.198 +E F3(number from 1 to 40)48.703 E F1(staf)36 499.5 Q(fs)-.198 E F3 +(number from 1 to 40, or comma-separated list of dash-separated ranges) +63.366 E F1(stemdir)36 512.5 Q F2(up)53.4 E F3(or)2.75 E F2(do)2.75 E +(wn)-.11 E F1(stemlen)36 525.5 Q F3 2.75(an)52.795 G(umber)-2.75 E 2.75 +(,i)-.44 G 2.75(ns)-2.75 G(tepsizes)-2.75 E F1(steps)36 538.5 Q F3 2.75 +(an)64.4 G +(umber of stepsizes, where a stepsize is 1/2 the distance between tw) +-2.75 E 2.75(os)-.11 G(taf)-2.75 E 2.75(fl)-.275 G(ines)-2.75 E F1 +(string)36 551.5 Q F3(in tablature chord:)60.726 E F1(pitc)2.75 E 2.75 +(ha)-.165 G(ccidental)-2.75 E F3(follo)2.75 E(wed by zero or more)-.275 +E F2(')2.75 E F3(marks)2.75 E F1(tab_string)36 564.5 Q F3 +(list of tablature strings. Each includes a)41.168 E F1(pitc)2.75 E(h) +-.165 E F3 2.75(,o)C(ptional)-2.75 E F2(')2.75 E F3(marks, and optional) +2.75 E F1(octave)2.75 E(.)-.165 E(ta)36 577.5 Q(g)-.11 E F3 2.75(al) +72.452 G -.275(ow)-2.75 G(er case letter).275 E 2.75(,o)-.44 G 2.75(ra) +-2.75 G 2.75(nu)-2.75 G(nderscore follo)-2.75 E(wed by lo)-.275 E +(wer case letters, digits, and/or underscores)-.275 E +(Each has 6 associated v)122.4 590.5 Q(alues:)-.275 E F2(x)2.75 E F3(,)A +F2(y)2.75 E F3(,)A F2(n)2.75 E F3(,)A F2(s)2.75 E F3(,)A F2(e)2.75 E F3 +2.75(,a)C(nd)-2.75 E F2(w)2.75 E F3(Prede\214ned tag names are)122.4 +603.5 Q F2(_win)2.75 E F3(,)A F2(_page)2.75 E F3 2.75(,a)C(nd)-2.75 E F2 +(_cur)2.75 E F1(te)36 616.5 Q(xt)-.22 E F3(arbitrary te)70.736 E +(xt; use)-.165 E F2(\\")2.75 E F3(to include quotes,)2.75 E F2(\\f\() +2.75 E F1(fontfamily font)A F2(\))A F3(to change font,)2.75 E F2(\\s\() +2.75 E F1(num)A F2(\))A F3(to change size,)2.75 E F2(\\\()122.4 629.5 Q +F1(xx)A F2(\))A F3(to include special characters,)2.75 E F2(\\v\()2.75 E +F1(num)A F2(\))A F3(for v)2.75 E(ertical motion,)-.165 E F2(\\:)2.75 E +F3(to toggle piling,)2.75 E F2(\\|)2.75 E F3(or)2.75 E F2(\\^)2.75 E F3 +(for alignment)2.75 E F1(time_value)36 642.5 Q F2(1/4)38.132 E F3(,)A F2 +(1/2)2.75 E F3(,)A F2(1)2.75 E F3(,)A F2(2)2.75 E F3(,)A F2(4)2.75 E F3 +(,)A F2(8)2.75 E F3(,)A F2(16)2.75 E F3(,)A F2(32)2.75 E F3(,)A F2(64) +2.75 E F3(,)A F2(128)2.75 E F3 2.75(,o)C(r)-2.75 E F2(256)2.75 E F3 +(with optional dots,)2.75 E F2(+)2.75 E F3(or)2.75 E F2(-)2.75 E F3 2.75 +(;o)C(r)-2.75 E F2(m)2.75 E F3(\(measure\))2.75 E F1(tieslur_style)36 +655.5 Q F2(dotted)32.621 E F3(,)A F2(dashed)2.75 E F3 2.75(,o)C 2.75(ro) +-2.75 G(mitted)-2.75 E F1(tuplet)36 668.5 Q F3(See)61.342 E F1 -.165(ch) +2.75 G(or).165 E(d)-.407 E(tupstyle)36 681.5 Q F2(y)52.179 E F3(\(al) +2.75 E -.11(wa)-.11 G(ys print brack).11 E(et\),)-.11 E F2(n)2.75 E F3 +(\(no number or brack)2.75 E(et\),)-.11 E F2(num)2.75 E F3 +(\(number only\), or omitted \(def)2.75 E(ault\))-.11 E F1(value)36 +694.5 Q F3(See information about the item to the left of the = for v) +62.574 E(alid v)-.275 E(alues)-.275 E F1(ver)36 707.5 Q(ses)-.11 E F3 +(number or comma-separated list of dash-separated ranges)59.021 E F1 +(voicenum)36 720.5 Q F2(1)44.248 E F3(,)A F2(2)2.75 E F3 2.75(,o)C(r) +-2.75 E F2(3)2.75 E F1 56.161(voices comma-separ)36 733.5 R +(ated list of dash-separ)-.165 E(ated r)-.165 E(ang)-.165 E +(es of voicenum)-.11 E F3(s)A F1(withlist)36 746.5 Q F3 +(comma-separated list of the follo)53.994 E(wing:)-.275 E F2(.)2.75 E F3 +(\(stacatto\),)2.75 E F2(-)2.75 E F3(\(le)2.75 E -.055(ga)-.165 G(to\),) +.055 E F2(^)2.75 E F3(\(accent\),)2.75 E F2(>)2.75 E F3(\(accent\), or) +2.75 E F2(")2.75 E F1(te)A(xt)-.22 E F2(")A F1(X)36 759.5 Q F2(x)79.679 +E F3(,)A F2(w)2.75 E F3 2.75(,o)C(r)-2.75 E F2(e)2.75 E F3 +(\(x, west, or east\))5.5 E F1(Y)36 772.5 Q F2(y)80.284 E F3(,)A F2(n) +2.75 E F3 2.75(,o)C(r)-2.75 E F2(s)2.75 E F3(\(y)5.5 E 2.75(,n)-.715 G +(orth, or south\))-2.75 E EP +%%Page: 3 3 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 9/Times-Roman@0 SF 2.25(-3-)262.503 44.5 S/F1 11/Times-Bold@0 SF +-.275(Fo)209.985 71.5 S(nt/size changes in text strings).275 E/F2 11 +/Times-Roman@0 SF 1.76 -.88(To c)36 99.5 T +(hange font inside a quoted te).88 E(xt string, use)-.165 E F1(\\f\() +2.75 E/F3 11/Times-Italic@0 SF(fontfamily font)A F1(\))A F2(or)2.75 E F1 +(\\f\()2.75 E F3(font_abbr)A F1(\))A F2(from the table:)2.75 E F3 +182.957(font fontfamily)44.558 113.5 R F2 -.22(av)86.732 127.5 S(antg) +-.055 E 13.75(arde bookman courier helv)-.055 F 13.75(etica ne)-.165 F +13.75(wcentury palatino times)-.275 F .44 LW 455.397 132.25 36 132.25 DL +(rom)36 143.5 Q/F4 11/Courier@0 SF 41.025(AR BR)50.264 F 32.048(CR HR) +39.347 F 39.941(NR PR)48.593 F(TR)32.939 E F1(bold)36 157.5 Q F4 41.025 +(AB BB)47.195 F 32.048(CB HB)39.347 F 39.941(NB PB)48.593 F(TB)32.939 E +F3(ital)36 171.5 Q F4 41.025(AI BI)53.311 F 32.048(CI HI)39.347 F 39.941 +(NI PI)48.593 F(TI)32.939 E/F5 11/Times-BoldItalic@0 SF(boldital)36 +185.5 Q F4 41.025(AX BX)33.753 F 32.048(CX HX)39.347 F 39.941(NX PX) +48.593 F(TX)32.939 E F1(\\f\(pr)36 199.5 Q -.165(ev)-.198 G(ious\)).165 +E F2(or)2.75 E F1(\\f\(PV\))2.75 E F2(changes to pre)2.75 E(vious font.) +-.275 E F1(\\s\()2.75 E F3(num)A F1(\))A F2(changes to point size)2.75 E +F3(num)2.75 E F2 2.75(,1t)C 2.75(o1)-2.75 G(00.)-2.75 E F1(\\s\(+)36 +213.5 Q F3(num)A F1(\))A F2(increases the size by)2.75 E F3(num)2.75 E +F2(while)2.75 E F1(\\s\(-)2.75 E F3(num)A F1(\))A F2(decreases it by) +2.75 E F3(num)2.75 E F2(points.)2.75 E F1(\\s\(PV\))36 227.5 Q F2(or) +2.75 E F1(\\s\(pr)2.75 E -.165(ev)-.198 G(ious\)).165 E F2(re)2.75 E +-.165(ve)-.275 G(rts to pre).165 E(vious size.)-.275 E F1 +(Mup command line ar)212.19 255.5 Q(guments)-.11 E(-c)36 283.5 Q F3(num) +2.75 E F2(combine)113.761 E F3(num)2.75 E F2 +(or more measures of rest into multirest)2.75 E F1(-C)36 297.5 Q F2 +(used with -E, k)132.395 E(eep comments rather than discarding them)-.11 +E F1(-d)36 311.5 Q F3(num)2.75 E F2(turn on deb)112.529 E(ugging le)-.22 +E -.165(ve)-.275 G(l).165 E F3(num)2.75 E F1(-D)36 325.5 Q F3(MA)2.75 E +(CR)-.33 E(O)-.44 E F1(=)A F3(def)A F2(de\214ne)72.819 E F3(MA)2.75 E +(CR)-.33 E(O)-.44 E F2(as)2.75 E F3(def)2.75 E F1(-e)36 339.5 Q F3 +(err\214le)2.75 E F2(put error output into)105.819 E F3(err\214le)2.75 E +F1(-E)36 353.5 Q F2(just e)133 E +(xpand macros and "include" \214les and write result to standard output) +-.165 E F1(-f)36 367.5 Q F3(out\214le)2.75 E F2(put output into)106.424 +E F3(out\214le)2.75 E F1(-F)36 381.5 Q F2(put output into \214le, deri) +133.616 E(ving output \214le name from input \214le name)-.275 E F1(-m) +36 395.5 Q F3(midi\214le)2.75 E F2(generate MIDI output into)95.424 E F3 +(midi\214le)2.75 E F1(-M)36 409.5 Q F2(generate MIDI output, deri) +129.953 E .33 -.165(ve \214)-.275 H(le name).165 E F1(-o)36 423.5 Q F3 +(pa)2.75 E -.11(ge)-.11 G(list).11 E F2(only print pages in)97.47 E F3 +(pa)2.75 E -.11(ge)-.11 G(list).11 E F2 2.75(,c)C +(an be list of numbers, or)-2.75 E F1(odd)2.75 E F2(or)2.75 E F1 -2.53 +-.165(ev e)2.75 H(n).165 E(-p)36 437.5 Q F3(num)2.75 E F2 +(start numbering pages at)112.529 E F3(num)2.75 E F1(-r)36 451.5 Q F2 +(print share)135.453 E -.11(wa)-.275 G(re re).11 E(gistration form)-.165 +E F1(-s)36 465.5 Q F3(staf)2.75 E(\215ist)-.198 E F2 +(print only the staf)101.716 E(fs listed in)-.275 E F3(staf)2.75 E +(\215ist)-.198 E F2 2.75(;a)C(dd)-2.75 E F1(v)2.75 E F3(N)A F2 +(to restrict to v)2.75 E(oice)-.22 E F3(N)2.75 E F1(-v)36 479.5 Q F2 +(print v)134.837 E(ersion number and e)-.165 E(xit)-.165 E F1(-x)36 +493.5 Q F3(M)2.75 E F1(,)A F3(N)A F2 -.165(ex)112.837 G(tract measures) +.165 E F3(M)2.75 E F2(through)2.75 E F3(N)2.75 E F2 2.75(,n)C -2.475 +-.165(eg a)-2.75 H(ti).165 E .33 -.165(ve r)-.275 H(elati).165 E .33 +-.165(ve t)-.275 H 2.75(oe).165 G(nd, 0 for pickup)-2.75 E F1 +(Mupdisp commands)236.572 521.5 Q F3(num)36 549.5 Q F2 194.074 +( go)B(to page)2.75 E F3(num)2.75 E F1(+)36 563.5 Q F2 +(or or or )2.75 E(forw)86.923 E(ard 1/8")-.11 E +F1(f)36 577.5 Q F2(or or or )2.75 E(forw)87.088 +E(ard 1")-.11 E F1(-)36 591.5 Q F2 +(or or or )2.75 E(backw)66.32 E(ard 1/8") +-.11 E F1(b)36 605.5 Q F2(or or or )2.75 E +(backw)79.124 E(ard 1")-.11 E F1(h)36 619.5 Q F2(or)2.75 E F1(?)2.75 E +F2(help)225.721 E F1(m)36 633.5 Q F2 +(toggle between full and partial page modes)242.837 E F1(n)36 647.5 Q F2 +(ne)245.884 E(xt page)-.165 E F1(p)36 661.5 Q F2(pre)245.884 E +(vious page)-.275 E F1(q)36 675.5 Q F2(or)2.75 E F1(ZZ)2.75 E F2(quit) +216.547 E F1(r)36 689.5 Q F2(repaint the screen)247.116 E EP +%%Page: 4 4 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 9/Times-Roman@0 SF 2.25(-4-)262.503 44.5 S/F1 11/Times-Bold@0 SF +(Mup P)244.591 70.5 Q(arameters)-.11 E .32 LW 578.6 74.5 36 74.5 DL/F2 8 +/Times-Roman@0 SF -.12(Pa)57.964 86.5 S 27.964(rameter Score).12 F(Staf) +12 E 16(fV)-.2 G 10(oice Hd/Ft)-17.032 F -.888(Va)130.812 G(lid V).888 E +137.96(alues Def)-.888 F(ault)-.08 E 578.6 90.5 36 90.5 DL 578.6 92.5 36 +92.5 DL/F3 8/Times-Bold@0 SF(abo)40 104.5 Q -.08(ve)-.08 G(order).08 E +F2 27.984<8383>49.004 G F3(mussym,octa)53.036 E -.08(ve)-.2 G +(,dyn&othertext&chord,lyrics,ending,r).08 E 97.84(eh as)-.144 F(listed)2 +E 578.6 108.5 36 108.5 DL(addtranspose)40 120.5 Q F2 27.984<8383>42.164 +G F3(up)53.036 E F2(or)2 E F3(do)2 E(wn)-.08 E F2 2(,f)C(ollo)-2 E +(wed by)-.2 E/F4 8/Times-Italic@0 SF(interval)2 E F2(and)2 E F4(num)2 E +F2(up perfect 1)153.232 E 578.6 124.5 36 124.5 DL F3(barstyle)40 136.5 Q +F2 111.804<8363>60.396 G(omma-separated lists of staf)-111.804 E +(fs or dash-separated ranges)-.2 E 578.6 140.5 36 140.5 DL F3(beamslope) +40 152.5 Q F2 27.984<8383>51.948 G 50.308<8330>-.072 G +(.0 to 1.0, 0.0 to 45.0)-50.308 E(1.0,20.0)221.392 E 578.6 156.5 36 +156.5 DL F3(beamstyle)40 168.5 Q F2 27.984<8383>53.732 G 50.308<8363> +-.072 G(omma-separated list of)-50.308 E F4(time_values)2 E F2 +(that add up to a measure)2 E 578.6 172.5 36 172.5 DL F3(belo)40 184.5 Q +-.08(wo)-.08 G(rder).08 E F2 27.984<8383>49.004 G F3(mussym,octa)53.036 +E -.08(ve)-.2 G 115.696(,dyn&othertext&chord,lyrics,pedal as).08 F +(listed)2 E 578.6 188.5 36 188.5 DL(betweenorder)40 200.5 Q F2 27.984 +<8383>40.852 G F3 159.856(mussym,dyn&othertext&chord,lyrics as)53.036 F +(listed)2 E 578.6 204.5 36 204.5 DL(bottommar)40 216.5 Q(gin)-.08 E F2 +111.804<8330>38.7 G(.0 to pageheight minus 0.5 inches)-111.804 E +(0.5 inches)178.512 E 578.6 220.5 36 220.5 DL F3(brace)40 232.5 Q F2 +111.804<8363>68.844 G(omma-separated list of staf)-111.804 E +(fs or dash-separated ranges)-.2 E 578.6 236.5 36 236.5 DL F3(brack)40 +248.5 Q(et)-.08 E F2 111.804<8363>61.812 G(omma-separated list of staf) +-111.804 E(fs or dash-separated ranges)-.2 E 578.6 252.5 36 252.5 DL F3 +(cancelk)40 264.5 Q(ey)-.08 E F2 27.984<8383>54.7 G F3(y)53.036 E F2(or) +2 E F3(n)2 E F2(n)270.728 E 578.6 268.5 36 268.5 DL F3(chorddist)40 +280.5 Q F2 23.052 27.984<83832030>55.5 H(to 50 \(stepsizes\))-25.984 E +(3)231.848 E 578.6 284.5 36 284.5 DL F3(clef)40 296.5 Q F2 312.892 +27.984<83832074>75.956 H(reble)-27.984 E F3(tr)242.552 296.5 Q(eble,tr) +-.144 E(eble8)-.144 E F2(,)A F3(8tr)A(eble)-.144 E F2(,)A F3(fr)A +(enchviolin)-.144 E F2(,)A F3(soprano)A F2(,)A F3(mezzosoprano)A F2(,)A +F3(alto)A F2(,)A F3(tenor)A F2(,)A F3(baritone)A F2(,)A F3(bass)A 578.6 +300.5 36 300.5 DL(def)40 312.5 Q(oct)-.2 E F2 27.984<8383>67.268 G +50.308<8330>-.072 G(to 9)-48.308 E(based on clef)271.616 E 578.6 316.5 +36 316.5 DL F3(dist)40 328.5 Q F2 23.052 27.984<83832030>75.5 H +(to 50 \(stepsizes\))-25.984 E(2)231.848 E 578.6 332.5 36 332.5 DL F3 +(di)40 344.5 Q(vision)-.08 E F2 111.804<834d>61.348 G(IDI di)-111.804 E +(vision, 1 to 1536 \(ticks per quarter note\))-.2 E(192)134.728 E 578.6 +348.5 36 348.5 DL F3(dyndist)40 360.5 Q F2 23.052 27.984<83832030>62.604 +H(to 50 \(stepsizes\))-25.984 E(2)231.848 E 578.6 364.5 36 364.5 DL F3 +(endingstyle)40 376.5 Q F2<83>49.276 E F3(top)111.804 E F2(,)A F3(barr)2 +E(ed)-.144 E F2 2(,o)C(r)-2 E F3(gr)2 E(ouped)-.144 E F2(top)210.352 E +578.6 380.5 36 380.5 DL F3(\214rstpage)40 392.5 Q F2 111.804<8331>58.172 +G(to 5000)-109.804 E(1)259.616 E 578.6 396.5 36 396.5 DL F3 -.2(fo)40 +408.5 S(nt).2 E F2 .316 27.984<83832083>74.372 H F3 -.144(ro)-8.048 G(m) +.144 E F2(,)A F3(bold)2 E F2(,)A F3(ital)2 E F2 2(,o)C(r)-2 E F3 +(boldital)2 E F2(rom)202.64 E 578.6 412.5 36 412.5 DL F3 -.2(fo)40 424.5 +S(ntfamily).2 E F2 .316 27.984<83832083>52.596 H(times)281.792 E F3 +-1.68 -.2(av a)242.552 424.5 T(ntgarde).2 E F2(,)A F3(bookman)2 E F2(,)A +F3(courier)2 E F2(,)A F3(helv)2 E(etica)-.08 E F2(,)A F3(newcentury)2 E +F2(,)A F3(palatino)2 E F2 2(,o)C(r)-2 E F3(times)2 E 578.6 428.5 36 +428.5 DL(gridfr)40 440.5 Q(et)-.144 E F2 23.052 27.984<83832032>61.436 H +(to 99)-25.984 E(4)267.616 E 578.6 444.5 36 444.5 DL F3(gridsatend)40 +456.5 Q F2<83>51.5 E F3(y)111.804 E F2(or)2 E F3(n)2 E F2(n)270.728 E +578.6 460.5 36 460.5 DL F3(gridswher)40 472.5 Q(eused)-.144 E F2 27.984 +<8383>34.316 G F3(y)53.036 E F2(or)2 E F3(n)2 E F2(n)270.728 E 578.6 +476.5 36 476.5 DL F3(gridscale)40 488.5 Q F2 23.052 27.984<83832030> +57.284 H(.1 to 10.0)-27.984 E(1.0)255.616 E 578.6 492.5 36 492.5 DL F3 +-.08(ke)40 504.5 S(y).08 E F2 312.892 27.984<83832063>76.028 H(major) +-25.984 E F4(pitc)242.552 504.5 Q(h)-.12 E F3(major)2 E F2(or)2 E F3 +(minor)2 E F2 2(;o)C 2(r0t)-2 G 2(o7)-2 G F3(#)A F2(or)2 E F3(&)2 E F2 +(and optional)2 E F3(major)2 E F2(or)2 E F3(minor)2 E 578.6 508.5 36 +508.5 DL(label2)40 520.5 Q F2 27.984<8383>67.5 G F3(")53.036 E F4(te)A +(xt)-.16 E F3(")A F2("")269.568 E 578.6 524.5 36 524.5 DL F3(label)40 +536.5 Q F2 27.984<8383>71.5 G F3(")53.036 E F4(te)A(xt)-.16 E F3(")A F2 +24("")269.568 G 578.6 540.5 36 540.5 DL F3(leftmar)40 552.5 Q(gin)-.08 E +F2 111.804<8330>52.036 G(.0 to page)-111.804 E(width minus 0.5 inches) +-.2 E(0.5 inches)180.488 E 578.6 556.5 36 556.5 DL F3(lyricsalign)40 +568.5 Q F2 23.052 27.984<83832030>52.388 H(.0 to 1.0)-27.984 E(0.25) +259.616 E 578.6 572.5 36 572.5 DL F3(lyricsf)40 584.5 Q(ont)-.2 E F2 +27.984<8383>55.708 G F3 -.144(ro)53.036 G(m).144 E F2(,)A F3(bold)2 E F2 +(,)A F3(ital)2 E F2 2(,o)C(r)-2 E F3(boldital)2 E F2(rom)202.64 E 578.6 +588.5 36 588.5 DL F3(lyricsf)40 600.5 Q(ontfamily)-.2 E F2 312.892 +27.984<83832074>33.932 H(imes)-27.984 E F3 -1.68 -.2(av a)242.552 600.5 +T(ntgarde).2 E F2(,)A F3(bookman)2 E F2(,)A F3(courier)2 E F2(,)A F3 +(helv)2 E(etica)-.08 E F2(,)A F3(newcentury)2 E F2(,)A F3(palatino)2 E +F2 2(,o)C(r)-2 E F3(times)2 E 578.6 604.5 36 604.5 DL(lyricssize)40 +616.5 Q F2 23.052 27.984<83832031>56.844 H(to 100 \(points\))-25.984 E +(12)236.728 E 578.6 620.5 36 620.5 DL F3(measnum)40 632.5 Q F2<83>55.06 +E F3(y)111.804 E F2(or)2 E F3(n)2 E F2(n)270.728 E 578.6 636.5 36 636.5 +DL F3(measnumf)40 648.5 Q(ont)-.2 E F2<83>41.484 E F3 -.144(ro)111.804 G +(m).144 E F2(,)A F3(bold)2 E F2(,)A F3(ital)2 E F2 2(,o)C(r)-2 E F3 +(boldital)2 E F2(rom)202.64 E 578.6 652.5 36 652.5 DL F3(measnumf)40 +664.5 Q(ontfamily)-.2 E F2 401.644<8374>19.708 G(imes)-401.644 E F3 +-1.68 -.2(av a)242.552 664.5 T(ntgarde).2 E F2(,)A F3(bookman)2 E F2(,)A +F3(courier)2 E F2(,)A F3(helv)2 E(etica)-.08 E F2(,)A F3(newcentury)2 E +F2(,)A F3(palatino)2 E F2 2(,o)C(r)-2 E F3(times)2 E 578.6 668.5 36 +668.5 DL(measnumsize)40 680.5 Q F2 111.804<8331>42.62 G +(to 100 \(points\))-109.804 E(11)236.728 E 578.6 684.5 36 684.5 DL 578.6 +74.5 578.6 684.5 DL 36 74.5 36 684.5 DL 526.392 74.5 526.392 684.5 DL +236.552 74.5 236.552 684.5 DL 205.88 74.5 205.88 684.5 DL 175.808 74.5 +175.808 684.5 DL 144.456 74.5 144.456 684.5 DL 114.24 74.5 114.24 684.5 +DL EP +%%Page: 5 5 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 9/Times-Roman@0 SF 2.25(-5-)262.503 47 S .32 LW 545.656 65 36 65 DL +/F1 8/Times-Roman@0 SF -.12(Pa)48.472 77 S 20.164(rameter Score).12 F +(Staf)14.816 E 18.888(fV)-.2 G 13.228(oice Hd/Ft)-19.92 F -.888(Va) +119.356 G(lid V).888 E 124.936(alues Def)-.888 F(ault)-.08 E 545.656 81 +36 81 DL 545.656 83 36 83 DL/F2 8/Times-Bold@0 SF(noteheads)40 95 Q F1 +-8.6 30.8<8383832073>36.432 H(tring containing 1 or 7 headshape names) +-30.8 E("norm")131.576 E 545.656 99 36 99 DL F2(numbermr)40 111 Q(pt) +-.08 E F1 30.8<8383>26.296 G F2(y)57.8 E F1(or)2 E F2(n)2 E F1(y)244.888 +E 545.656 115 36 115 DL F2(ontheline)40 127 Q F1 30.8<838383>39.096 G F2 +(y)24.2 E F1(or)2 E F2(n)2 E F1(y)244.888 E 545.656 131 36 131 DL F2 +(pack)40 143 Q(exp)-.08 E F1 122.2<8330>42.288 G(.0 to 1.0)-122.2 E(0.8) +233.776 E 545.656 147 36 147 DL F2(packfact)40 159 Q F1 122.2<8330> +41.328 G(.0 to 10.0)-122.2 E(1.0)229.776 E 545.656 163 36 163 DL F2(pad) +40 175 Q F1 -8.6 30.8<838383202d>57.76 H(5.0 to 50.0)-30.8 E(0.0)227.112 +E 545.656 179 36 179 DL F2(pageheight)40 191 Q F1 122.2<8332>33.32 G +(.0 to 24.0 inches or 5.0 to 61.0 cm)-122.2 E(11.0 inches)150.672 E +545.656 195 36 195 DL F2(pagesize)40 207 Q F1<83>42.216 E F2(letter) +122.2 E 2(,l)-.736 G(egal, \215sa, hal\215etter)-2 E 2(,a)-.736 G +(4, a5, a6)-2 E F1(then optional)2 E F2(portrait)2 E F1(or)2 E F2 +(landscape)2 E F1(letter)23.048 E 545.656 211 36 211 DL F2(pagewidth)40 +223 Q F1 122.2<8332>35.096 G(.0 to 24.0 inches or 5.0 to 61.0 cm)-122.2 +E(8.5 inches)150.672 E 545.656 227 36 227 DL F2(panelsper)40 239 Q(page) +-.08 E F1 122.2<8331>21.4 G(or 2)-120.2 E(1)245.336 E 545.656 243 36 243 +DL F2(pedstyle)40 255 Q F1 30.8<8383>42.656 G F2(line)57.8 E F1(,)A F2 +(pedstar)2 E F1 2(,o)C(r)-2 E F2(alt pedstar)2 E F1(line)172.448 E +545.656 259 36 259 DL F2(printmultnum)40 271 Q F1 30.8<8383>21.76 G F2 +(y)57.8 E F1(or)2 E F2(n)2 E F1(y)244.888 E 545.656 275 36 275 DL F2 +-.144(re)40 287 S(hstyle).144 E F1 30.8<8383>43.696 G F2(boxed)57.8 E F1 +(,)A F2(cir)2 E(cled)-.144 E F1 2(,o)C(r)-2 E F2(plain)2 E F1(box) +186.584 E(ed)-.12 E 545.656 291 36 291 DL F2 -.144(re)40 303 S(lease) +.144 E F1 -8.6 30.8<8383832030>47.256 H(to 500 \(milliseconds\))-28.8 E +(20)190 E 545.656 307 36 307 DL F2 -.144(re)40 319 S(stcombine).144 E F1 +122.2<8332>29.032 G(to 1000)-120.2 E(not set)233.776 E 545.656 323 36 +323 DL F2 -.144(re)40 335 S(stsymmult).144 E F1 30.8<8383>28.144 G F2(y) +57.8 E F1(or)2 E F2(n)2 E F1(n)244.888 E 545.656 339 36 339 DL F2 +(rightmar)40 351 Q(gin)-.08 E F1 122.2<8330>28.96 G(.0 to page)-122.2 E +(width minus 0.5 inches)-.2 E(0.5 inches)154.648 E 545.656 355 36 355 DL +F2(scale)40 367 Q F1 122.2<8330>54.216 G(.1 to 10.0)-122.2 E(1.0)229.776 +E 545.656 371 36 371 DL F2(scor)40 383 Q(epad)-.144 E F1<83>40.136 E/F3 +8/Times-Italic@0 SF(num)122.2 E F1 2(,o)C(r)-2 E F3(num)2 E F2(,)A F3 +(num)A F1 2(,n)C -1.8 -.12(eg a)-2 H(ti).12 E .24 -.12(ve p)-.2 H +(ageheight to pageheight \(stepsizes\)).12 E(2,2)59.184 E 545.656 387 36 +387 DL F2(scor)40 399 Q(esep)-.144 E F1<83>41.92 E F3(num)122.2 E F1 2 +(,o)C(r)-2 E F3(num)2 E F2(,)A F3(num)A F1 2(,6t)C 2(op)-2 G +(ageheight \(stepsizes\))-2 E(12,20)118.912 E 545.656 403 36 403 DL F2 +(size)40 415 Q F1 .8 30.8<83832083>58.216 H 2(1t)-9.4 G 2(o1)-2 G +235.776(00 12)-2 F 545.656 419 36 419 DL F2(staf\215ines)40 431 Q F1 +30.8<8383>40.432 G F2(1)57.8 E F1(,)A F2(1n)2 E F1(,)A F2(5)2 E F1(,)A +F2(5n)2 E F1(,)A F2 2(5d)2 G(rum)-2 E F1(,)A F2 2(1d)2 G(rum)-2 E F1 2 +(,o)C(r)-2 E F2(tab \()2 E F3(tab_strings)A F2(\))A F1(5)101.768 E +545.656 435 36 435 DL F2(staffpad)40 447 Q F1 25 30.8<8383206e>42.656 H +-1.8 -.12(eg a)-30.8 H(ti).12 E .24 -.12(ve p)-.2 H +(ageheight to pageheight \(stepsizes\)).12 E(0)119.176 E 545.656 451 36 +451 DL F2(staffs)40 463 Q F1 122.2<8331>52.44 G(to 40)-120.2 E(1)241.776 +E 545.656 467 36 467 DL F2(staffscale)40 479 Q F1 25 30.8<83832030> +39.112 H(.1 to 10.0)-30.8 E(1.0)229.776 E 545.656 483 36 483 DL F2 +(staffsep)40 495 Q F1 25 30.8<83832036>44.44 H +(to pageheight \(stepsizes\))-28.8 E(10)178.904 E 545.656 499 36 499 DL +F2(stemlen)40 511 Q F1 -8.6 30.8<8383832030>44.44 H +(.0 to 100.0 \(stepsizes\))-30.8 E(7.0)190.008 E 545.656 515 36 515 DL +F2(stemshorten)40 527 Q F1 -8.6 30.8<8383832030>28.888 H +(.0 to 2.0 \(stepsizes\))-30.8 E(1.0)198.008 E 545.656 531 36 531 DL F2 +(swingunit)40 543 Q F1 -8.6 30.8<8383832074>37.312 H(ime v)-30.8 E +(alue or nothing)-.2 E(nothing)195.536 E 545.656 547 36 547 DL F2 +(sylposition)40 559 Q F1 25 30.8<8383202d>34.2 H(100 to 100 \(points\)) +-30.8 E(-5)200.224 E 545.656 563 36 563 DL F2(tabwhitebox)40 575 Q F1 +30.8<838383>28.432 G F2(y)24.2 E F1(or)2 E F2(n)2 E F1(n)244.888 E +545.656 579 36 579 DL F2(time)40 591 Q F1<83>55.552 E F2(common)122.2 E +F1(,)A F2(cut)2 E F1(or)2 E F3(N)2 E F2(/)A F3(D)A F1(where)2 E F3(N)2 E +F1(is 1 to 99 and)2 E F3(D)2 E F1(is)2 E F2(1)2 E F1(,)A F2(2)2 E F1(,)A +F2(4)2 E F1(,)A F2(8)2 E F1(,)A F2(16)2 E F1(,)A F2(32)2 E F1 2(,o)C(r) +-2 E F2(64)2 E F1(4/4)32.24 E 545.656 595 36 595 DL F2(timeunit)40 607 Q +F1 30.8<838383>41.768 G F3(time_value)24.2 E F1(\(can include dots\))2 E +F3(D)169.576 E F1(of time sig)2 E 545.656 611 36 611 DL F2(topmar)40 623 +Q(gin)-.08 E F1 122.2<8330>34.736 G(.0 to pageheight minus 0.5 inches) +-122.2 E(0.5 inches)152.672 E 545.656 627 36 627 DL F2(transpose)40 639 +Q F1 30.8<8383>37.768 G F2(up)57.8 E F1(or)2 E F2(do)2 E(wn)-.08 E F1 2 +(,f)C(ollo)-2 E(wed by)-.2 E F3(interval)2 E F1(and)2 E F3(num)2 E F1 +(up perfect 1)127.392 E 545.656 643 36 643 DL F2(units)40 655 Q F1<83> +53.76 E F2(inches)122.2 E F1(or)2 E F2(cm)2 E F1(inches)221.784 E +545.656 659 36 659 DL F2(visible)40 671 Q F1 30.8<838383>48.872 G F2(y) +24.2 E F1(,)A F2(n)2 E F1 2(,o)C(r)-2 E F2(wher)2 E(eused)-.144 E F1(y) +202.592 E 545.656 675 36 675 DL F2(vcombine)40 687 Q F1 25 30.8 +<8383206c>37.768 H(ist of staf)-30.8 E(fs, plus optional)-.2 E F2(noo)2 +E -.08(ve)-.08 G(rlap).08 E F1(,)A F2(shar)2 E(eone)-.144 E F1 2(,o)C(r) +-2 E F2 -.08(ove)2 G(rlap).08 E F1 2(,o)C 2(rn)-2 G 32.888 +(othing nothing)-2 F 545.656 691 36 691 DL F2(vscheme)40 703 Q F1 30.8 +<8383>41.776 G F2(1)57.8 E F1(,)A F2(2o)2 E F1(,)A F2(2f)2 E F1(,)A F2 +(3o)2 E F1 2(,o)C(r)-2 E F2(3f)2 E F1(1)206.008 E 545.656 707 36 707 DL +F2(war)40 719 Q(n)-.12 E F1<83>53 E F2(y)122.2 E F1(or)2 E F2(n)2 E F1 +(y)244.888 E 545.656 723 36 723 DL 545.656 65 545.656 723 DL 36 65 36 +723 DL 493.656 65 493.656 723 DL 229.656 65 229.656 723 DL 196.056 65 +196.056 723 DL 162.456 65 162.456 723 DL 128.856 65 128.856 723 DL +95.256 65 95.256 723 DL EP +%%Page: 6 6 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 9/Times-Roman@0 SF 2.25(-6-)262.503 47 S/F1 8/Times-Roman@0 SF +(Music symbols can be used in te)36 61 Q(xt strings by using)-.12 E/F2 8 +/Times-Bold@0 SF(\\\()2 E/F3 8/Times-Italic@0 SF(symbol_name)A F2(\))A +F1 2(.P)C(re\214x with)-2 E F2(sm)2 E F1(for smaller v)2 E(ersion.)-.12 +E 70 157 443 443 -589 589 14.4 663 PBEGIN +%%BeginDocument: muschar.ps +%%BoundingBox: 70 157 513 746 +/boxheight 62 def +/boxwidth 40 def +/nameheight 10 def +/tmpstring 50 string def +/flagsep 1.6 300 mul def + +/Times-Roman findfont nameheight 2 sub scalefont setfont +/prm { + /yoff exch def + /xoff exch def + /sym exch def + /name sym tmpstring cvs def + /realboxheight boxheight extra add def + + save + xoff yoff translate + + % draw box + newpath + 0 0 moveto + boxwidth 0 lineto + boxwidth realboxheight lineto + 0 realboxheight lineto + closepath + stroke + + % print name of music character + gsave + nameheight 4 sub + realboxheight name stringwidth pop sub 2 div 4 add moveto + 55 rotate + 0 0.25 0.75 setrgbcolor + name show + grestore + % display the music character + boxwidth 2 div nameheight add + realboxheight nameheight sub 2 div + 1.0 sym cvx exec + restore +} def + +/offset 72 def +/col 0 def +/row 11 def +/extra 0 def +/extraoffset 0 def + +% go to next display slot on the page and show one music character +/showone { + col boxwidth mul offset add row boxheight mul + extra sub extraoffset sub prm + /col col 1 add def + % go to next column when current one is full + col 11 ge { /col 0 def /row row 1 sub def } if + % one row has to be extra tall + row 5 eq { /extra 28 def } if + row 4 eq { /extraoffset 28 def /extra 0 def } if +} def + +/gclef showone +/fclef showone +/cclef showone +/dblwhole showone +/1n showone +/2n showone +/4n showone +/upflag showone +/dnflag showone +/qwhrest showone +/dwhrest showone +/1rest showone +/2rest showone +/4rest showone +/8rest showone +/16rest showone +/32rest showone +/64rest showone +/128rest showone +/256rest showone +/ll1rest showone +/ll2rest showone +/dot showone +/nat showone +/sharp showone +/flat showone +/dblsharp showone +/dblflat showone +/xnote showone +/dwhdiamond showone +/diamond showone +/filldiamond showone +/up2n showone +/dn2n showone +/up4n showone +/dn4n showone +/com showone +/cut showone +/begped showone +/pedal showone +/endped showone +/dnbow showone +/upbow showone +/wedge showone +/uwedge showone +/ferm showone +/uferm showone +/sign showone +/coda showone +/mor showone +/invmor showone +/turn showone +/invturn showone +/acc_gt showone +/acc_hat showone +/acc_uhat showone +/tr showone +/leg showone +/rr showone +/dim showone +/halfdim showone +/triangle showone +/measrpt showone +/copyright showone +/up8n showone +/dn8n showone +/up16n showone +/dn16n showone +/up32n showone +/dn32n showone +/up64n showone +/dn64n showone +/up128n showone +/dn128n showone +/up256n showone +/dn256n showone +/dwhrighttriangle showone +/righttriangle showone +/fillrighttriangle showone +/udwhrighttriangle showone +/urighttriangle showone +/ufillrighttriangle showone +/dwhrectangle showone +/rectangle showone +/fillrectangle showone +/dwhisostriangle showone +/isostriangle showone +/fillisostriangle showone +/dwhpiewedge showone +/piewedge showone +/fillpiewedge showone +/dwhsemicircle showone +/semicircle showone +/fillsemicircle showone +/dwhslashhead showone +/slashhead showone +/fillslashhead showone +/blankhead showone +showpage +%%EndDocument +end PEND 9 90 115 115 -669 669 471.8 734 PBEGIN +%%BeginDocument: extlist.ps +%%BoundingBox: 9 90 124 759 +makeExtEncoding +/Ext-Times-Roman /Times-Roman makeExtendedFont +/do1char { + 15 y moveto + /Ext-Times-Roman findfont 7 scalefont setfont + show + /Times-Roman findfont 7 scalefont setfont + 50 y moveto + show + 110 y moveto + show + /y y 7 sub def +} def +save +1.000000 1.000000 scale +newpath +10 91 moveto +10 758 lineto +123 758 lineto +123 91 lineto +closepath +stroke +/y 748 def +( ) (exclamdown) ( ) do1char +( ) (questiondown) (.) do1char +( ) (sterling) (") do1char +( ) (yen) (#) do1char +(\301\301) (quotedblleft) ($) do1char +(\302\302) (quotedblright) (-) do1char +(<<) (guillemotleft) (%) do1char +(>>) (guillemotright) (&) do1char +( ) (guilsinglleft) (') do1char +( ) (guilsinglright) (\() do1char +( ) (dagger) (\)) do1char +( ) (daggerdbl) (*) do1char +( ) (grave) (/) do1char +( ) (acute) (0) do1char +( ) (macron) (1) do1char +( ) (breve) (2) do1char +( ) (dotaccent) (3) do1char +( ) (dieresis) (4) do1char +( ) (ring) (5) do1char +( ) (cedilla) (6) do1char +( ) (hungarumlaut) (7) do1char +( ) (ogonek) (8) do1char +( ) (caron) (9) do1char +( ) (emdash) (:) do1char +( ) (space) (\177) do1char +( ) (AE) (;) do1char +( ) (ae) (<) do1char +( ) (ordfeminine) (=) do1char +( ) (ordmasculine) (>) do1char +(L/) (Lslash) (?) do1char +(l/) (lslash) (@) do1char +(O/) (Oslash) (A) do1char +(o/) (oslash) (B) do1char +( ) (OE) (C) do1char +( ) (oe) (D) do1char +( ) (dotlessi) (E) do1char +(ss) (germandbls) (F) do1char +(A') (Aacute) (G) do1char +(a') (aacute) (H) do1char +(A^) (Acircumflex) (I) do1char +(a^) (acircumflex) (J) do1char +(A:) (Adieresis) (K) do1char +(a:) (adieresis) (L) do1char +(A`) (Agrave) (M) do1char +(a`) (agrave) (N) do1char +(Ao) (Aring) (O) do1char +(ao) (oring) (P) do1char +(A~) (Atilde) (Q) do1char +(a~) (atilde) (R) do1char +(C,) (Ccedilla) (S) do1char +(c,) (ccedilla) (T) do1char +(E') (Eacute) (U) do1char +(e') (eacute) (V) do1char +(E^) (Ecircumflex) (W) do1char +(e^) (ecircumflex) (X) do1char +(E:) (Edieresis) (Y) do1char +(e:) (edieresis) (Z) do1char +(E`) (Egrave) ([) do1char +(e`) (egrave) (\\) do1char +(I') (Iacute) (]) do1char +(i') (iacute) (^) do1char +(I^) (Icircumflex) (_) do1char +(i^) (icircumflex) (`) do1char +(I:) (Idieresis) (a) do1char +(i:) (idieresis) (b) do1char +(I`) (Igrave) (c) do1char +(i`) (igrave) (d) do1char +(N~) (Ntilde) (e) do1char +(n~) (ntilde) (f) do1char +(O') (Oacute) (g) do1char +(o') (oacute) (h) do1char +(O^) (Ocircumflex) (i) do1char +(o^) (ocircumflex) (j) do1char +(O:) (Odieresis) (k) do1char +(o:) (odieresis) (l) do1char +(O`) (Ograve) (m) do1char +(o`) (ograve) (n) do1char +(O~) (Otilde) (o) do1char +(o~) (otilde) (p) do1char +(Sv) (Scaron) (q) do1char +(sv) (scaron) (r) do1char +(U') (Uacute) (s) do1char +(u') (uacute) (t) do1char +(U^) (Ucircumflex) (u) do1char +(u^) (ucircumflex) (v) do1char +(U:) (Udieresis) (w) do1char +(u:) (udieresis) (x) do1char +(U`) (Ugrave) (y) do1char +(u`) (ugrave) (z) do1char +(Y:) (Ydieresis) ({) do1char +(y:) (ydieresis) (|) do1char +(Zv) (Zcaron) (}) do1char +(zv) (zcaron) (~) do1char +( ) (bullet) (+) do1char +showpage +restore +%%Pages: 1 +%%EndDocument +end PEND/F4 9/NewCenturySchlbk-BoldItalic@0 SF -2.502(Ar kkr)266.832 +688.5 R 2.583(aE)-.099 G(nter)-2.583 E(pr)-.153 E(ises)-.126 E/F5 9 +/NewCenturySchlbk-Roman@0 SF -1.125(P.)285.201 701.5 S .666 -.333(O. B) +1.125 H(ox 315).333 E -.675(Wa)249.885 714.5 S(rrenville).675 E 2.502 +(,I)-.162 G 2.502(L6)-2.502 G 10.008(0555 USA)-2.502 F(http://www) +263.785 727.5 Q(.arkkra.com)-1.125 E(support@arkkra.com)268.249 740.5 Q +EP +%%Trailer +end +%%EOF diff --git a/mup/docs/overview.txt b/mup/docs/overview.txt new file mode 100644 index 0000000..e05762e --- /dev/null +++ b/mup/docs/overview.txt @@ -0,0 +1,143 @@ + + MUP Overview + + 1. OVERVIEW OF THE MUP MUSIC PUBLICATION PROGRAM + + Mup is a shareware program for printing music. It takes an + input file containing ordinary (ASCII) text describing + music, and produces PostScript output for printing the + musical score described by the input. Arkkra Enterprises + was established to make Mup readily available at low cost to + anyone who would like to use Mup. + + A Mup input file can contains several kinds of sections or + contexts. The description of musical notes is given in the + "music" context. There are contexts for defining page + headers and footers. There are also several contexts used + for setting various parameters. For example, there is a + "score" context in which global aspects are listed, such as + the number of staffs, the time signature, page margins, etc. + It is also possible to set parameters for individual staffs + and even individual voices. (Each staff can have up to three + independent voices.) Any parameter that can be set for an + individual voice can also be set for a staff, and any + parameter that can be set for a staff can be set for the + score as a whole. The actual value used for a given + parameter is obtained by searching from the most specific + (i.e., voice), to the most general (i.e., score) until a + value is found. All values are given a default at the score + level, so that everything will always resolve to some value. + Parameters include items such as: + + - Number of staffs + + - Number of voices per staff + + - Time signature + + - Key signature + + - Clef + + - Transposition amount + + - Whether to use beams or flags on notes of 8th note + duration or shorter + + - Margins + + - Which staffs to group with braces or brackets, and what + labels to use + + - How tightly to pack output together, both horizontally + and vertically. + + - Whether to print measure numbers + + Mup can handle up to 40 parallel staffs. Each staff can have + a different key signature, clef, and transposition value. + Staffs can be 5-line, 1-line, or tablature (1 to 9 lines). + It is possible to print a subset of staffs or voices. + Guitar grids are supported. + + Music data is organized into measures. Each measure consists + of data for one or more voices followed by a bar line. Data + for each voice consists of one or more chords. Each chord + consists of a time value and one or more notes, and possibly + additional items associated with the chord. To minimize + input, an omitted time value defaults to being the same as + the previous time value, and if the notes are omitted, the + notes of the previous chord are used. There are also two + special kinds of "notes": rests and space. Time values from + double whole through 256th are supported, as well as + tuplets, and any number of dots. Notes are specified by a + letter 'a' to 'g', which may be followed by an accidental + (#, &, x, &&, or n for sharp, flat, double sharp, double + flat, and natural respectively), and an optional octave. The + octave can be an absolute number 0 to 9 or one or more + or + - signs to indicate one or more octaves above or below the + default octave. It is also possible to specify that octave + marks are to be printed. + + Individual notes or entire chords can be tied or slurred to + notes in the following chord. Slides, bends, and phrase + marks can also be specified. Mup takes care of all details + of drawing appropriate curves and splitting the curves + across scores or pages if necessary. + + Grace notes can be specified before any chord. It is also + possible to specify that notes are to be printed in "cue" + (small) size rather than regular size, or that "X" or + diamond shaped notes are to be used. Shaped note used in + "Sacred Harp" music are also supported. + + Each measure ends with a bar line. There are several types + of bars: an ordinary bar, a double bar, a heavy bar to end + the song, and bars with repeat signs. There is also an + "invisible bar" which allows for organizing the input into + bars without having the bar lines printed on the output. + + First and subsequent endings can be specified at bar lines. + Rehearsal marks can be requested at any bar line. + + Macros can be defined to minimize input or improve + readability. There is a generalized "if" clause that lets + you produce different outputs based on macro values. It is + also possible to "include" one file in another. + + Lyrics can be specified for zero or more verses, above, + below or between staffs. You can control the font and size + used for the lyrics. + + Music symbols or words can be placed relative to staffs and + notes. This may include musical marks such as fermatas and + accents, as well as words to indicate tempo or dynamics, + etc. + + Since both the input and output of Mup are ASCII text files, + it is easy to write programs to do various transformations. + For example, a program could be written to move voices from + one staff to another, or any sort of PostScript filter + program could be used on the output. + + Mup will optionally provide output in standard Musical + Instrument Digital Interface (MIDI) format, for performance + rather than PostScript output for printing. + + While Mup itself bucks the trend of graphical, mouse-driven + input, it has proven to be a very useful and powerful method + of capturing the complexities of musical notation, and there + is a companion program, called Mupmate, that provides a + graphical interface on top of Mup for those who are more + comfortable with that kind of interface. The use of ordinary + text input and PostScript output make it largely device + independent. Mup was designed and written by people who are + both musicians and computer programmers. The result is a + program that provides the capability to produce full- + featured, very high quality musical scores with a minimum of + effort. It is available ready-to-run for selected computer + operating systems, and source code is also available so that + it can be run on most platforms that have a C compiler. You + can get a copy of Mup to try out with no obligation, and if + you like it, the registration fee is far lower than the + price of most music publication software. diff --git a/mup/docs/register.txt b/mup/docs/register.txt new file mode 100644 index 0000000..a7773aa --- /dev/null +++ b/mup/docs/register.txt @@ -0,0 +1,28 @@ +Mup is SHAREWARE. You can try out a copy for free, but if you decide +to keep and use it, you must register by filling out the form below +and sending the form and cash, check, or money order to: + Arkkra Enterprises + P. O. Box 315 + Warrenville, IL 60555 USA + +Name______________________________________________________________ + +Address___________________________________________________________ + +City_____________________________ State/Province__________________ + +Zip code/Postal code_____________________ Country_________________ + +Email address (please print clearly)______________________________ + +How did you find out about Mup?___________________________________ + +__________________________________________________________________ + +___Linux ___ Windows/MS-DOS ___Mac ___Other____________________ + +Would you like to join the Mup users mailing list? ___ Yes ___ No + +___ Mup Version 5.3 Registrations.........................$29 each + (Illinois residents, add $2.18 sales tax) +(For credit card payment, see http://www.arkkra.com/doc/credtcrd.html) diff --git a/mup/docs/sample.mup b/mup/docs/sample.mup new file mode 100644 index 0000000..e568452 --- /dev/null +++ b/mup/docs/sample.mup @@ -0,0 +1,576 @@ + + +//********************************************************************** +// NOTE: +// +// This is a sample Mup input file. This file is intended to demonstrate +// lots of the features of Mup, including advanced features. +// In most cases, you'll probably only need to use a few basic features, +// so your input file will usually be a lot simpler. +// +//********************************************************************** + + +// header to go on first page +header + title (18) "Sample Song to Show What Mup Can Do" + title palatino ital (12) "This is a subtitle" + title "Text: Ann Onymous" "Tune: Arthur Unknown" + title "" "(1995)" + +// header for subsequent pages +header2 + title "Sample Songs" "This is the title" "page \% of \#" + +// footer for first page +footer + // use a printing command other than "title" to show how others work + center nl "This is a sample of a Mup footer" + // leave a blank line + title (12) " " + + title (11) "Published by Arkkra Enterprises" \ + "P. O. Box 315 Warrenville, IL 60555" \ + "http://www.arkkra.com" + +// footer for subsequent pages +footer2 + print nl "This is a sample remark at the bottom of the page" + +// top/top2/bottom/bottom2 are like header/header2/footer/footer2 except +// they can be changed later; for example, you could use header/header2 for +// the whole song, but have a new top/top2 for each section of the song. + +// to be printed right below the header on this page (the first page) +top + title (13) "First Movement" +// to be printed right below the header2 on later pages +top2 + title "First movement" + +// set some score-wide parameters +score + staffs = 9 + key = c minor + time = 9/8 + + // beam things a dotted quarter at a time, and beam across rests + // have the main beams group together notes a dotted quarter at a + // time, but have subgroupings an 8th note at a time; also, beam + // across rests + beamstyle = (8,8,8), (8,8,8), (8,8,8) r + + // put bracket to left of top 2 staffs, and bottom 2, with labels + bracket = 1-2 ("Choir", "Ch"), 7-8 ("Guitar", "Gtr") + + // put brace on keyboard's staffs + brace = 5-6 ("keyboard", "Kbd") + + // bar the staffs 5 and 6 together, and 7 and 8 together + barstyle = 5-6, 7-8 + + // put rehearsal marks in circles, instead of the default rectangles + rehstyle = circled + + // make a little smaller than normal + scale = 0.77 + + // pack notes together + packexp = 0.7 + packfact = 0.75 + + // set the margins, allowing choice depending on whether -DBIGMARGINS + // is used on the command line or not + ifdef BIGMARGINS + topmargin = 1.0 + bottommargin = 1.1 + leftmargin = 1 + rightmargin = 1 + else + topmargin = 0.8 + bottommargin = 0.8 + leftmargin = 0.7 + rightmargin = 0.6 + endif + + // make sure chord marks are a ways away from staffs + chorddist = 4 + + // make sure other things are a ways away too + dist = 3 + + // spread scores and staffs apart more than normal + scoresep = 14, 24 + scorepad = 5 + staffsep = 14 + staffpad = 2 + + // label endings above staffs that are grouped by brace or bracket + endingstyle = grouped + + // use palatino fonts by default, in 14 point + fontfamily = palatino + font = rom + size = 14 + + // put lyrics in helvetica italics, 11 point + lyricsfontfamily = helvetica + lyricsfont = ital + lyricssize = 11 + + // print measure numbers at the beginning of each score + // in Helvetica italics + measnumfontfamily = helvetica + measnumfont = ital + measnumsize = 9 + measnum = y + + // When there are chords, print guitar grids with them. To put them + // at the end of the song we would use gridsatend. If we wanted + // to make them bigger or smaller, we could set "gridscale". + gridswhereused = y + + // If the lowest fret used is 3 or more, use "N fr" notation instead + // of showing the whole guitar neck up to that point in the grid. + // The default value of this is 4, and it can be turned off. + gridfret = 3 + + +//set some things for particular staffs +staff 2 + clef = bass + +staff 3 + label = "foghorn\nin G\(smflat)" + staffscale = 0.8 // make this staff a little smaller + clef = baritone + transpose = down dim 5 + // make staff 3 visible only when there is something on it + visible = whereused + + // set different default octave + defoct = 4 + +staff 4 + // make staff 4 a 1-line staff, with a "drum clef" + stafflines = 1 drum + +staff 5 + // Use three voices on staff 5. Allow the stems of the top and bottom + // voices (1 and 2) to float to whichever way is appropriate. (We + // could use 2o to force their stems to be in opposite directions.) + // Voice 3 is an extra voice, typically in the middle, whose stems can + // go either way. + vscheme = 3f + +staff 6 + clef = bass + + // use dotted quarter for default time unit instead of + // the normal time signature denominator + timeunit = 4. + +staff 7 + vscheme = 2f + +staff 8 + // Make staff 8 a tablature staff for standard guitar. This + // automatically makes the preceding staff (7) a "tabnote" staff, + // meaning its notes will be derived from staff 8 automatically, + // unless overriden. + stafflines = tab + + // make fret numbers more readable by putting a white background there + tabwhitebox = y + + vscheme = 2f // allow two voices on this tab staff + +staff 9 + // On staff 9, use "shaped notes". Each scale degree uses a different + // shape of note head. + label = "Soprano" + noteheads = "isostri semicirc diam righttri norm rect pie" + +// define a macro to allow saying "DRUM" instead of "4:" for the 4th staff +define DRUM 4: @ + +grids + // define grids to be printed with guitar chords + "Cm" "- (3 5 5 4 3)" + "G:9 7" "3 x o o o 5" + "Go7" "o 1 2 o 2 o" + "G" "3 x o o o 3" + +// now do musical data +music + +// put a tempo mark above staffs 1 and 6, and set MIDI tempo to 92 +// quarter notes per minute + rom above 1,6 : 1 "Andante"; + midi all: 0 "tempo = 92"; +// set the instruments to use for MIDI + midi 1-2: 0 "channel=5"; 0 "program=52"; 0 "onvelocity=92"; + midi 3: 0 "channel=6"; 0 "program=109"; 0 "onvelocity=61"; + midi 4: 0 "channel=10"; // percussion channel +// set onvelocity to accent the top note + midi 5-6: 0 "channel=11"; 0 "program=1"; 0 "onvelocity=104,88"; + midi 5 2: 0 "channel=11"; + midi 7: 0 "channel=14"; 0 "program=25"; 0 "onvelocity=83"; + +// Note that lines of input within a given measure can be entered in any order. +// It is usually a good idea to enter music data a staff at a time from top +// to bottom, just to make it easy to keep track of, although Mup makes no +// such requirement. You may choose to intersperse other things like lyrics +// and phrase marks, or do them all at once before or after the music data, +// or in whatever order you choose. + +// Also note that you can indent things any way you want in your Mup +// input file, and can put extra blank spaces almost anywhere +// except in the middle of a word. + +// For MIDI purposes, the first two measures get played an extra time +// before the Coda, so put them inside a macro. +define FIRST2MEASURES + +// staff 1, three dotted quarter notes, second chord same as the first + 1 1: 4.ceg;;dfb; + +// staff 2, dotted quarter, two eighths with a rest between, dotted quarter + 2: 4.c;8c;r;e;4.f; + +// phrase on staff 2 from beginning note to first count of next measure + phrase 2: 1 til 1m+1; + +// two verses of lyrics between top two staffs +// use "|" to align the first syllables 8 points left of the notes' centers + lyrics between 1&2: 4.;;; "-8|These are the"; "-8|This is verse"; + +// a grace note and an accent on staff 3 + 3: [grace; slash 1]c#; [with >] 2.f#;4.r; + +// measure rest for staff 4 + DRUM mr; + +// staff 5, voice 1, begins with duplet, also has a tied note + 5 1: {4c+;g;}2,4.; 4.c+;4f+~;16;; + +// second voice for staff 5 + 5 2: 2.c;4.d; + +// third voice for staff 5 starts with a "space", nothing printed; force +// horizontal offsets (ho) on two of the notes to fine tune their spacing + 5 3: 4.s; [ho 3.5]8e;f;g; [ho 3]an; 4; + +// staff 6, some notes an octave or two away from the default octave + 6: 4.c-c--;;d-d--; + +// put piano pedal mark at the bottom + pedal below 6: 1;6; + +// show the fret numbers on guitar strings on the tablature staff + 8: 4. a3d1g0; 8 a3; e'3; a3; 4. d0g2b3e1; + +// Print music theory analysis symbols at counts 1 and 7. The ":" makes the +// following space-separated items be stacked on top of each other. + rom analysis above 5: 1 "i"; 7 "VII:6 #5"; + +// print figured bass numbers below count 7; the slash goes through the "5" + rom figbass below 6: 7 "6 5/"; + + 9: 4.c+; 8e+; c+; e+; 4.f+; + lyrics 9: 2.+4.; "ah_"; + +// ordinary bar line, with a reherasal letter + bar reh let + + + +// next measure + 1: 2.c+gc;4.r; + 2: 2.ce;4.r; + +// lyrics with an underscore + // This time, since the time values of the lyrics match those + // of the music, we'll let Mup derive the time values, + // rather than specifying them. Notice that we are chanting multiple + // syllables on the last word, so we show that they are to be treated + // as one syllable by separating them by a special \(space) character + // instead of simple space. + lyrics between 1&2: [1] "words!_"; [2] "two\(space)oh\(space)yes."; + +// include a note with a double flat + 3: 2.f&&;4.r; + +// you can specify a pitch for a 1-line staff, even though all notes will be +// placed on the line. The pitch will be used for MIDI output, if you use +// the -m option to Mup to get a MIDI file instead of printed output. + DRUM 4.f&;2.r; + +// because of the beamstyle setting, the 16th notes here are joined in pairs +// by both beams, but only one beam joins all six + 5 1: 2.c++;4.r; + 5 2: 8e;g;e; 16g;e;g;e;g;e; 4.r; + 6: 2.c- alt 2;c;4.r; + pedal below 6: 1;6*; + +// print 3 tremelo slashes on this chord + 8: [slash 3] 2. d1g0b1e3; 4.r; + + 9: 2.e+; 4.r; + +// at count 9.9 (almost the dblbar), back up 19 stepsizes and print this coda +// indication, including the actual coda symbol; do this in italics of font +// size 13 (but turn off the italics for the symbol), and above all the staffs + ital(13) all: 9.9[-19] "To coda \f(TR)\(coda)"; + + // double bar + dblbar +@ // end the macro definition of the first measures +// Now call the macro for the first measures + FIRST2MEASURES + + + +// start a new score. Normally, Mup will place things +// as best it can, but you can force things if you like. +newscore + +// now more music data +music + + + // set location tags on the two notes, then draw a wavy line between + // them saying that it is a glissando + 1: 2.c =h; 4.g =k; + wavy line (h.e+3, h.y) to (k.w-3, k.y) with ital (11) "gliss." + 2: 4.e; 8..; 32f;8g;4.c; + +// a crescendo mark + < below 2: 3 til 7.5; + +// trill the foghorn from count 1 to 7; put a "turn" symbol above the note +// at count 8. For MIDI, specify exactly how to play it. + ifndef MIDI + 3: 2..d&; 4d; + mussym 3: 1 "tr" til 7; 8 "turn"; + else + 3: 16d&;e;d;e;d;e;d;e;d;e;d;e;d;e; {d;e;d;c;d;}5; + endif + + 4: [slash 2] 2.c; [with .]4.c-; + 5: 4.ceg;;; + +// a dynamic mark + times boldital between 5&6: 7 "ff"; + +// roll up on first chord, down on second, default (up) on third + roll up 5: 1; + roll down 5: 4; + roll 5: 7; + +// the <> indicates a slur + 6: 2.c e?;8e<>;4c; + +// For the second note, "bend" the previous note up 1/2 step by stretching +// the E string. Then bend to a full step, and release back to normal. + 8 1: 4.e5; e "1/2"; 8e "full"; 4e ""; + +// Put some notes in the second tab voice. These will be translated to the +// the second voice of the tabnote staff above. + 8 2: 4.g0; 4; 8; 4.; + + 9: 8c+; b; an; g; c; d; 4.e; + +// chord symbols will be transposed if the music is transposed. +// In this particular example, transposition is not in effect + bold chord above all: 1 "Cm"; + + bar ending "1." + + + +// two measures of rest + multirest 2 + repeatend ending "2." + + +staff 4 +// From now on, staff 4 (the one-line staff) will have two voices with stems +// that are always opposing. Set it so that the notes will not be on the line +// but rather above and below it. + vscheme = 2o + ontheline = n +music + midi 4 2: 0 "channel=10"; + +// Define a macro with parameters for printing a chord name at a given count. +// Note that the chord name is passed in and then the ` ` cause it to be +// put in quotes. +define K(COUNT, NAME) bold chord all: COUNT `NAME`; @ + +// Define a "map" for chord-at-a-time input. (By "chord" here we mean a group +// of notes, not the symbolic chord name as above.) Since all the voices in +// the choir have the same rhythm from now on, it's convenient to use this +// method of input instead of the usual voice-at-a-time method. Set it up +// to enter bass and tenor on staff 2, then alto and soprano on staff 1. +define M [ 2; 2; 1; 1 ] @ + + + K(1,Cm) // print a C minor chord at count 1 + +// assign all the notes for staffs 1 and 2, using the map. Each goes to its +// proper octave according to defoct. + M: 4.cgce; ceeg; cgce; + +// Put phrase marks on each staff, from count 1 until count 7 of the next +// measure. We didn't specify "above" or "below", so Mup chooses the side. + phrase 1,2: 1 til 1m+7; + +// Increase the size of the lyrics by 3 points. This will carry forward to +// the end of the song unless changed again. Also, use the non-ASCII +// character n-tilde, indicated by \(n~). If you can type non-ASCII characters +// directly on your keyboard, you can do that instead of using this notation. + lyrics between 1&2: "\s(+3)Ma-\(n~)a-na"; + +// put the last note's accidental in parentheses, since it is just a +// reminder to the player that this accidental is still in force + 3: 4.an; b; a(n); + +// Use X-shaped notes on the top voice. Use the "..." to show that this +// applies for the rest of this measure, not just the first chord. + 4 1: [xnote]... 4.; ; 8;;; + 4 2: 4.; ; ; + +// Beam notes together across both staffs. Set a location tag (=h) on the +// first note, for later use. + 5: 4.s bm with staff below; ; 8c; e; g ebm; + 6: 8c- =h bm with staff above; e-; g-; c; e; g; 4.s ebm; + + 8: 2. a3 d5 g5 b4 e3; 4. tie; + + // For the last two notes, override the head shape to be a slash, to + // indicate repeating the first part of the measure. + 9: 8g; e; ; [hs "slash"]... 4.b; ; + bar endending + + + + ital all: 1 "\[A special note, on\ntwo lines, in a box.\]"; + 1: 4.ce; eg; ; + lyrics between 1&2: "am gr\(o:)\(ss)t-en,"; // non-ACSII chars + 2: 4.cg; ce; ; + +// draw a measure repeat sign + 3: mrpt; + + // put a text string in an ellipse + ital 4: 1 "\{mute\}"; + 4 1: [xnote]... 4.; ; 8;;; + 4 2: 2.; 4.; + + 6: 8 with e+c++ above; c+ with g+ above; g with e+ above; ec+; g; e; \ + 4.c =k; // set loc tag "k" + 8: 4. a3 d5 g5 b4 e3; 2.; + 9: mrpt; + bar + +// Draw a curve, with endpoints based on the "=h" and "=k" location tags with +// vertical offsets of 11 and 8 stepsizes upwards. The curve bulges upwards +// 20 and 23 stepsizes 1/3 and 2/3 of the way through it. + medium curve (h.x, h.y + 11) to (k.x, k.y + 8) bulge 20, 23; + + +// print the chord G97, with the 9 above the 7 + K(1,G:9 7) + + ital(15) all: 9.9[-20] "D.C. al Coda"; + +// use a C double sharp (cx) and B natural + 1: 4.cxbn; 2.; + lyrics between 1&2: "tr\(e`)s bien!"; // another non-ASCII character + 2: 4.g-f; 2.; + 4 1: 4.r; c; ; // the pitch is arbitrary except for MIDI on one-line + 4 2: 4.; r; ; + 5: 4.dfgbn; ; dfan; + +// force first note stem to point upwards, which would by default have +// pointed down; change clef in the middle of the measure + 6: [up] 4.d; c; <> 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 ; + 9: 2.+4.g; + lyrics 9: "oo_"; + dblbar + +// For MIDI, insert the D.C. al Coda fragment + ifdef MIDI + FIRST2MEASURES + endif + +// leave a gap and start all the staffs anew, showing clefs and key signatures + restart + +staff 6 + clef = bass // change the clef back to bass + +music +// override the "dist" parameter, and specify a minimum distance of 5 stepsizes +// from the staff for this coda sign + mussym(13) all dist 5: 0.5 "coda"; + ital(15) all: 1 "Coda"; + +// at count 1 print G diminished 7 (the "o" is translated to a diminished +// symbol), and at count 7 print G + K(1,Go7) + K(7,G) + +// Another duplet. If we put "n" after the first number it would prevent the +// bracket from being printed. + 1: 2.d&g; { 4gbn; ; }2,4.; + +// Draw parentheses around the one D natural. Force this duplet's bracket to +// be below; this one would have defaulted to above. + 2: 2.b&f&; { 4d-n(dn)g; dbn; } below 2,4.; + +// Print both keyboard hands on its top staff, using two voices. Since the +// top notes are so high, set their stems to extend only 5 stepsizes instead +// of the usual 7 (octave). Slur and tie the notes, using dashed or dotted +// rather than solid curves. + 5 1: [len 5]... 2.g++b++d&+++f&+++ dashed slur; 4.g++bn++d+++g+++; + 5 2: 2.gg+ dotted tie; 4.; + +// leave staff 6 unspecified, so that it will default to a space + + 8: [slash 1] 2. e'0 a1 d2 g0 b2 e0; 4. e'3 d0 g0 b0 e3; + + 9: 2.g; 4.bn; + lyrics 9: "At the"; + bar + + + +score +// set a time signature that combines two simple time signatures + time = 2/4 + 3/8 + +music +// use shorthand to enter the same data for two staffs at once + 1,2: 2egc+ tie; 4.; + + 4 1,2: mr; // measure rest on both voices of staff 4 + 5-6: 2c tie; 4.; + +// mark notes an octave lower than normal + octave below 6: 1 "8va" til 7.5; + +// put a fermata above staffs 1, 2, and 4 to 6 + mussym above 1,2,4-6: 5 "ferm"; +// for MIDI, slow the tempo, to produce the fermata + midi all: 3 "tempo=50"; + 8: 2 e20~; 4.; + 9: 2+4.c+; + lyrics 9: "end."; + K(1,Cm) + endbar diff --git a/mup/docs/sample.ps b/mup/docs/sample.ps new file mode 100644 index 0000000..b759ada --- /dev/null +++ b/mup/docs/sample.ps @@ -0,0 +1,6024 @@ +%!PS-Adobe-1.0 +%%Creator: Mup +%%Title: music: from /home/johnkr/mup/5.3/doc/arkkra/sample.mup +%%CreationDate: Sat Dec 9 16:59:22 2006 +%%Pages: (atend) +%%DocumentFonts: (atend) +%%BoundingBox: 0 0 612 792 +%%EndComments +% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises +% All rights reserved + +% Mup PostScript Prolog 5.3 for use with Mup 5.3 + +% lwid is used as the width of a standard (thin) line in the music +% character definitions. +/lwid 70 def +/halflwid lwid 2 div def + +% Define the following for use in do_upshortnote, do_dnshortnote, and +% do_shortrest; it has to be done outside of the music font definition. +/utildict 10 dict def +utildict begin + /setnumflags { /numflags exch def } def + /sethooksm1 { /hooksm1 exch def } def + /setoffsets { /offsets exch def } def + /setx { /x exch def } def + /sety { /y exch def } def +end + +% Define a music character font. Each music character is defined as if it +% were a normal ASCII character in a strange font where "A" looks like a +% treble clef, "B" looks like a bass clef, etc. + +/mfont0 100 dict def +mfont0 begin + /FontType 3 def + /FontMatrix [ .001 0 0 0.001 0 0 ] def + /FontBBox [ -2000 -4030 2000 4030 ] def + /FontName (Mfont0) def + + % set up Encoding vector with standard names + /Encoding 256 array def + StandardEncoding Encoding copy + pop + + % the following definitions are used for quarter rests + /topx -170 def /topy 950 def + /cor1x 250 def /cor1y 450 def + /cor2x -300 def /cor2y 200 def + /cor3x 250 def /cor3y -400 def + + % the following definitions are used for double sharps + /limit 300 halflwid add def + /off 70 def + /inbendsmall limit 200 sub def + /inbendbig limit 20 sub def + /outbendsmall 100 def + /outbendbig outbendsmall off add def + + %%%%% define routines that will be used by multiple characters %%%%% + /do_1n { + gsave + newpath -10 rotate 1.6 1 scale + 0 0 325 0 360 arc %outer ellipse + 1 1.6 div 1 scale 10 rotate %back to original + 35 rotate 0.85 1.1 scale + 0 0 275 0 360 arc %inner ellipse + eofill + grestore + } def + /do_upflag { + -315 0 moveto + -300 100 -100 480 0 600 curveto + 300 960 350 1500 200 1700 curveto + 130 1700 lineto + 350 1200 50 650 -315 600 curveto + fill + } def + /do_flat { + -250 -400 moveto %outer edge of loop + 500 0 350 650 -250 160 curveto + -250 160 lwid sub lineto %inner edge of loop + 100 400 300 0 -250 -400 lwid add curveto + fill + + lwid setlinewidth %stem + -250 1100 moveto -250 -400 lineto stroke + } def + /do_diamond { + newpath + 420 0 moveto 0 300 lineto -420 0 lineto + 0 -300 lineto closepath + 259 -29 moveto -41 185 lineto -259 29 lineto + 41 -185 lineto closepath + eofill + } def + /do_2n { + gsave + newpath 25 rotate 1.4 1 scale + 0 0 315 0 360 arc %outer ellipse + 1 1.4 div 1 scale %back to original + 1.3 0.5 scale + 0 0 310 0 360 arc %inner ellipse + eofill + grestore + } def + /do_4n { + gsave + newpath 25 rotate 1.35 1 scale + 0 0 310 0 360 arc fill + grestore + } def + /do_com { + newpath + 330 250 150 0 360 arc fill %knob at upper right + 465 300 moveto %outer boundary + 410 500 200 635 0 635 curveto + -750 635 -750 -635 0 -635 curveto + 350 -635 480 -300 500 -100 curveto + 430 -100 lineto %inner boundary + 380 -300 250 -565 0 -565 curveto + -450 -565 -450 565 0 565 curveto + 200 565 370 350 395 300 curveto + fill + } def + /do_ferm { + 0 0 800 lwid sub 0 180 arc %inner arc + -800 0 lineto + 0 270 lwid sub 800 180 0 arcn %outer arc + 800 0 lineto fill + 0 120 120 0 360 arc fill %the dot + } def + /do_mor { + gsave + 0.7 1 scale %scrunch the following horizontally + 45 rotate %to pretend all lines horz or vertical + 0 1 1 { + pop %we don't need the loop variable + %one half of the mordent + 0 40 moveto 350 40 lineto 350 -460 lineto + 750 -460 lineto 750 -540 lineto + 150 -540 lineto 150 -40 lineto + 0 -40 lineto fill + 180 rotate %to do the other half + } for + grestore + } def + /do_turn { + gsave + 0 1 1 { + pop %we don't need the loop variable + 0 -100 moveto %outer boundary + 200 -400 625 -400 625 0 curveto + 625 200 500 325 300 325 curveto + 300 185 lineto %inner boundary + 450 255 555 150 555 0 curveto + 555 -350 250 -250 0 100 curveto + fill + 300 255 70 0 360 arc fill %knob on end + 180 rotate %to do the other half + } for + grestore + } def + + /do_upshortnote { + utildict begin + setnumflags %set numflags from the stack + gsave + -330 0 translate %half a flag width + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto + 370 2100 numflags 2 sub flagsep mul add lineto stroke + 670 2100 numflags 2 sub flagsep mul add translate + 1 -1 scale %reflect across X axis + 0 1 numflags 1 sub { + do_upflag %do an upflag + pop %we don't need the loop variable + 0 flagsep translate + } for + grestore + end + } def + + /do_dnshortnote { + utildict begin + setnumflags %set numflags from the stack + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto + -370 -2100 numflags 2 sub flagsep mul sub lineto stroke + gsave + -70 -2100 numflags 2 sub flagsep mul sub translate + 0 1 numflags 1 sub { + do_upflag %do an upflag + pop %we don't need the loop variable + 0 flagsep translate + } for + grestore + end + } def + + /do_shortrest { + utildict begin + sety setx setoffsets sethooksm1 %set variable from the stack + gsave + -105.8 offsets mul -600 offsets mul translate + 0 1 hooksm1 { %loop once per hook + newpath + 1 setlinewidth + gsave + 1 1.2 scale + -150 300 1.2 div 140 0 360 arc fill %the dot + grestore + lwid setlinewidth + -50 700 550 255 315 arc %rest of the hook + hooksm1 lt { stroke 105.8 600 translate } if + } for + x y lineto stroke + grestore + end + } def + + + % subsidiary dictionary of character definitions + /CharStrings 128 dict def + CharStrings begin + + /.notdef {} def + + % Here are the definitions of the characters. A stepsize here + % is 300 units (assuming the character is drawn at its default + % size). + + % gclef + /A { + newpath + %start with inner curl, inside boundary + -50 -300 moveto + -450 600 700 700 750 0 curveto + 750 -800 -700 -800 -700 200 curveto + -700 900 500 1400 520 2250 curveto + 520 2900 300 3000 200 3000 curveto + 100 3000 -400 2500 -200 1800 curveto + 350 -600 lineto + 720 -1600 0 -1650 -400 -1400 curveto + + %go back to start, drawing the other boundary + -400 -1480 lineto + 0 -1700 800 -1700 430 -600 curveto + -120 1800 lineto + -300 2400 200 2800 250 2800 curveto + 400 2800 430 2700 430 2450 curveto + 430 1800 -900 1200 -900 300 curveto + -750 -900 800 -900 850 0 curveto + 900 1100 -750 900 -120 -300 curveto fill + + %circle at the bottom + -300 -1250 250 0 360 arc fill + } def + + % fclef + /B { + newpath + %start with outside boundary, at bottom + -1000 -1700 moveto + 100 -1100 500 -600 450 0 curveto + 450 850 -1100 850 -950 0 curveto + + %go back to start, drawing the other boundary + -880 0 lineto + -920 400 -600 560 -300 560 curveto + 0 560 150 400 150 0 curveto + 150 -400 100 -900 -1000 -1620 curveto fill + + %circle at the left + newpath + -700 0 250 0 360 arc fill + + %do the two dots after the main curve + 700 -300 100 0 360 arc fill + 700 300 100 0 360 arc fill + } def + + % cclef + /C { + gsave + %do upper curved part, then scale to do mirror image + 0 1 1 { + pop %we don't need the loop variable + %outer boundary of curve + -170 0 moveto 100 300 lineto + 400 -200 750 300 750 650 curveto + 750 1100 450 1235 250 1235 curveto + 0 1235 -143 1100 -143 950 curveto + + %inner boundary of curve + 0 950 lineto + 0 1100 30 1165 250 1165 curveto + 300 1165 450 1100 450 650 curveto + 450 400 400 -100 100 400 curveto + -270 0 lineto fill + %stroke + %-270 0 moveto 100 400 lineto + %400 -100 450 400 450 650 curveto + %450 1100 300 1165 250 1165 curveto + %30 1165 0 1100 0 950 curveto + %stroke + + %elliptical ball at end of curve + gsave + 1.3 1 scale + 10 950 120 0 360 arc fill + grestore + 1 -1 scale %reflect across X axis + } for + grestore + + % two vertical lines on the left + 300 setlinewidth -600 -1200 halflwid sub moveto + -600 1200 halflwid add lineto stroke + lwid setlinewidth -300 -1200 halflwid sub moveto + -300 1200 halflwid add lineto stroke + } def + + % dblwhole + /D { + do_1n %do a whole note + lwid setlinewidth + -490 -600 moveto -490 600 lineto stroke + 490 -600 moveto 490 600 lineto stroke + } def + + % 1n + /E { + do_1n %do a whole note + } def + + % 2n + /F { + do_2n %do a half note + } def + + % 4n + /G { + do_4n %do a quarter note head + } def + + % upflag + /H { + do_upflag %do an upflag + } def + + % dnflag + /I { + gsave + 1 -1 scale %reflect across X axis + do_upflag %do an upflag + grestore + } def + + % dwhrest + /J { + 300 setlinewidth + 0 0 moveto 0 600 lineto stroke + } def + + % 1rest + /K { + lwid setlinewidth + -750 600 moveto 750 600 lineto stroke + 300 setlinewidth + -400 450 moveto 400 450 lineto stroke + } def + + % 2rest + /L { + lwid setlinewidth + -750 0 moveto 750 0 lineto stroke + 300 setlinewidth + -400 150 moveto 400 150 lineto stroke + } def + + % 4rest + /M { + newpath + cor3x cor3y halflwid add moveto + %-400 -200 -450 -650 50 -950 lwid add curveto + -450 -50 -450 -650 50 -950 lwid add curveto + -150 -650 -100 -250 cor3x cor3y halflwid sub curveto + fill + + cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto + cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto + fill + + lwid setlinewidth + topx topy moveto cor1x cor1y lineto stroke + cor2x cor2y moveto cor3x cor3y lineto stroke + } def + + % 8rest + /N { + 0 0 0 -600 do_shortrest + } def + + % 16rest + /O { + 1 1 100 -1200 do_shortrest + } def + + % 32rest + /P { + 2 1 0 -1800 do_shortrest + } def + + % 64rest + /Q { + 3 2 -80 -2100 do_shortrest + } def + + % 128rest + /R { + 4 2 -150 -2700 do_shortrest + } def + + % 256rest + /S { + 5 3 -280 -3300 do_shortrest + } def + + % dot + /T { + newpath + 0 0 120 0 360 arc fill + } def + + % nat + /U { + % fill crossbars so that we can do parallelograms + -235 -470 moveto -235 -270 lineto + 235 -130 lineto 235 -330 lineto fill + -235 130 moveto -235 330 lineto + 235 470 lineto 235 270 lineto fill + + % vertical strokes + lwid setlinewidth + -200 -380 moveto -200 850 lineto stroke + 200 -850 moveto 200 380 lineto stroke + } def + + % sharp + /V { + % fill crossbars so that we can do parallelograms + -325 -480 moveto -325 -280 lineto + 325 -120 lineto 325 -320 lineto fill + -325 120 moveto -325 320 lineto + 325 480 lineto 325 280 lineto fill + + % vertical strokes + lwid setlinewidth + -150 -930 moveto -150 880 lineto stroke + 150 -880 moveto 150 930 lineto stroke + } def + + % flat + /W { + do_flat %do a flat + } def + + % dblsharp + /X { + gsave + 0 1 3 { %loop once for each of 4 sticks + pop %we don't need the loop variable + 0 off neg moveto + outbendbig outbendsmall lineto + inbendbig inbendsmall lineto + limit limit lineto + inbendsmall inbendbig lineto + outbendsmall outbendbig lineto + off neg 0 lineto + fill + -90 rotate + } for + grestore + } def + + % dblflat + /Y { + -290 580 290 { %loop once for each flat + + gsave + 1 setlinewidth + 0 translate %translate left/right (loop var) + do_flat %do a flat + grestore + + } for + } def + + % xnote + /Z { + gsave + 1.15 1 scale 120 setlinewidth 1 setlinecap %round + -300 -300 moveto 300 300 lineto stroke + -300 300 moveto 300 -300 lineto stroke + grestore + } def + + % dwhdiamond + /a { + do_diamond %do a diamond + lwid setlinewidth + -420 -600 moveto -420 600 lineto stroke + 420 -600 moveto 420 600 lineto stroke + } def + + % diamond + /b { + do_diamond %do a diamond + } def + + % filldiamond + /c { + 420 0 moveto 0 300 lineto + -420 0 lineto 0 -300 lineto fill + } def + + % up2n + /d { + lwid setlinewidth + 380 0 moveto 380 2100 lineto stroke + do_2n %do a half note + } def + + % dn2n + /e { + lwid setlinewidth + -380 0 moveto -380 -2100 lineto stroke + do_2n %do a half note + } def + + % up4n + /f { + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto 370 2100 lineto stroke + } def + + % dn4n + /g { + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto -370 -2100 lineto stroke + } def + + % up8n + /h { + gsave + -330 0 translate % half a flag width + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto 370 2100 lineto stroke + 670 2100 translate + 1 -1 scale %reflect across X axis + do_upflag %do an upflag + grestore + } def + + % dn8n + /i { + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto -370 -2100 lineto stroke + gsave + -70 -2100 translate + do_upflag %do an upflag + grestore + } def + + % up16n + /j { + 2 do_upshortnote + } def + + % dn16n + /k { + 2 do_dnshortnote + } def + + % up32n + /l { + 3 do_upshortnote + } def + + % dn32n + /m { + 3 do_dnshortnote + } def + + % up64n + /n { + 4 do_upshortnote + } def + + % dn64n + /o { + 4 do_dnshortnote + } def + + % up128n + /p { + 5 do_upshortnote + } def + + % dn128n + /q { + 5 do_dnshortnote + } def + + % up256n + /r { + 6 do_upshortnote + } def + + % dn256n + /s { + 6 do_dnshortnote + } def + + % com + /t { + do_com %do a common time symbol + } def + + % cut + /u { + do_com %do a common time symbol + lwid setlinewidth + 0 -900 moveto 0 900 lineto stroke + } def + + % begped + /v { + lwid setlinewidth + -200 600 moveto -200 0 lineto 200 0 lineto stroke + } def + + % pedal + /w { + lwid setlinewidth + -500 0 moveto -450 0 lineto 0 600 lineto + 450 0 lineto 500 0 lineto stroke + } def + + % endped + /x { + lwid setlinewidth + 200 600 moveto 200 0 lineto -200 0 lineto stroke + } def + + % dnbow + /y { + lwid setlinewidth + -350 0 moveto -350 900 lineto stroke + 350 0 moveto 350 900 lineto stroke + 200 setlinewidth + -350 800 moveto 350 800 lineto stroke + } def + + % upbow + /z { + lwid setlinewidth + -300 900 moveto 0 0 lineto 300 900 lineto stroke + } def + + % wedge + /one { + 0 0 moveto -150 500 lineto 150 500 lineto fill + } def + + % uwedge + /two { + -150 0 moveto 150 0 lineto 0 500 lineto fill + } def + + % ferm + /three { + newpath + do_ferm %do a right side up fermata + } def + + % uferm + /four { + newpath + gsave + 0 270 lwid sub 800 add translate %baseline at bottom + 180 rotate %upside down + do_ferm %do a right side up fermata + grestore + } def + + % sign + /five { + gsave + %do upper left curved part, upper right dot; + %then rotate 180 to do other half + 0 1 1 { + pop %we don't need the loop variable + 0 100 moveto %inner boundary + -1000 300 -400 750 -200 700 curveto + -200 800 lineto %outer boundary + -550 900 -1100 100 0 -100 curveto + fill + %dot at end of curve + -200 700 100 0 360 arc fill + %dot in upper right quadrant + 500 200 70 0 360 arc fill + 180 rotate + } for + grestore + + %slash through middle + lwid setlinewidth + -400 -800 moveto 400 800 lineto stroke + } def + + % coda + /six { + newpath + gsave + 0.6 1 scale + 0 0 550 0 360 arc %outside boundary + 1 0.6 div 1 scale %back to original + 0.9 1 scale + 0 0 650 0 360 arc %inside boundary + eofill + grestore + lwid setlinewidth + 0 -850 moveto 0 850 lineto stroke + -800 0 moveto 800 0 lineto stroke + } def + + % mor + /seven { + do_mor %do a mordent + } def + + % invmor + /eight { + do_mor %do a mordent + lwid setlinewidth + 0 -450 moveto 0 450 lineto stroke + } def + + % turn + /nine { + do_turn %do a turn + } def + + % invturn + /zero { + gsave + 1 -1 scale %reflect across X axis + do_turn %do a turn + grestore + } def + + % acc_gt + /numbersign { + lwid setlinewidth + -500 300 moveto 500 0 lineto -500 -300 lineto stroke + } def + + % acc_hat + /dollar { + newpath + -365 0 moveto 0 860 lineto 365 0 lineto + 150 0 lineto -75 530 lineto -300 0 lineto fill + } def + + % acc_uhat + /quotedbl { + newpath + 365 860 moveto 0 0 lineto -365 860 lineto + -150 860 lineto 75 330 lineto 300 860 lineto fill + } def + + % tr + /asterisk { + %vertical bar of t + -350 1000 moveto -550 200 lineto + -612.5 -50 -212.5 -50 -160 200 curveto + -230 200 lineto + -300 50 -420 50 -400 200 curveto + -200 1000 lineto fill + + %crossbar of t and vertical bar of r + -700 600 moveto -160 600 lineto + 20 600 30 520 60 440 curveto + -50 0 lineto 70 0 lineto 180 440 lineto + 190 480 100 670 -150 670 curveto + -690 670 lineto fill + + %horizontal curve of r + 100 480 moveto + 300 630 450 700 650 550 curveto + 560 480 lineto + 450 630 300 560 100 390 curveto + fill + + %knob at end of r + 600 460 100 0 360 arc fill + } def + + % leg + /comma { + 100 setlinewidth + -400 0 moveto 400 0 lineto stroke + } def + + % rr + /hyphen { + 100 setlinewidth + -400 0 moveto 0 1000 lineto stroke + 0 0 moveto 400 1000 lineto stroke + } def + + % measrpt + /period { + newpath -450 400 150 0 360 arc fill + newpath 450 -400 150 0 360 arc fill + 200 setlinewidth + -550 -600 moveto 550 600 lineto stroke + } def + + % copyright + /slash { + lwid setlinewidth + newpath 0 400 400 0 360 arc stroke + newpath 0 400 200 45 315 arc stroke + } def + + % dim + /quoteleft { + 50 setlinewidth + newpath 0 640 220 0 360 arc stroke + } def + + % halfdim + /quoteright { + 50 setlinewidth + newpath 0 640 220 0 360 arc stroke + newpath -340 300 moveto 340 980 lineto stroke + } def + + % triangle + /asciicircum { + 50 setlinewidth + newpath -340 -10 moveto 0 710 lineto + 340 -10 lineto closepath stroke + } def + + % qwhrest + /ampersand { + 300 setlinewidth + 0 -600 moveto 0 600 lineto stroke + } def + + % ll1rest + /exclam { + 310 setlinewidth + -400 455 moveto 400 450 lineto stroke + } def + + % ll2rest + /at { + 310 setlinewidth + -400 145 moveto 400 150 lineto stroke + } def + end + + /BuildChar { + + exch begin + Encoding exch get + + dup + Mcbbox0 exch get + aload pop setcachedevice + + CharStrings exch get + exec + end + } def +end + + +% Define another music character font, since there are too many to fit in one +% font. It works the same way as the first one. + +/mfont1 100 dict def +mfont1 begin + /FontType 3 def + /FontMatrix [ .001 0 0 0.001 0 0 ] def + /FontBBox [ -2000 -4030 2000 4030 ] def + /FontName (Mfont1) def + + % set up Encoding vector with standard names + /Encoding 256 array def + StandardEncoding Encoding copy + pop + + %%%%% define routines that will be used by multiple characters %%%%% + + /do_dwh_bars { + % the two bars surrounding a double whole note + lwid setlinewidth + -420 -600 moveto -420 600 lineto stroke + 420 -600 moveto 420 600 lineto stroke + } def + /do_righttriangle { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto + 350 150 moveto -140 150 lineto 350 -213 lineto + eofill + } def + /do_fillrighttriangle { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto + fill + } def + /do_rectangle { + newpath + 420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto + 350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto + eofill + } def + /do_isostriangle { + newpath + 0 300 moveto -420 -270 lineto 420 -270 lineto + 0 182 moveto -245 -150 lineto 245 -150 lineto + eofill + } def + /do_piewedge { + newpath + 0 -300 moveto 0 -244 514 35 145 arc + 0 -209 moveto 0 -244 394 43 137 arc + eofill + } def + /do_semicircle { + newpath + gsave + 1 1.357 scale 420 199 moveto 0 199 420 180 360 arc + 1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc + eofill + grestore + } def + /do_slashhead { + newpath + lwid setlinewidth + -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto + closepath stroke + } def + + % subsidiary dictionary of character definitions + /CharStrings 128 dict def + CharStrings begin + + /.notdef {} def + + % Here are the definitions of the characters. A stepsize here + % is 300 units (assuming the character is drawn at its default + % size). + + % dwhrighttriangle + /A { + do_righttriangle + do_dwh_bars + } def + + % righttriangle + /B { + do_righttriangle + } def + + % fillrighttriangle + /C { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto + 420 -300 lineto + fill + } def + + % udwhrighttriangle + /D { + gsave + 180 rotate + do_righttriangle + do_dwh_bars + grestore + } def + + % urighttriangle + /E { + gsave + 180 rotate + do_righttriangle + grestore + } def + + % ufillrighttriangle + /F { + gsave + 180 rotate + do_fillrighttriangle + grestore + } def + + % dwhrectangle + /G { + do_rectangle + do_dwh_bars + } def + + % rectangle + /H { + do_rectangle + } def + + % fillrectangle + /I { + newpath + 420 270 moveto -420 270 lineto -420 -270 lineto + 420 -270 lineto + fill + } def + + % dwhisostriangle + /J { + do_isostriangle + do_dwh_bars + } def + + % isostriangle + /K { + do_isostriangle + } def + + % fillisostriangle + /L { + newpath + 0 300 moveto -420 -270 lineto 420 -270 lineto + fill + } def + + % dwhpiewedge + /M { + do_piewedge + do_dwh_bars + } def + + % piewedge + /N { + do_piewedge + } def + + % fillpiewedge + /O { + newpath + 0 -300 moveto 0 -244 514 35 145 arc + fill + } def + + % dwhsemicircle + /P { + do_semicircle + do_dwh_bars + } def + + % semicircle + /Q { + do_semicircle + } def + + % fillsemicircle + /R { + newpath + gsave + 1 570 420 div scale + 420 199 moveto 0 199 420 180 360 arc + fill + grestore + } def + + % dwhslashhead + /S { + do_slashhead + lwid setlinewidth + -650 -600 moveto -650 600 lineto stroke + 650 -600 moveto 650 600 lineto stroke + } def + + % slashhead + /T { + do_slashhead + } def + + % fillslashhead + /U { + newpath + 200 setlinewidth + -550 -600 moveto 550 600 lineto stroke + } def + + % blankhead + /V { + %print nothing + } def + end + + /BuildChar { + + exch begin + Encoding exch get + + dup + Mcbbox1 exch get + aload pop setcachedevice + + CharStrings exch get + exec + end + } def +end + + +% General routines for printing any music character, invoked by each music +% character's specific routine below. The scaling factor (default 1) needs +% to be multiplied by 10 to get the actual size. These routines restore the +% preexisting current font when they are done. + +/printmchar0 { + gsave + /musicchar exch def + /Mfont0 findfont exch 10 mul scalefont setfont moveto + musicchar show + grestore +} def +/printmchar1 { + gsave + /musicchar exch def + /Mfont1 findfont exch 10 mul scalefont setfont moveto + musicchar show + grestore +} def + +% Define each music character name to be a routine that prints the character. +% Each character is to be invoked as in this example: +% 100 200 1 gclef % at (100, 200), scale to default size & print + +/gclef { (A) printmchar0 } def +/fclef { (B) printmchar0 } def +/cclef { (C) printmchar0 } def +/dblwhole { (D) printmchar0 } def +/1n { (E) printmchar0 } def +/2n { (F) printmchar0 } def +/4n { (G) printmchar0 } def +/upflag { (H) printmchar0 } def +/dnflag { (I) printmchar0 } def +/dwhrest { (J) printmchar0 } def +/1rest { (K) printmchar0 } def +/2rest { (L) printmchar0 } def +/4rest { (M) printmchar0 } def +/8rest { (N) printmchar0 } def +/16rest { (O) printmchar0 } def +/32rest { (P) printmchar0 } def +/64rest { (Q) printmchar0 } def +/128rest { (R) printmchar0 } def +/256rest { (S) printmchar0 } def +/dot { (T) printmchar0 } def +/nat { (U) printmchar0 } def +/sharp { (V) printmchar0 } def +/flat { (W) printmchar0 } def +/dblsharp { (X) printmchar0 } def +/dblflat { (Y) printmchar0 } def +/xnote { (Z) printmchar0 } def +/dwhdiamond { (a) printmchar0 } def +/diamond { (b) printmchar0 } def +/filldiamond { (c) printmchar0 } def +/up2n { (d) printmchar0 } def +/dn2n { (e) printmchar0 } def +/up4n { (f) printmchar0 } def +/dn4n { (g) printmchar0 } def +/up8n { (h) printmchar0 } def +/dn8n { (i) printmchar0 } def +/up16n { (j) printmchar0 } def +/dn16n { (k) printmchar0 } def +/up32n { (l) printmchar0 } def +/dn32n { (m) printmchar0 } def +/up64n { (n) printmchar0 } def +/dn64n { (o) printmchar0 } def +/up128n { (p) printmchar0 } def +/dn128n { (q) printmchar0 } def +/up256n { (r) printmchar0 } def +/dn256n { (s) printmchar0 } def +/com { (t) printmchar0 } def +/cut { (u) printmchar0 } def +/begped { (v) printmchar0 } def +/pedal { (w) printmchar0 } def +/endped { (x) printmchar0 } def +/dnbow { (y) printmchar0 } def +/upbow { (z) printmchar0 } def +/wedge { (1) printmchar0 } def +/uwedge { (2) printmchar0 } def +/ferm { (3) printmchar0 } def +/uferm { (4) printmchar0 } def +/sign { (5) printmchar0 } def +/coda { (6) printmchar0 } def +/mor { (7) printmchar0 } def +/invmor { (8) printmchar0 } def +/turn { (9) printmchar0 } def +/invturn { (0) printmchar0 } def +/acc_gt { (#) printmchar0 } def +/acc_hat { ($) printmchar0 } def +/acc_uhat { (") printmchar0 } def +/tr { (*) printmchar0 } def +/leg { (,) printmchar0 } def +/rr { (-) printmchar0 } def +/measrpt { (.) printmchar0 } def +/copyright { (/) printmchar0 } def +/dim { (`) printmchar0 } def +/halfdim { (') printmchar0 } def +/triangle { (^) printmchar0 } def +/qwhrest { (&) printmchar0 } def +/ll1rest { (!) printmchar0 } def +/ll2rest { (@) printmchar0 } def +/dwhrighttriangle { (A) printmchar1 } def +/righttriangle { (B) printmchar1 } def +/fillrighttriangle { (C) printmchar1 } def +/udwhrighttriangle { (D) printmchar1 } def +/urighttriangle { (E) printmchar1 } def +/ufillrighttriangle { (F) printmchar1 } def +/dwhrectangle { (G) printmchar1 } def +/rectangle { (H) printmchar1 } def +/fillrectangle { (I) printmchar1 } def +/dwhisostriangle { (J) printmchar1 } def +/isostriangle { (K) printmchar1 } def +/fillisostriangle { (L) printmchar1 } def +/dwhpiewedge { (M) printmchar1 } def +/piewedge { (N) printmchar1 } def +/fillpiewedge { (O) printmchar1 } def +/dwhsemicircle { (P) printmchar1 } def +/semicircle { (Q) printmchar1 } def +/fillsemicircle { (R) printmchar1 } def +/dwhslashhead { (S) printmchar1 } def +/slashhead { (T) printmchar1 } def +/fillslashhead { (U) printmchar1 } def +/blankhead { (V) printmchar1 } def + + +% Define routines for Mup output other than music characters. + +/stepsize 3 def % define a step size as 3 points (at default magnification) + +% x1 y1 x2 lines dist staffscale staff +% draw a staff starting at x1, y1 and extending to x2 with "lines" +% lines, 2*dist*stepsize apart, scaled by staffscale +/staff { + /staffscale exch def + /dist exch def + /lines exch def + /x2 exch def + /y1 exch def + /x1 exch def + 0.7 staffscale mul sb setlinewidth + 1 lines sub 2 lines 1 sub { % loop from bottom line to top line + dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto + stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke + } for +} def + +% x y1 y2 bracket draw a bracket; y1 is the top +/bracket { + /y2 exch def + /y1 exch def + /x exch def + gsave + 3 setlinewidth + x 2 sub y1 1 add moveto + x 2 sub y2 1 sub lineto + stroke + x 2 sub y1 1 add moveto + x 1 sub y1 1 add x 3 add y1 1 add x 5 add y1 6 add curveto + x 6 add y1 5 add lineto + x 5 add y1 2 add x 1 add y1 2 sub x 2 sub y1 2 sub curveto + fill + x 2 sub y2 1 sub moveto + x 1 sub y2 1 sub x 3 add y2 1 sub x 5 add y2 6 sub curveto + x 6 add y2 5 sub lineto + x 5 add y2 2 sub x 1 add y2 2 add x 2 sub y2 2 add curveto + fill + grestore +} def + +% x y1 y2 brace draw a brace; y1 is the top +/brace { + /y2 exch def + /y1 exch def + /x exch def + gsave + x 9 sub y1 y2 add 2 div translate + /topy y1 y2 sub 2 div 1 sub def + 0 1 1 { + pop + %0 topy moveto 0 0 lineto stroke + 0 0 moveto + 16 topy 0.2 mul -11 topy 0.6 mul 8 topy curveto + 8.7 topy lineto + -7 topy 0.7 mul 20 topy 0.3 mul 1 0 curveto + fill + 1 -1 scale % flip to do bottom half + } for + grestore +} def + +% endx endy wavy staffscale draw a wavy line from current point to here, +% scaled by staffscale +/wavy { + /staffscale exch def + /endy exch def % define the end point of the line + /endx exch def + currentpoint % line starts at current point + /begy exch def % define the beginning point of the line + /begx exch def + gsave + /dx endx begx sub def % find delta x and delta y + /dy endy begy sub def + /r dx dx mul dy dy mul add sqrt def % hypotenuse + /theta dy dx atan def % angle with positive x axis + begx begy translate % change axes so that we can draw the line + theta rotate % from (0, 0) to (r, 0) + staffscale staffscale scale % scale everything by staffscale + /scaledr r staffscale div def % but scale r in reverse to keep length + + % Each outer loop draws one cycle of the squiggle. It continues until + % we are at or beyond the desired end point. + 0 0 moveto + 0 6 scaledr { + gsave + % first loop draws left half of squiggle; second draws right + 0 1 1 { + 0.0 0.4 moveto + 2.0 1.9 3.4 2.3 3.9 0.0 curveto + 2.1 0.0 lineto + 1.9 0.8 1.4 0.7 0.0 -0.4 curveto + fill + pop 180 rotate -6 0 translate + } for + grestore + + pop 6 0 translate % shift axes right one squiggle + } for + + grestore +} def + +% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid +% print a guitar grid diagram +/grid { + /grid_positions exch def % 0="o", -1="x", -2=nothing, positive=dot + /curver exch def % right string for curve, 0 if none + /curvel exch def % left string for curve, 0 if none + /numvert exch def % vertical position to print fretno, 0 if none + /fretno exch def % fret no. to print at right, 0 if none + /frets exch def % number of fret lines + /space exch def % points between two neighboring lines + /y exch def % y coord of top fret line + /x exch def % x coord of left strings + + gsave + /strings grid_positions length def % number of strings + /lmarky 0.4 space mul y add def % lowest Y of a "o" or "x" + space 10 div setlinewidth + 2 setlinecap + + % draw the lines of the grid + 0 1 strings 1 sub { % loop from left string to right string + dup space mul x add y moveto + space mul x add frets 1 sub space mul y exch sub lineto stroke + } for + 0 -1 1 frets sub { % loop from top fret (nut) to bottom fret + dup space mul y add x exch moveto + space mul y add strings 1 sub space mul x add exch lineto stroke + } for + + % draw the curved line if there is one + curvel 0 gt { + % within strings curvel to curver, find smallest positive fret + /minfret 1000 def + curvel 1 curver { + /strno exch def + /grid_p grid_positions strno 1 sub get def + grid_p 0 gt grid_p minfret lt and { + /minfret grid_p def + } if + } for + + % if curve goes above top fret, other marks must be higher + minfret 1 eq { + /hmarky 1.2 space mul y add def + } { + /hmarky lmarky def + } ifelse + + /strdiff curver curvel sub def + space 8 div setlinewidth + + % set endpoint coords of curve; higher if curve is short + /curvex1 curvel 1 sub space mul x add def + /curvex2 curver 1 sub space mul x add def + /curvey 1 minfret sub space mul y add def + strdiff 3 lt { + /curvey 0.2 strdiff div space mul curvey add def + } if + + % move to left end, set other points, draw curve + curvex1 curvey moveto + + curvex1 curvex2 curvex1 sub 3 div add + curvey space 0.4 strdiff sqrt mul mul add + + curvex2 curvex2 curvex1 sub 3 div sub + curvey space 0.4 strdiff sqrt mul mul add + + curvex2 curvey curveto stroke + } if + + space 10 div setlinewidth + + % draw dots and x and o marks + 0 1 strings 1 sub { % loop from left string to right string + /strno exch def % first string is 0 + /grid_p grid_positions strno get def + /strx strno space mul x add def + + % set Y of mark higher if curved line covers this string + strno 1 add curvel ge strno 1 add curver le and { + /marky hmarky def + } { + /marky lmarky def + } ifelse + + grid_p -1 eq { % draw an X above the string + /xhwid space 3 div def + strx xhwid sub marky xhwid sub moveto + strx xhwid add marky xhwid add lineto stroke + strx xhwid sub marky xhwid add moveto + strx xhwid add marky xhwid sub lineto stroke + } if + grid_p 0 eq { % draw a circle above the string + strx marky space 0.3 mul 0 360 arc stroke + } if + grid_p 1 ge { % draw a dot by the proper fret + strx y grid_p space mul sub space 3 div add + space 3 div 0 360 arc fill + } if + } for + + % print "X fr" if requested + fretno 0 gt { + /Palatino-Roman findfont space 1.9 mul scalefont setfont + x strings 0.5 sub space mul add + y space numvert 0.3 add mul sub moveto + fretno 2 string cvs show ( fr) show + } if + grestore +} def + +% x1 y1 x2 y2 whitebox draw a white rectangle with opposite +% corners of (x1,y1) and (x2,y2) +/whitebox { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + 1.0 setgray + newpath + x1 y1 moveto + x1 y2 lineto + x2 y2 lineto + x2 y1 lineto + closepath + fill + stroke + 0.0 setgray +} def + + +/LineNum 0 def +/InputFile (unknown) def + +% n linenum +/linenum { + /LineNum exch def +} def + +% (inputfilename) inputfile +/inputfile { + /InputFile exch def +} def + +% find size of Encoding and make a dictionary +% that size for bounding box information +mfont0 begin +/dictsize Encoding length def +mfont0 /Mcbbox0 dictsize dict put + +% temporarily redefine printmchar0 to get code +5 dict begin +/printmchar0 { {} forall } def + +Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put +Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put +Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put +Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put +Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put +Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put +Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put +Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put +Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put +Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put +Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put +Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put +Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put +Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put +Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put +Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put +Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put +Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put +Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put +Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put +Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put +Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put +Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put +Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put +Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put +Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put +Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put +Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put +Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put +Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put +Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put +Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put +Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put +Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put +Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put +Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put +Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put +Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put +Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put +Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put +Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put +Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put +Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put +Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put +Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put +Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put +Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put +Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put +Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put +Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put +Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put +Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put +Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put +Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put +Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put +Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put +Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put +Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put +Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put +Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put +Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put +Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put +Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put +Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put +Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put +Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put +Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put +Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put +Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put +Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put +Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put +Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put + +end +end + +/Mfont0 mfont0 definefont + + +% find size of Encoding and make a dictionary +% that size for bounding box information +mfont1 begin +/dictsize Encoding length def +mfont1 /Mcbbox1 dictsize dict put + +% temporarily redefine printmchar1 to get code +5 dict begin +/printmchar1 { {} forall } def + +Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put +Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put +Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put +Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put + +end +end + +/Mfont1 mfont1 definefont + +/makeExtEncoding { + /extendedencoding 256 array def + StandardEncoding extendedencoding copy + extendedencoding 32 /exclamdown put + extendedencoding 33 /cent put + extendedencoding 34 /sterling put + extendedencoding 35 /yen put + extendedencoding 36 /quotedblleft put + extendedencoding 37 /guillemotleft put + extendedencoding 38 /guillemotright put + extendedencoding 39 /guilsinglleft put + extendedencoding 40 /guilsinglright put + extendedencoding 41 /dagger put + extendedencoding 42 /daggerdbl put + extendedencoding 43 /bullet put + extendedencoding 44 /quotedblbase put + extendedencoding 45 /quotedblright put + extendedencoding 46 /questiondown put + extendedencoding 47 /grave put + extendedencoding 48 /acute put + extendedencoding 49 /macron put + extendedencoding 50 /breve put + extendedencoding 51 /dotaccent put + extendedencoding 52 /dieresis put + extendedencoding 53 /ring put + extendedencoding 54 /cedilla put + extendedencoding 55 /hungarumlaut put + extendedencoding 56 /ogonek put + extendedencoding 57 /caron put + extendedencoding 58 /emdash put + extendedencoding 59 /AE put + extendedencoding 60 /ae put + extendedencoding 61 /ordfeminine put + extendedencoding 62 /ordmasculine put + extendedencoding 63 /Lslash put + extendedencoding 64 /lslash put + extendedencoding 65 /Oslash put + extendedencoding 66 /oslash put + extendedencoding 67 /OE put + extendedencoding 68 /oe put + extendedencoding 69 /dotlessi put + extendedencoding 70 /germandbls put + extendedencoding 71 /Aacute put + extendedencoding 72 /aacute put + extendedencoding 73 /Acircumflex put + extendedencoding 74 /acircumflex put + extendedencoding 75 /Adieresis put + extendedencoding 76 /adieresis put + extendedencoding 77 /Agrave put + extendedencoding 78 /agrave put + extendedencoding 79 /Aring put + extendedencoding 80 /aring put + extendedencoding 81 /Atilde put + extendedencoding 82 /atilde put + extendedencoding 83 /Ccedilla put + extendedencoding 84 /ccedilla put + extendedencoding 85 /Eacute put + extendedencoding 86 /eacute put + extendedencoding 87 /Ecircumflex put + extendedencoding 88 /ecircumflex put + extendedencoding 89 /Edieresis put + extendedencoding 90 /edieresis put + extendedencoding 91 /Egrave put + extendedencoding 92 /egrave put + extendedencoding 93 /Iacute put + extendedencoding 94 /iacute put + extendedencoding 95 /Icircumflex put + extendedencoding 96 /icircumflex put + extendedencoding 97 /Idieresis put + extendedencoding 98 /idieresis put + extendedencoding 99 /Igrave put + extendedencoding 100 /igrave put + extendedencoding 101 /Ntilde put + extendedencoding 102 /ntilde put + extendedencoding 103 /Oacute put + extendedencoding 104 /oacute put + extendedencoding 105 /Ocircumflex put + extendedencoding 106 /ocircumflex put + extendedencoding 107 /Odieresis put + extendedencoding 108 /odieresis put + extendedencoding 109 /Ograve put + extendedencoding 110 /ograve put + extendedencoding 111 /Otilde put + extendedencoding 112 /otilde put + extendedencoding 113 /Scaron put + extendedencoding 114 /scaron put + extendedencoding 115 /Uacute put + extendedencoding 116 /uacute put + extendedencoding 117 /Ucircumflex put + extendedencoding 118 /ucircumflex put + extendedencoding 119 /Udieresis put + extendedencoding 120 /udieresis put + extendedencoding 121 /Ugrave put + extendedencoding 122 /ugrave put + extendedencoding 123 /Ydieresis put + extendedencoding 124 /ydieresis put + extendedencoding 125 /Zcaron put + extendedencoding 126 /zcaron put + extendedencoding 127 /space put +} def + +/makeExtendedFont { + findfont + dup length dict /newdict exch def + { 1 index /FID ne + { newdict 3 1 roll put } + { pop pop } + ifelse + } forall + newdict /Encoding extendedencoding put + newdict /UniqueID newdict /UniqueID get 1 add put + newdict definefont pop +} def +/flagsep 1.60 300 mul def % 1.60 stepsizes +/scv 147460 def /sf 962 string def +/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def +[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa +[ 961 ] 1341740116 fa +[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa +[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa +[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa +[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa +[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa +[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa +[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa +[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa +[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa +[ 795 ] 1622189328 fa +[ 463 45 40 41 50 45 84 ] 304180545 fa +[ 494 40 41 49 45 43 84 ] 251711819 fa +[ 149 203 37 144 ] 358262127 fa +[ 456 142 52 ] 95949173 fa +[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa +[ 839 5 13 12 13 13 48 ] 1943250302 fa +[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa +[ 798 1 3 1 ] 1277775234 fa +[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa +[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa +[ 193 49 180 8 17 134 ] 831070621 fa +[ 353 366 ] 1033403809 fa +[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa +[ 423 8 109 ] 508918194 fa +[ 328 6 30 6 31 6 269 ] 212071871 fa +[ 390 357 2 ] 1671244225 fa +[ 500 ] 347047368 fa +[ 558 ] 1276946910 fa +[ 651 ] 2109048312 fa +[ 644 ] 1914352160 fa +[ 520 ] 471204394 fa +[ 512 5 2 ] 1930983991 fa +[ 665 ] 154021439 fa +[ 513 ] 777103941 fa +[ 514 ] 260959830 fa +[ 530 239 ] 1284535922 fa +[ 510 ] 1982423675 fa +[ 150 ] 1969948305 fa +[ 511 7 134 ] 1407991454 fa +[ 144 371 ] 1896661664 fa +[ 464 52 ] 1444653737 fa +[ 509 81 ] 1712172720 fa +[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa +[ 954 ] 1802916616 fa +[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa +[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa +[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa +[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa +[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa +[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa +[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa +[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa +[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa +[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa +[ 960 ] 75399990 fa +[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa +[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa +[ 901 ] 422446918 fa +[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa +[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa +[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa +[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa +[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa +[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa +[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa +[ 780 32 ] 847653755 fa +[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa +[ 724 83 7 ] 1643402114 fa +[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa +[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa +[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa +[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa +[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa +[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa +[ 944 8 ] 1770206109 fa +[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa +[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa +[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa +[ 912 9 11 ] 273962927 fa +[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa +[ 130 683 ] 1406620603 fa +[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa +[ 861 13 9 4 12 8 17 3 ] 1447963591 fa +[ 67 143 8 128 115 435 19 2 ] 477757388 fa +[ 490 35 ] 1151262673 fa +[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa +[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa +sf cvx exec + +% set up extended character set fonts +makeExtEncoding +/Ext-Helvetica-Oblique /Helvetica-Oblique makeExtendedFont +%%EndProlog +%%Page: 1 1 +save +1216322504 1216321786 sv +0.770000 0.770000 scale +% S_SSV +(/home/johnkr/mup/5.3/doc/arkkra/sample.mup) inputfile +53 linenum +% S_SSV +141 linenum +% S_SSV +144 linenum +% S_SSV +155 linenum +% S_SSV +159 linenum +% S_SSV +167 linenum +% S_SSV +174 linenum +% S_SSV +177 linenum +% S_SSV +189 linenum +% S_FEED +46 linenum +/Times-Roman findfont +13 scalefont +setfont +360.43 884.59 moveto +(First Movement) show +274.11 1314.68 738.70 5 1.000000 1.000000 stf +274.11 1234.26 738.70 5 1.000000 1.000000 stf +274.11 1170.66 738.70 5 1.000000 0.800000 stf +274.11 1107.06 738.70 1 1.000000 1.000000 stf +274.11 1028.13 738.70 5 1.000000 1.000000 stf +274.11 946.01 738.70 5 1.000000 1.000000 stf +274.11 831.00 738.70 5 1.000000 1.000000 stf +274.11 750.98 738.70 6 1.735000 1.000000 stf +274.11 670.95 738.70 5 1.000000 1.000000 stf +/Times-Roman findfont +12 scalefont +setfont +83.90 766.44 moveto +(Choir) show +/Palatino-Roman findfont +11 scalefont +setfont +78.07 669.93 moveto +(foghorn) show +84.99 657.45 moveto +(in G) show +107.90 659.39 0.583333 flat +110.08 657.45 moveto +/Times-Roman findfont +12 scalefont +setfont +66.62 480.26 moveto +(keyboard) show +/Times-Roman findfont +12 scalefont +setfont +80.59 282.96 moveto +(Guitar) show +/Palatino-Roman findfont +14 scalefont +setfont +65.45 164.05 moveto +(Soprano) show +128.11 825.68 715.26 bracket +129.61 536.13 430.01 brace +128.11 342.00 217.95 bracket +0.70 setlinewidth +130.11 822.68 moveto +130.11 154.95 lineto stroke +% S_CLEFSIG +141.91 804.68 1.000000 gclef +142.16 736.26 1.000000 fclef +138.54 676.26 0.800000 cclef +136.11 595.56 moveto +136.11 610.56 lineto stroke +138.21 595.56 moveto +138.21 610.56 lineto stroke +141.91 518.13 1.000000 gclef +142.16 448.01 1.000000 fclef +141.91 321.00 1.000000 gclef +/Helvetica-Bold findfont +20 scalefont +setfont +133.11 256.92 moveto +(T) show +/Helvetica-Bold findfont +20 scalefont +setfont +133.11 239.04 moveto +(A) show +/Helvetica-Bold findfont +20 scalefont +setfont +133.11 221.16 moveto +(B) show +141.91 160.95 1.000000 gclef +155.95 810.68 1.000000 flat +161.43 819.68 1.000000 flat +166.92 807.68 1.000000 flat +155.95 724.26 1.000000 flat +161.43 733.26 1.000000 flat +166.92 721.26 1.000000 flat +156.06 666.66 0.800000 sharp +161.51 676.26 0.800000 sharp +166.97 669.06 0.800000 sharp +155.95 524.13 1.000000 flat +161.43 533.13 1.000000 flat +166.92 521.13 1.000000 flat +155.95 436.01 1.000000 flat +161.43 445.01 1.000000 flat +166.92 433.01 1.000000 flat +155.95 327.00 1.000000 flat +161.43 336.00 1.000000 flat +166.92 324.00 1.000000 flat +155.95 166.95 1.000000 flat +161.43 175.95 1.000000 flat +166.92 163.95 1.000000 flat +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 810.68 moveto +(9) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 798.48 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 730.26 moveto +(9) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 718.05 moveto +(8) show +/NewCenturySchlbk-Bold findfont +13 scalefont +setfont +172.67 666.66 moveto +(9) show +/NewCenturySchlbk-Bold findfont +13 scalefont +setfont +172.67 656.72 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 603.06 moveto +(9) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 590.85 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 524.13 moveto +(9) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 511.92 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 442.01 moveto +(9) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 429.80 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 327.00 moveto +(9) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 314.79 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 166.95 moveto +(9) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +172.67 154.74 moveto +(8) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +331 linenum +/Helvetica-Oblique findfont +11 scalefont +setfont +211.06 776.32 moveto +(These) show +/Helvetica-Oblique findfont +11 scalefont +setfont +285.74 776.32 moveto +(are) show +/Helvetica-Oblique findfont +11 scalefont +setfont +366.84 776.32 moveto +(the) show +331 linenum +/Helvetica-Oblique findfont +11 scalefont +setfont +211.06 764.51 moveto +(This) show +/Helvetica-Oblique findfont +11 scalefont +setfont +287.74 764.51 moveto +(is) show +/Helvetica-Oblique findfont +11 scalefont +setfont +363.95 764.51 moveto +(verse) show +219.06 804.68 1.000000 4n +228.32 807.68 1.000000 dot +219.06 798.68 1.000000 4n +228.32 801.68 1.000000 dot +219.06 792.68 1.000000 4n +228.32 795.68 1.000000 dot +212.83 792.68 moveto +225.29 792.68 lineto stroke +222.74 793.43 moveto +222.74 825.68 lineto stroke +289.72 804.68 1.000000 4n +298.98 807.68 1.000000 dot +289.72 798.68 1.000000 4n +298.98 801.68 1.000000 dot +289.72 792.68 1.000000 4n +298.98 795.68 1.000000 dot +283.49 792.68 moveto +295.95 792.68 lineto stroke +293.40 793.43 moveto +293.40 825.68 lineto stroke +370.67 810.68 1.000000 4n +379.93 813.68 1.000000 dot +370.67 801.68 1.000000 4n +379.93 801.68 1.000000 dot +370.67 795.68 1.000000 4n +379.93 795.68 1.000000 dot +374.35 796.43 moveto +374.35 831.68 lineto stroke +/Palatino-Roman findfont +14 scalefont +setfont +213.60 835.46 moveto +(Andante ) show +restore +% S_STAFF +% staff 2 +save +219.06 727.26 1.000000 4n +228.32 727.26 1.000000 dot +0.70 setlinewidth +222.74 728.01 moveto +222.74 748.26 lineto stroke +289.72 727.26 1.000000 4n +286.04 726.51 moveto +286.04 707.32 lineto stroke +318.60 724.26 1.000000 8rest +344.67 733.26 1.000000 4n +340.98 732.51 moveto +340.98 713.32 lineto stroke +370.67 736.26 1.000000 4n +379.93 739.26 1.000000 dot +366.99 735.51 moveto +366.99 715.26 lineto stroke +newpath +285.69 708.82 moveto +341.33 714.82 lineto +341.33 711.82 lineto +285.69 705.82 lineto +closepath +fill +219.81 751.26 moveto +219.80 751.41 lineto +263.09 755.16 306.44 756.06 349.85 754.11 curveto +393.25 752.17 436.35 747.40 479.13 739.79 curveto +479.09 739.50 lineto +436.24 746.30 393.13 750.67 349.78 752.62 curveto +306.43 754.56 263.10 754.06 219.81 751.11 curveto +fill +restore +% S_STAFF +% staff 3 +save +202.61 666.66 0.466667 4n +198.01 666.66 0.466667 dblsharp +0.56 setlinewidth +204.21 667.05 moveto +204.21 678.66 lineto stroke +205.72 678.66 0.466667 dnflag +newpath +201.61 669.66 moveto +201.61 670.86 lineto +206.81 676.46 lineto +206.81 675.26 lineto +closepath +fill +219.06 673.86 0.800000 2n +211.55 673.86 0.800000 sharp +226.64 673.86 0.800000 dot +/Palatino-Roman findfont +11 scalefont +setfont +212.92 680.53 moveto +219.06 680.53 0.916667 acc_gt +225.20 680.53 moveto +215.94 673.26 moveto +215.94 657.06 lineto stroke +370.67 666.66 0.800000 4rest +377.52 669.06 0.800000 dot +restore +% S_STAFF +% staff 4 +save +325.58 597.06 1.000000 ll1rest +restore +% S_STAFF +% staff 5 +save +219.06 527.13 1.000000 4n +0.70 setlinewidth +222.74 527.88 moveto +222.74 548.13 lineto stroke +256.90 518.13 1.000000 4n +260.59 518.88 moveto +260.59 539.13 lineto stroke +289.72 527.13 1.000000 4n +298.98 527.13 1.000000 dot +293.40 527.88 moveto +293.40 548.13 lineto stroke +370.67 536.13 1.000000 4n +374.35 536.88 moveto +374.35 557.13 lineto stroke +425.61 536.13 1.000000 4n +429.29 536.88 moveto +429.29 555.63 lineto stroke +443.17 536.13 1.000000 4n +446.85 536.88 moveto +446.85 555.63 lineto stroke +/NewCenturySchlbk-BoldItalic findfont +11 scalefont +setfont +234.81 545.91 moveto +(2) show +215.03 554.41 moveto +232.81 550.77 lineto stroke +243.15 549.06 moveto +260.94 545.41 lineto stroke +215.03 554.41 moveto +215.03 551.41 lineto stroke +260.94 545.41 moveto +260.94 542.41 lineto stroke +newpath +428.94 557.13 moveto +447.20 557.13 lineto +447.20 554.13 lineto +428.94 554.13 lineto +closepath +fill +newpath +428.94 552.13 moveto +447.20 552.13 lineto +447.20 549.13 lineto +428.94 549.13 lineto +closepath +fill +219.06 506.13 1.000000 2n +228.54 503.13 1.000000 dot +212.61 506.13 moveto +225.51 506.13 lineto stroke +215.16 505.38 moveto +215.16 485.13 lineto stroke +370.67 509.13 1.000000 4n +379.93 509.13 1.000000 dot +366.99 508.38 moveto +366.99 488.13 lineto stroke +300.22 512.13 1.000000 4n +303.90 512.88 moveto +303.90 532.22 lineto stroke +318.60 515.13 1.000000 4n +322.28 515.88 moveto +322.28 534.68 lineto stroke +344.67 518.13 1.000000 4n +348.35 518.88 moveto +348.35 538.17 lineto stroke +379.67 521.13 1.000000 4n +371.22 521.13 1.000000 nat +383.35 521.88 moveto +383.35 542.13 lineto stroke +386.38 542.13 1.000000 dnflag +400.18 521.13 1.000000 4n +403.86 521.88 moveto +403.86 542.13 lineto stroke +newpath +303.55 533.72 moveto +348.70 539.67 lineto +348.70 536.67 lineto +303.55 530.72 lineto +closepath +fill +376.70 541.23 moveto +376.68 541.37 lineto +384.59 544.22 392.75 545.64 401.16 545.64 curveto +409.56 545.64 417.72 544.22 425.63 541.37 curveto +425.59 541.08 lineto +417.57 543.12 409.43 544.14 401.16 544.14 curveto +392.88 544.14 384.74 543.12 376.72 541.08 curveto +fill +/Palatino-Roman findfont +14 scalefont +setfont +365.63 561.91 moveto +(VII) show +388.72 569.09 moveto +/Palatino-Roman findfont +9 scalefont +setfont +(6) show +385.12 558.82 moveto +386.92 562.11 0.416667 sharp +388.72 558.82 moveto +388.72 559.64 moveto +(5) show +393.20 561.91 moveto +/Palatino-Roman findfont +14 scalefont +setfont +( ) show +/Palatino-Roman findfont +14 scalefont +setfont +217.04 562.91 moveto +(i ) show +restore +% S_STAFF +% staff 6 +save +219.06 418.01 1.000000 4n +228.32 421.01 1.000000 dot +0.70 setlinewidth +212.83 418.01 moveto +225.29 418.01 lineto stroke +212.83 424.01 moveto +225.29 424.01 lineto stroke +219.06 397.01 1.000000 4n +228.32 397.01 1.000000 dot +212.83 400.01 moveto +225.29 400.01 lineto stroke +212.83 406.01 moveto +225.29 406.01 lineto stroke +212.83 412.01 moveto +225.29 412.01 lineto stroke +212.83 418.01 moveto +225.29 418.01 lineto stroke +212.83 424.01 moveto +225.29 424.01 lineto stroke +222.74 397.76 moveto +222.74 442.01 lineto stroke +289.72 418.01 1.000000 4n +298.98 421.01 1.000000 dot +283.49 418.01 moveto +295.95 418.01 lineto stroke +283.49 424.01 moveto +295.95 424.01 lineto stroke +289.72 397.01 1.000000 4n +298.98 397.01 1.000000 dot +283.49 400.01 moveto +295.95 400.01 lineto stroke +283.49 406.01 moveto +295.95 406.01 lineto stroke +283.49 412.01 moveto +295.95 412.01 lineto stroke +283.49 418.01 moveto +295.95 418.01 lineto stroke +283.49 424.01 moveto +295.95 424.01 lineto stroke +293.40 397.76 moveto +293.40 442.01 lineto stroke +370.67 421.01 1.000000 4n +379.93 421.01 1.000000 dot +364.44 424.01 moveto +376.90 424.01 lineto stroke +370.67 400.01 1.000000 4n +379.93 403.01 1.000000 dot +364.44 400.01 moveto +376.90 400.01 lineto stroke +364.44 406.01 moveto +376.90 406.01 lineto stroke +364.44 412.01 moveto +376.90 412.01 lineto stroke +364.44 418.01 moveto +376.90 418.01 lineto stroke +364.44 424.01 moveto +376.90 424.01 lineto stroke +374.35 400.76 moveto +374.35 442.01 lineto stroke +/Palatino-Roman findfont +14 scalefont +setfont +213.60 466.79 moveto +(Andante ) show +219.06 377.80 moveto +219.06 370.81 lineto stroke +219.06 370.81 moveto +221.59 370.81 lineto stroke +220.92 370.81 moveto +339.96 370.81 lineto stroke +339.63 370.81 moveto +344.67 377.80 lineto stroke +344.67 377.80 moveto +349.71 370.81 lineto stroke +/Palatino-Roman findfont +14 scalefont +setfont +368.43 381.58 moveto +368.43 388.76 moveto +/Palatino-Roman findfont +9 scalefont +setfont +(6) show +368.43 379.31 moveto +(5) show +gsave +0.58 setlinewidth +368.43 380.78 moveto +372.91 383.71 lineto stroke +grestore +372.91 379.31 moveto +372.91 381.58 moveto +/Palatino-Roman findfont +14 scalefont +setfont +( ) show +restore +% S_STAFF +% staff 7 +save +219.06 321.00 1.000000 4n +228.32 324.00 1.000000 dot +219.06 315.00 1.000000 4n +228.32 318.00 1.000000 dot +219.06 309.00 1.000000 4n +228.32 312.00 1.000000 dot +0.70 setlinewidth +212.83 309.00 moveto +225.29 309.00 lineto stroke +222.74 309.75 moveto +222.74 342.00 lineto stroke +289.72 309.00 1.000000 4n +283.49 309.00 moveto +295.95 309.00 lineto stroke +293.40 309.75 moveto +293.40 325.50 lineto stroke +318.60 300.00 1.000000 4n +312.37 303.00 moveto +324.83 303.00 lineto stroke +312.37 309.00 moveto +324.83 309.00 lineto stroke +322.28 300.75 moveto +322.28 325.50 lineto stroke +344.67 309.00 1.000000 4n +338.43 309.00 moveto +350.90 309.00 lineto stroke +348.35 309.75 moveto +348.35 325.50 lineto stroke +370.67 339.00 1.000000 4n +379.93 342.00 1.000000 dot +370.67 333.00 1.000000 4n +379.93 336.00 1.000000 dot +370.67 324.00 1.000000 4n +362.22 324.00 1.000000 nat +379.93 324.00 1.000000 dot +370.67 312.00 1.000000 4n +379.93 312.00 1.000000 dot +374.35 312.75 moveto +374.35 360.00 lineto stroke +newpath +293.05 327.00 moveto +348.70 327.00 lineto +348.70 324.00 lineto +293.05 324.00 lineto +closepath +fill +restore +% S_STAFF +% staff 8 +save +215.71 246.71 222.41 257.65 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +215.71 247.86 moveto +(0) show +215.71 236.51 222.41 247.03 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +215.71 237.52 moveto +(1) show +215.71 225.89 222.41 236.83 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +215.71 227.11 moveto +(3) show +286.37 225.89 293.07 236.83 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +286.37 227.11 moveto +(3) show +315.25 215.48 321.95 226.42 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +315.25 216.70 moveto +(3) show +341.32 225.89 348.01 236.83 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +341.32 227.11 moveto +(3) show +367.32 267.74 374.02 278.26 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +367.32 268.75 moveto +(1) show +367.32 257.12 374.02 268.06 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +367.32 258.34 moveto +(3) show +367.32 246.82 374.02 257.54 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +367.32 247.75 moveto +(2) show +367.32 236.30 374.02 247.24 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +367.32 237.45 moveto +(0) show +restore +% S_STAFF +% staff 9 +save +331 linenum +0.70 setlinewidth +232.87 138.97 moveto +484.11 138.97 lineto stroke +/Helvetica-Oblique findfont +11 scalefont +setfont +214.45 138.97 moveto +(ah) show +219.06 169.95 1.000000 fillrectangle +228.54 169.95 1.000000 dot +215.16 169.95 moveto +215.16 148.95 lineto stroke +289.72 175.95 1.000000 fillisostriangle +285.82 173.55 moveto +285.82 153.45 lineto stroke +318.60 169.95 1.000000 fillrectangle +314.70 169.95 moveto +314.70 153.45 lineto stroke +344.67 175.95 1.000000 fillisostriangle +340.77 173.55 moveto +340.77 153.45 lineto stroke +370.67 178.95 1.000000 fillsemicircle +380.15 181.95 1.000000 dot +366.77 181.35 moveto +366.77 157.95 lineto stroke +newpath +285.47 154.95 moveto +341.12 154.95 lineto +341.12 151.95 lineto +285.47 151.95 lineto +closepath +fill +restore +% S_BAR +331 linenum +0.70 setlinewidth +461.45 822.68 moveto +461.45 798.68 lineto stroke +461.45 742.26 moveto +461.45 718.26 lineto stroke +461.45 676.26 moveto +461.45 657.06 lineto stroke +461.45 609.06 moveto +461.45 597.06 lineto stroke +461.45 536.13 moveto +461.45 430.01 lineto stroke +461.45 339.00 moveto +461.45 220.95 lineto stroke +461.45 178.95 moveto +461.45 154.95 lineto stroke +/Palatino-Bold findfont +12 scalefont +setfont +gsave +newpath +1.000000 1.000000 scale +461.45 355.72 7.72 0 360 arc +1.000000 1.000000 scale +1.000000 1.000000 scale +461.45 355.72 7.22 0 360 arc +eofill +grestore +456.77 351.65 moveto +(A) show +/Palatino-Bold findfont +12 scalefont +setfont +gsave +newpath +1.000000 1.000000 scale +461.45 552.85 7.72 0 360 arc +1.000000 1.000000 scale +1.000000 1.000000 scale +461.45 552.85 7.22 0 360 arc +eofill +grestore +456.77 548.78 moveto +(A) show +/Palatino-Bold findfont +12 scalefont +setfont +gsave +newpath +1.000000 1.000000 scale +461.45 839.41 7.72 0 360 arc +1.000000 1.000000 scale +1.000000 1.000000 scale +461.45 839.41 7.22 0 360 arc +eofill +grestore +456.77 835.34 moveto +(A) show +0.70 setlinewidth +349.37 370.81 moveto +460.45 370.81 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +331 linenum +/Helvetica-Oblique findfont +11 scalefont +setfont +470.24 776.32 moveto +(words!) show +331 linenum +/Helvetica-Oblique findfont +11 scalefont +setfont +465.97 764.51 moveto +(two) show +/Ext-Helvetica-Oblique findfont +11 scalefont +setfont +() show +/Helvetica-Oblique findfont +11 scalefont +setfont +(oh) show +/Ext-Helvetica-Oblique findfont +11 scalefont +setfont +() show +/Helvetica-Oblique findfont +11 scalefont +setfont +(yes.) show +479.86 813.68 1.000000 2n +489.34 813.68 1.000000 dot +479.86 804.68 1.000000 2n +489.34 807.68 1.000000 dot +479.86 792.68 1.000000 2n +489.34 795.68 1.000000 dot +473.41 792.68 moveto +486.31 792.68 lineto stroke +483.76 793.43 moveto +483.76 834.68 lineto stroke +682.24 810.68 1.000000 4rest +690.54 813.68 1.000000 dot +/Palatino-Italic findfont +13 scalefont +setfont +674.54 845.57 moveto +(To coda ) show +727.93 854.86 1.083333 coda +737.72 845.57 moveto +/Times-Roman findfont +13 scalefont +setfont +674.54 831.68 moveto +restore +% S_STAFF +% staff 2 +save +479.86 733.26 1.000000 2n +489.34 733.26 1.000000 dot +479.86 727.26 1.000000 2n +489.34 727.26 1.000000 dot +0.70 setlinewidth +475.96 732.51 moveto +475.96 706.26 lineto stroke +682.24 730.26 1.000000 4rest +690.54 733.26 1.000000 dot +restore +% S_STAFF +% staff 3 +save +479.86 673.86 0.800000 2n +470.53 673.86 0.800000 dblflat +487.44 673.86 0.800000 dot +0.56 setlinewidth +476.74 673.26 moveto +476.74 657.06 lineto stroke +682.24 666.66 0.800000 4rest +689.09 669.06 0.800000 dot +restore +% S_STAFF +% staff 4 +save +479.86 603.06 1.000000 4n +489.12 606.06 1.000000 dot +0.70 setlinewidth +483.54 603.81 moveto +483.54 624.06 lineto stroke +574.99 603.06 1.000000 ll2rest +584.26 606.06 1.000000 dot +restore +% S_STAFF +% staff 5 +save +479.86 548.13 1.000000 2n +489.34 551.13 1.000000 dot +0.70 setlinewidth +473.41 548.13 moveto +486.31 548.13 lineto stroke +473.41 542.13 moveto +486.31 542.13 lineto stroke +483.76 548.88 moveto +483.76 569.13 lineto stroke +682.24 536.13 1.000000 4rest +690.54 539.13 1.000000 dot +479.86 512.13 1.000000 4n +476.18 511.38 moveto +476.18 495.63 lineto stroke +522.39 518.13 1.000000 4n +518.71 517.38 moveto +518.71 495.63 lineto stroke +549.56 512.13 1.000000 4n +545.88 511.38 moveto +545.88 495.63 lineto stroke +574.99 518.13 1.000000 4n +571.31 517.38 moveto +571.31 495.63 lineto stroke +591.72 512.13 1.000000 4n +588.03 511.38 moveto +588.03 495.63 lineto stroke +608.44 518.13 1.000000 4n +604.76 517.38 moveto +604.76 495.63 lineto stroke +625.17 512.13 1.000000 4n +621.48 511.38 moveto +621.48 495.63 lineto stroke +641.89 518.13 1.000000 4n +638.21 517.38 moveto +638.21 495.63 lineto stroke +658.78 512.13 1.000000 4n +655.09 511.38 moveto +655.09 495.63 lineto stroke +682.24 512.13 1.000000 4rest +690.54 515.13 1.000000 dot +newpath +475.83 497.13 moveto +546.23 497.13 lineto +546.23 494.13 lineto +475.83 494.13 lineto +closepath +fill +newpath +570.96 497.13 moveto +655.44 497.13 lineto +655.44 494.13 lineto +570.96 494.13 lineto +closepath +fill +newpath +570.96 502.13 moveto +588.38 502.13 lineto +588.38 499.13 lineto +570.96 499.13 lineto +closepath +fill +newpath +604.41 502.13 moveto +621.83 502.13 lineto +621.83 499.13 lineto +604.41 499.13 lineto +closepath +fill +newpath +637.86 502.13 moveto +655.44 502.13 lineto +655.44 499.13 lineto +637.86 499.13 lineto +closepath +fill +restore +% S_STAFF +% staff 6 +save +479.86 418.01 1.000000 2n +489.34 421.01 1.000000 dot +0.70 setlinewidth +473.41 418.01 moveto +486.31 418.01 lineto stroke +473.41 424.01 moveto +486.31 424.01 lineto stroke +483.76 418.76 moveto +483.76 440.51 lineto stroke +newpath +483.76 434.01 moveto +483.76 437.01 lineto +578.89 455.94 lineto +578.89 452.94 lineto +closepath +fill +newpath +483.76 439.01 moveto +483.76 442.01 lineto +578.89 460.94 lineto +578.89 457.94 lineto +closepath +fill +574.99 439.01 1.000000 2n +584.47 439.01 1.000000 dot +578.89 439.76 moveto +578.89 459.44 lineto stroke +682.24 442.01 1.000000 4rest +690.54 445.01 1.000000 dot +460.45 370.81 moveto +475.15 370.81 lineto stroke +474.82 370.81 moveto +479.86 377.80 lineto stroke +479.86 377.80 moveto +484.90 370.81 lineto stroke +484.57 370.81 moveto +639.62 370.81 lineto stroke +638.95 370.81 moveto +641.89 370.81 lineto stroke +641.89 377.80 moveto +641.89 370.81 lineto stroke +restore +% S_STAFF +% staff 7 +save +479.86 342.00 1.000000 2n +489.34 342.00 1.000000 dot +479.86 330.00 1.000000 2n +489.34 330.00 1.000000 dot +479.86 321.00 1.000000 2n +489.34 324.00 1.000000 dot +479.86 315.00 1.000000 2n +489.34 318.00 1.000000 dot +0.70 setlinewidth +475.96 341.25 moveto +475.96 289.20 lineto stroke +newpath +470.96 300.50 moveto +470.96 303.50 lineto +480.96 307.90 lineto +480.96 304.90 lineto +closepath +fill +newpath +470.96 295.50 moveto +470.96 298.50 lineto +480.96 302.90 lineto +480.96 299.90 lineto +closepath +fill +newpath +470.96 290.50 moveto +470.96 293.50 lineto +480.96 297.90 lineto +480.96 294.90 lineto +closepath +fill +682.24 327.00 1.000000 4rest +690.54 330.00 1.000000 dot +restore +% S_STAFF +% staff 8 +save +476.51 267.53 483.21 278.47 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +476.51 268.75 moveto +(3) show +476.51 257.33 483.21 267.85 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +476.51 258.34 moveto +(1) show +476.51 246.71 483.21 257.65 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +476.51 247.86 moveto +(0) show +476.51 236.51 483.21 247.03 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +476.51 237.52 moveto +(1) show +newpath +474.86 227.27 moveto +474.86 230.27 lineto +484.86 234.67 lineto +484.86 231.67 lineto +closepath +fill +newpath +474.86 222.27 moveto +474.86 225.27 lineto +484.86 229.67 lineto +484.86 226.67 lineto +closepath +fill +newpath +474.86 217.27 moveto +474.86 220.27 lineto +484.86 224.67 lineto +484.86 221.67 lineto +closepath +fill +restore +% S_STAFF +% staff 9 +save +479.86 175.95 1.000000 isostriangle +489.34 175.95 1.000000 dot +0.70 setlinewidth +475.96 173.55 moveto +475.96 154.95 lineto stroke +682.24 166.95 1.000000 4rest +690.54 169.95 1.000000 dot +restore +% S_BAR +331 linenum +0.70 setlinewidth +735.35 822.68 moveto +735.35 798.68 lineto stroke +738.35 822.68 moveto +738.35 798.68 lineto stroke +735.35 742.26 moveto +735.35 718.26 lineto stroke +738.35 742.26 moveto +738.35 718.26 lineto stroke +735.35 676.26 moveto +735.35 657.06 lineto stroke +738.35 676.26 moveto +738.35 657.06 lineto stroke +735.35 609.06 moveto +735.35 597.06 lineto stroke +738.35 609.06 moveto +738.35 597.06 lineto stroke +735.35 536.13 moveto +735.35 430.01 lineto stroke +738.35 536.13 moveto +738.35 430.01 lineto stroke +735.35 339.00 moveto +735.35 220.95 lineto stroke +738.35 339.00 moveto +738.35 220.95 lineto stroke +735.35 178.95 moveto +735.35 154.95 lineto stroke +738.35 178.95 moveto +738.35 154.95 lineto stroke +% S_FEED +336 linenum +% Printing header/footer +/Times-Roman findfont +18 scalefont +setfont +251.47 939.19 moveto +(Sample Song to Show What Mup Can Do) show +/Palatino-Italic findfont +12 scalefont +setfont +362.15 925.15 moveto +(This is a subtitle) show +/Times-Roman findfont +12 scalefont +setfont +65.45 912.33 moveto +(Text: Ann Onymous) show +/Times-Roman findfont +12 scalefont +setfont +625.73 912.33 moveto +(Tune: Arthur Unknown) show +/Times-Roman findfont +12 scalefont +setfont +65.45 899.51 moveto +/Times-Roman findfont +12 scalefont +setfont +706.88 899.51 moveto +(\(1995\)) show +/Times-Roman findfont +12 scalefont +setfont +323.99 103.77 moveto +(This is a sample of a Mup footer) show +/Times-Roman findfont +12 scalefont +setfont +400.57 90.96 moveto +( ) show +/Times-Roman findfont +11 scalefont +setfont +65.45 79.21 moveto +(Published by Arkkra Enterprises) show +/Times-Roman findfont +11 scalefont +setfont +320.17 79.21 moveto +(P. O. Box 315 Warrenville, IL 60555) show +/Times-Roman findfont +11 scalefont +setfont +636.34 79.21 moveto +(http://www.arkkra.com) show +showpage +restore +%%Page: 2 2 +save +1361190600 1361190394 sv +0.770000 0.770000 scale +/Times-Roman findfont +12 scalefont +setfont +364.28 930.22 moveto +(First movement) show +240.05 1338.43 1098.70 5 1.000000 1.000000 stf +/Helvetica-Oblique findfont +9 scalefont +setfont +100.55 860.43 moveto +(3) show +240.05 1255.27 1098.70 5 1.000000 1.000000 stf +240.05 1191.67 1098.70 5 1.000000 0.800000 stf +240.05 1125.09 1098.70 1 1.000000 1.000000 stf +240.05 1052.07 1098.70 5 1.000000 1.000000 stf +/Helvetica-Oblique findfont +9 scalefont +setfont +100.55 574.07 moveto +(3) show +240.05 979.83 1098.70 5 1.000000 1.000000 stf +240.05 895.55 1098.70 5 1.000000 1.000000 stf +/Helvetica-Oblique findfont +9 scalefont +setfont +100.55 417.55 moveto +(3) show +240.05 791.31 1098.70 6 1.735000 1.000000 stf +240.05 711.29 1098.70 5 1.000000 1.000000 stf +/Times-Roman findfont +12 scalefont +setfont +72.08 788.82 moveto +(Ch) show +/Times-Roman findfont +12 scalefont +setfont +65.45 507.92 moveto +(Kbd) show +/Times-Roman findfont +12 scalefont +setfont +70.13 335.40 moveto +(Gtr) show +94.05 849.43 736.27 bracket +95.55 560.07 463.83 brace +94.05 406.55 258.29 bracket +0.70 setlinewidth +96.05 846.43 moveto +96.05 195.29 lineto stroke +316.27 429.55 moveto +316.27 440.55 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +319.27 430.55 moveto +(1.) show +316.27 440.55 moveto +419.86 440.55 lineto stroke +419.86 440.55 moveto +419.86 429.55 lineto stroke +316.27 578.09 moveto +316.27 589.09 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +319.27 579.09 moveto +(1.) show +316.27 589.09 moveto +419.86 589.09 lineto stroke +419.86 589.09 moveto +419.86 578.09 lineto stroke +316.27 899.98 moveto +316.27 910.98 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +319.27 900.98 moveto +(1.) show +316.27 910.98 moveto +419.86 910.98 lineto stroke +419.86 910.98 moveto +419.86 899.98 lineto stroke +423.86 429.55 moveto +423.86 440.55 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +426.86 430.55 moveto +(2.) show +423.86 440.55 moveto +579.34 440.55 lineto stroke +423.86 578.09 moveto +423.86 589.09 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +426.86 579.09 moveto +(2.) show +423.86 589.09 moveto +579.34 589.09 lineto stroke +423.86 899.98 moveto +423.86 910.98 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +426.86 900.98 moveto +(2.) show +423.86 910.98 moveto +579.34 910.98 lineto stroke +% S_CLEFSIG +107.84 828.43 1.000000 gclef +108.09 757.27 1.000000 fclef +104.47 697.27 0.800000 cclef +102.05 613.59 moveto +102.05 628.59 lineto stroke +104.15 613.59 moveto +104.15 628.59 lineto stroke +107.84 542.07 1.000000 gclef +108.09 481.83 1.000000 fclef +107.84 385.55 1.000000 gclef +107.84 201.29 1.000000 gclef +121.88 834.43 1.000000 flat +127.37 843.43 1.000000 flat +132.85 831.43 1.000000 flat +121.88 745.27 1.000000 flat +127.37 754.27 1.000000 flat +132.85 742.27 1.000000 flat +121.99 687.67 0.800000 sharp +127.45 697.27 0.800000 sharp +132.90 690.07 0.800000 sharp +121.88 548.07 1.000000 flat +127.37 557.07 1.000000 flat +132.85 545.07 1.000000 flat +121.88 469.83 1.000000 flat +127.37 478.83 1.000000 flat +132.85 466.83 1.000000 flat +121.88 391.55 1.000000 flat +127.37 400.55 1.000000 flat +132.85 388.55 1.000000 flat +121.88 207.29 1.000000 flat +127.37 216.29 1.000000 flat +132.85 204.29 1.000000 flat +% S_CHHEAD +% S_STAFF +% staff 1 +save +165.79 816.43 1.000000 2n +175.27 819.43 1.000000 dot +159.34 816.43 moveto +172.24 816.43 lineto stroke +169.69 817.18 moveto +169.69 837.43 lineto stroke +267.32 828.43 1.000000 4n +276.59 831.43 1.000000 dot +271.01 829.18 moveto +271.01 849.43 lineto stroke +/Times-Roman findfont +14 scalefont +setfont +155.67 887.89 moveto +(Cm) show +153.79 880.03 4.80 5 3 1 2 6 [ -2 1 3 3 2 1 ] grid +restore +% S_STAFF +% staff 2 +save +165.79 754.27 1.000000 4n +175.06 754.27 1.000000 dot +0.70 setlinewidth +162.11 753.52 moveto +162.11 733.27 lineto stroke +213.33 754.27 1.000000 4n +222.59 754.27 1.000000 dot +229.06 754.27 1.000000 dot +209.65 753.52 moveto +209.65 729.77 lineto stroke +242.03 757.27 1.000000 4n +238.35 756.52 moveto +238.35 733.85 lineto stroke +252.89 760.27 1.000000 4n +249.20 759.52 moveto +249.20 735.39 lineto stroke +267.32 748.27 1.000000 4n +276.59 748.27 1.000000 dot +271.01 749.02 moveto +271.01 769.27 lineto stroke +newpath +209.30 731.27 moveto +249.55 736.89 lineto +249.55 733.89 lineto +209.30 728.27 lineto +closepath +fill +newpath +238.00 740.35 moveto +229.94 739.21 lineto +229.94 736.21 lineto +238.00 737.35 lineto +closepath +fill +newpath +238.00 745.35 moveto +229.94 744.21 lineto +229.94 741.21 lineto +238.00 742.35 lineto +closepath +fill +198.10 722.27 moveto +278.32 726.27 lineto stroke +198.10 722.27 moveto +278.32 718.26 lineto stroke +restore +% S_STAFF +% staff 3 +save +165.79 690.07 0.800000 2n +158.97 690.07 0.800000 nat +173.38 690.07 0.800000 dot +178.70 690.07 0.800000 dot +0.56 setlinewidth +162.67 689.47 moveto +162.67 673.27 lineto stroke +289.31 690.07 0.800000 4n +286.37 689.47 moveto +286.37 673.27 lineto stroke +/Palatino-Roman findfont +11 scalefont +setfont +282.58 701.96 moveto +289.31 701.96 0.916667 turn +296.04 701.96 moveto +173.15 703.79 moveto +267.32 703.79 0.800000 wavy +/Palatino-Roman findfont +11 scalefont +setfont +158.43 698.99 moveto +165.79 698.99 0.916667 tr +173.15 698.99 moveto +restore +% S_STAFF +% staff 4 +save +165.79 621.09 1.000000 2n +175.27 624.09 1.000000 dot +0.70 setlinewidth +169.69 621.84 moveto +169.69 642.09 lineto stroke +newpath +164.69 628.39 moveto +164.69 631.39 lineto +174.69 635.79 lineto +174.69 632.79 lineto +closepath +fill +newpath +164.69 633.39 moveto +164.69 636.39 lineto +174.69 640.79 lineto +174.69 637.79 lineto +closepath +fill +267.32 621.09 1.000000 4n +276.59 624.09 1.000000 dot +/Palatino-Roman findfont +14 scalefont +setfont +264.72 614.55 moveto +267.32 614.55 1.166667 dot +269.93 614.55 moveto +271.01 621.84 moveto +271.01 642.09 lineto stroke +restore +% S_STAFF +% staff 5 +save +165.79 542.07 1.000000 4n +175.06 545.07 1.000000 dot +165.79 536.07 1.000000 4n +175.06 539.07 1.000000 dot +165.79 530.07 1.000000 4n +175.06 533.07 1.000000 dot +0.70 setlinewidth +159.56 530.07 moveto +172.02 530.07 lineto stroke +169.47 530.82 moveto +169.47 563.07 lineto stroke +154.76 545.35 moveto +154.76 526.79 1.000000 wavy +154.76 548.35 moveto +150.76 540.35 lineto stroke +154.76 548.35 moveto +158.76 540.35 lineto stroke +213.33 542.07 1.000000 4n +222.59 545.07 1.000000 dot +213.33 536.07 1.000000 4n +222.59 539.07 1.000000 dot +213.33 530.07 1.000000 4n +222.59 533.07 1.000000 dot +207.10 530.07 moveto +219.56 530.07 lineto stroke +217.01 530.82 moveto +217.01 563.07 lineto stroke +202.30 545.35 moveto +202.30 526.79 1.000000 wavy +202.30 523.79 moveto +198.30 531.79 lineto stroke +202.30 523.79 moveto +206.30 531.79 lineto stroke +267.32 542.07 1.000000 4n +276.59 545.07 1.000000 dot +267.32 536.07 1.000000 4n +276.59 539.07 1.000000 dot +267.32 530.07 1.000000 4n +276.59 533.07 1.000000 dot +261.09 530.07 moveto +273.56 530.07 lineto stroke +271.01 530.82 moveto +271.01 563.07 lineto stroke +256.29 545.35 moveto +256.29 526.79 1.000000 wavy +/Times-BoldItalic findfont +14 scalefont +setfont +265.01 512.04 moveto +(ff ) show +restore +% S_STAFF +% staff 6 +save +164.02 478.83 0.583333 2n +175.27 478.83 1.000000 dot +165.79 472.83 1.000000 2n +175.27 472.83 1.000000 dot +0.70 setlinewidth +161.89 478.34 moveto +161.89 451.83 lineto stroke +267.32 478.83 1.000000 4n +263.64 478.08 moveto +263.64 457.83 lineto stroke +266.67 457.83 1.000000 upflag +289.31 472.83 1.000000 4n +292.99 473.58 moveto +292.99 493.83 lineto stroke +269.32 483.93 moveto +269.33 484.16 lineto +272.99 485.22 276.63 485.20 280.27 484.11 curveto +283.91 483.01 286.97 481.02 289.43 478.12 curveto +289.19 477.73 lineto +286.48 480.14 283.39 481.87 279.92 482.92 curveto +276.44 483.96 272.91 484.22 269.32 483.69 curveto +fill +restore +% S_STAFF +% staff 7 +save +165.79 409.55 1.000000 4n +157.34 409.55 1.000000 nat +175.06 412.55 1.000000 dot +0.70 setlinewidth +159.56 409.55 moveto +172.02 409.55 lineto stroke +169.47 410.30 moveto +169.47 430.55 lineto stroke +213.33 412.55 1.000000 4n +222.59 412.55 1.000000 dot +207.10 409.55 moveto +219.56 409.55 lineto stroke +217.01 413.30 moveto +217.01 433.55 lineto stroke +267.32 412.55 1.000000 4n +258.87 412.55 1.000000 nat +261.09 409.55 moveto +273.56 409.55 lineto stroke +271.01 413.30 moveto +271.01 433.55 lineto stroke +274.03 433.55 1.000000 dnflag +289.31 409.55 1.000000 4n +283.08 409.55 moveto +295.54 409.55 lineto stroke +292.99 410.30 moveto +292.99 430.55 lineto stroke +165.79 385.55 1.000000 4n +175.06 382.55 1.000000 dot +162.11 384.80 moveto +162.11 364.55 lineto stroke +213.33 385.55 1.000000 4n +209.65 384.80 moveto +209.65 364.55 lineto stroke +252.89 385.55 1.000000 4n +249.20 384.80 moveto +249.20 364.55 lineto stroke +252.23 364.55 1.000000 upflag +267.32 385.55 1.000000 4n +276.59 382.55 1.000000 dot +263.64 384.80 moveto +263.64 364.55 lineto stroke +273.36 417.65 moveto +281.86 418.94 lineto stroke +281.86 418.94 moveto +289.31 414.65 lineto stroke +227.59 417.65 moveto +247.46 425.75 lineto stroke +247.46 425.75 moveto +267.32 417.65 lineto stroke +180.06 414.65 moveto +195.97 424.22 lineto stroke +195.97 424.22 moveto +213.33 417.65 lineto stroke +restore +% S_STAFF +% staff 8 +save +162.44 307.87 169.14 318.81 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +162.44 309.09 moveto +(5) show +/Helvetica findfont +12 scalefont +setfont +204.98 331.11 moveto +(1/2) show +0.70 setlinewidth +171.64 314.34 moveto +173.72 314.22 175.81 314.22 177.89 314.34 curveto +185.58 314.76 193.26 315.32 200.82 316.86 curveto +202.25 317.15 203.69 317.42 204.99 318.12 curveto +208.24 319.87 211.64 321.45 213.33 325.06 curveto +213.63 325.69 213.63 326.32 213.33 326.95 curveto +stroke +213.33 324.53 1.000000 uwedge +/Helvetica findfont +12 scalefont +setfont +259.66 346.72 moveto +(full) show +213.33 327.95 moveto +216.03 327.82 218.73 327.82 221.43 327.95 curveto +231.38 328.44 241.31 329.08 251.13 330.88 curveto +252.97 331.21 254.82 331.51 256.53 332.34 curveto +260.63 334.33 265.07 335.89 267.32 340.38 curveto +267.69 341.11 267.69 341.84 267.32 342.57 curveto +stroke +267.32 340.15 1.000000 uwedge +267.32 343.57 moveto +268.42 343.80 269.52 343.80 270.62 343.57 curveto +275.03 342.64 279.11 340.95 282.72 338.21 curveto +283.66 337.49 284.36 336.57 284.92 335.53 curveto +287.37 330.91 288.56 325.91 289.31 320.78 curveto +289.51 319.44 289.51 318.10 289.31 316.76 curveto +stroke +289.31 314.34 1.000000 wedge +162.44 287.05 169.14 297.99 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +162.44 288.20 moveto +(0) show +209.98 287.05 216.68 297.99 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +209.98 288.20 moveto +(0) show +249.54 287.05 256.23 297.99 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +249.54 288.20 moveto +(0) show +263.98 287.05 270.67 297.99 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +263.98 288.20 moveto +(0) show +restore +% S_STAFF +% staff 9 +save +165.79 210.29 1.000000 fillrectangle +0.70 setlinewidth +161.89 210.29 moveto +161.89 191.55 lineto stroke +180.19 207.29 1.000000 4n +176.51 206.54 moveto +176.51 188.89 lineto stroke +198.10 204.29 1.000000 ufillrighttriangle +189.43 204.29 1.000000 nat +194.20 204.29 moveto +194.20 185.57 lineto stroke +213.33 201.29 1.000000 filldiamond +217.23 201.29 moveto +217.23 216.99 lineto stroke +227.77 189.29 1.000000 fillrectangle +221.32 189.29 moveto +234.22 189.29 lineto stroke +231.67 189.29 moveto +231.67 214.26 lineto stroke +252.89 192.29 1.000000 fillpiewedge +256.78 192.59 moveto +256.78 209.52 lineto stroke +267.32 195.29 1.000000 fillisostriangle +276.80 198.29 1.000000 dot +271.22 192.89 moveto +271.22 216.29 lineto stroke +newpath +161.54 193.05 moveto +194.55 187.07 lineto +194.55 184.07 lineto +161.54 190.05 lineto +closepath +fill +newpath +216.88 218.49 moveto +257.13 211.02 lineto +257.13 208.02 lineto +216.88 215.49 lineto +closepath +fill +restore +% S_LINE +345 linenum +gsave +179.04 816.43 translate +9.1 rotate +/Palatino-Italic findfont +11 scalefont +setfont +26.65 6.89 moveto +(gliss.) show +grestore +179.04 816.43 moveto +254.29 828.43 1.000000 wavy +% S_CURVE +480 linenum +441.19 484.83 moveto +441.10 484.94 lineto +461.94 513.57 488.54 535.07 520.90 549.43 curveto +547.42 561.20 574.40 569.92 603.93 562.46 curveto +641.95 552.86 670.65 531.02 690.05 496.95 curveto +689.87 496.71 lineto +670.10 530.27 641.31 551.71 603.49 561.03 curveto +574.36 568.21 547.73 559.54 521.55 548.08 curveto +489.27 533.95 462.52 512.83 441.29 484.71 curveto +fill +% S_BAR +388 linenum +0.70 setlinewidth +314.27 846.43 moveto +314.27 822.43 lineto stroke +314.27 763.27 moveto +314.27 739.27 lineto stroke +314.27 697.27 moveto +314.27 678.07 lineto stroke +314.27 627.09 moveto +314.27 615.09 lineto stroke +314.27 560.07 moveto +314.27 463.83 lineto stroke +314.27 403.55 moveto +314.27 261.29 lineto stroke +314.27 219.29 moveto +314.27 195.29 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +1.50 setlinewidth +331.38 828.43 moveto +331.38 840.43 lineto stroke +400.24 828.43 moveto +400.24 840.43 lineto stroke +3.00 setlinewidth +331.38 834.43 moveto +400.24 834.43 lineto stroke +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +361.20 849.43 moveto +(2) show +restore +% S_STAFF +% staff 2 +save +1.50 setlinewidth +331.38 745.27 moveto +331.38 757.27 lineto stroke +400.24 745.27 moveto +400.24 757.27 lineto stroke +3.00 setlinewidth +331.38 751.27 moveto +400.24 751.27 lineto stroke +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +361.20 766.27 moveto +(2) show +restore +% S_STAFF +% staff 3 +save +1.20 setlinewidth +335.22 682.87 moveto +335.22 692.47 lineto stroke +396.40 682.87 moveto +396.40 692.47 lineto stroke +2.40 setlinewidth +335.22 687.67 moveto +396.40 687.67 lineto stroke +/NewCenturySchlbk-Bold findfont +13 scalefont +setfont +362.07 699.67 moveto +(2) show +restore +% S_STAFF +% staff 4 +save +1.50 setlinewidth +331.38 615.09 moveto +331.38 627.09 lineto stroke +400.24 615.09 moveto +400.24 627.09 lineto stroke +3.00 setlinewidth +331.38 621.09 moveto +400.24 621.09 lineto stroke +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +361.20 627.09 moveto +(2) show +restore +% S_STAFF +% staff 5 +save +1.50 setlinewidth +331.38 542.07 moveto +331.38 554.07 lineto stroke +400.24 542.07 moveto +400.24 554.07 lineto stroke +3.00 setlinewidth +331.38 548.07 moveto +400.24 548.07 lineto stroke +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +361.20 563.07 moveto +(2) show +restore +% S_STAFF +% staff 6 +save +1.50 setlinewidth +331.38 469.83 moveto +331.38 481.83 lineto stroke +400.24 469.83 moveto +400.24 481.83 lineto stroke +3.00 setlinewidth +331.38 475.83 moveto +400.24 475.83 lineto stroke +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +361.20 490.83 moveto +(2) show +restore +% S_STAFF +% staff 7 +save +1.50 setlinewidth +331.38 385.55 moveto +331.38 397.55 lineto stroke +400.24 385.55 moveto +400.24 397.55 lineto stroke +3.00 setlinewidth +331.38 391.55 moveto +400.24 391.55 lineto stroke +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +361.20 406.55 moveto +(2) show +restore +% S_STAFF +% staff 8 +save +restore +% S_STAFF +% staff 9 +save +1.50 setlinewidth +331.38 201.29 moveto +331.38 213.29 lineto stroke +400.24 201.29 moveto +400.24 213.29 lineto stroke +3.00 setlinewidth +331.38 207.29 moveto +400.24 207.29 lineto stroke +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +361.20 222.29 moveto +(2) show +restore +% S_BAR +394 linenum +417.86 837.43 1.000000 dot +417.86 831.43 1.000000 dot +0.70 setlinewidth +421.86 846.43 moveto +421.86 822.43 lineto stroke +3.00 setlinewidth +425.86 846.43 moveto +425.86 822.43 lineto stroke +0.70 setlinewidth +417.86 754.27 1.000000 dot +417.86 748.27 1.000000 dot +421.86 763.27 moveto +421.86 739.27 lineto stroke +3.00 setlinewidth +425.86 763.27 moveto +425.86 739.27 lineto stroke +0.70 setlinewidth +417.86 690.07 0.800000 dot +417.86 685.27 0.800000 dot +421.86 697.27 moveto +421.86 678.07 lineto stroke +3.00 setlinewidth +425.86 697.27 moveto +425.86 678.07 lineto stroke +0.70 setlinewidth +417.86 624.09 1.000000 dot +417.86 618.09 1.000000 dot +421.86 627.09 moveto +421.86 615.09 lineto stroke +3.00 setlinewidth +425.86 627.09 moveto +425.86 615.09 lineto stroke +0.70 setlinewidth +417.86 551.07 1.000000 dot +417.86 545.07 1.000000 dot +417.86 478.83 1.000000 dot +417.86 472.83 1.000000 dot +421.86 560.07 moveto +421.86 463.83 lineto stroke +3.00 setlinewidth +425.86 560.07 moveto +425.86 463.83 lineto stroke +0.70 setlinewidth +417.86 394.55 1.000000 dot +417.86 388.55 1.000000 dot +417.86 297.72 1.000000 dot +417.86 276.90 1.000000 dot +421.86 403.55 moveto +421.86 261.29 lineto stroke +3.00 setlinewidth +425.86 403.55 moveto +425.86 261.29 lineto stroke +0.70 setlinewidth +417.86 210.29 1.000000 dot +417.86 204.29 1.000000 dot +421.86 219.29 moveto +421.86 195.29 lineto stroke +3.00 setlinewidth +425.86 219.29 moveto +425.86 195.29 lineto stroke +0.70 setlinewidth +% S_SSV +398 linenum +% S_CHHEAD +% S_STAFF +% staff 1 +save +423 linenum +/Helvetica-Oblique findfont +14 scalefont +setfont +466.96 787.40 moveto +(-) show +/Helvetica-Oblique findfont +11 scalefont +setfont +435.17 787.40 moveto +/Helvetica-Oblique findfont +14 scalefont +setfont +(Ma) show +/Helvetica-Oblique findfont +14 scalefont +setfont +511.97 787.40 moveto +(-) show +/Helvetica-Oblique findfont +14 scalefont +setfont +482.26 787.40 moveto +/Ext-Helvetica-Oblique findfont +14 scalefont +setfont +(f) show +/Helvetica-Oblique findfont +14 scalefont +setfont +(a) show +/Helvetica-Oblique findfont +14 scalefont +setfont +529.04 787.40 moveto +(na) show +441.19 822.43 1.000000 4n +450.46 825.43 1.000000 dot +441.19 816.43 1.000000 4n +450.46 819.43 1.000000 dot +434.96 816.43 moveto +447.43 816.43 lineto stroke +444.88 817.18 moveto +444.88 843.43 lineto stroke +487.32 828.43 1.000000 4n +496.59 831.43 1.000000 dot +487.32 822.43 1.000000 4n +496.59 825.43 1.000000 dot +491.01 823.18 moveto +491.01 849.43 lineto stroke +532.95 822.43 1.000000 4n +542.21 825.43 1.000000 dot +532.95 816.43 1.000000 4n +542.21 819.43 1.000000 dot +526.72 816.43 moveto +539.18 816.43 lineto stroke +536.63 817.18 moveto +536.63 843.43 lineto stroke +441.94 810.16 moveto +441.95 810.31 lineto +483.13 806.43 524.40 804.99 565.75 805.99 curveto +607.10 806.99 648.25 810.43 689.19 816.31 curveto +689.22 816.01 lineto +648.34 809.33 607.20 805.50 565.79 804.49 curveto +524.38 803.49 483.09 805.33 441.94 810.01 curveto +fill +/Times-Roman findfont +14 scalefont +setfont +431.07 887.89 moveto +(Cm) show +429.19 880.03 4.80 5 3 1 2 6 [ -2 1 3 3 2 1 ] grid +restore +% S_STAFF +% staff 2 +save +441.19 760.27 1.000000 4n +450.46 760.27 1.000000 dot +441.19 748.27 1.000000 4n +450.46 748.27 1.000000 dot +0.70 setlinewidth +437.51 759.52 moveto +437.51 727.27 lineto stroke +487.32 754.27 1.000000 4n +496.59 754.27 1.000000 dot +487.32 748.27 1.000000 4n +496.59 748.27 1.000000 dot +483.64 753.52 moveto +483.64 727.27 lineto stroke +532.95 760.27 1.000000 4n +542.21 760.27 1.000000 dot +532.95 748.27 1.000000 4n +542.21 748.27 1.000000 dot +529.27 759.52 moveto +529.27 727.27 lineto stroke +441.94 766.54 moveto +441.94 766.69 lineto +483.09 771.38 524.38 773.21 565.79 772.21 curveto +607.20 771.20 648.34 767.37 689.22 760.69 curveto +689.19 760.39 lineto +648.25 766.27 607.10 769.71 565.75 770.71 curveto +524.40 771.71 483.13 770.27 441.95 766.39 curveto +fill +restore +% S_STAFF +% staff 3 +save +441.19 699.67 0.800000 4n +433.86 699.67 0.800000 sharp +448.61 699.67 0.800000 dot +0.56 setlinewidth +438.25 699.07 moveto +438.25 682.87 lineto stroke +487.32 702.07 0.800000 4n +494.74 704.47 0.800000 dot +482.34 702.07 moveto +492.31 702.07 lineto stroke +484.38 701.47 moveto +484.38 685.27 lineto stroke +532.95 699.67 0.800000 4n +/Times-Roman findfont +10 scalefont +setfont +515.68 697.15 moveto +(\() show +522.58 699.67 0.800000 sharp +/Times-Roman findfont +10 scalefont +setfont +526.18 697.15 moveto +(\)) show +540.36 699.67 0.800000 dot +530.00 699.07 moveto +530.00 682.87 lineto stroke +restore +% S_STAFF +% staff 4 +save +441.19 624.09 1.000000 xnote +450.67 624.09 1.000000 dot +0.70 setlinewidth +445.09 627.09 moveto +445.09 645.09 lineto stroke +487.32 624.09 1.000000 xnote +496.80 624.09 1.000000 dot +491.22 627.09 moveto +491.22 645.09 lineto stroke +532.95 624.09 1.000000 xnote +536.85 627.09 moveto +536.85 643.59 lineto stroke +548.18 624.09 1.000000 xnote +552.07 627.09 moveto +552.07 643.59 lineto stroke +564.28 624.09 1.000000 xnote +568.18 627.09 moveto +568.18 643.59 lineto stroke +newpath +536.50 645.09 moveto +568.53 645.09 lineto +568.53 642.09 lineto +536.50 642.09 lineto +closepath +fill +441.19 618.09 1.000000 4n +450.67 618.09 1.000000 dot +437.51 617.34 moveto +437.51 597.09 lineto stroke +487.32 618.09 1.000000 4n +496.80 618.09 1.000000 dot +483.64 617.34 moveto +483.64 597.09 lineto stroke +532.95 618.09 1.000000 4n +542.43 618.09 1.000000 dot +529.27 617.34 moveto +529.27 597.09 lineto stroke +restore +% S_STAFF +% staff 5 +save +532.95 530.07 1.000000 4n +0.70 setlinewidth +526.72 530.07 moveto +539.18 530.07 lineto stroke +529.27 529.32 moveto +529.27 508.67 lineto stroke +548.18 536.07 1.000000 4n +544.49 535.32 moveto +544.49 514.67 lineto stroke +564.28 542.07 1.000000 4n +560.60 541.32 moveto +560.60 521.02 lineto stroke +newpath +444.53 477.21 moveto +560.95 522.52 lineto +560.95 519.52 lineto +444.53 474.21 lineto +closepath +fill +restore +% S_STAFF +% staff 6 +save +441.19 451.83 1.000000 4n +0.70 setlinewidth +434.96 451.83 moveto +447.43 451.83 lineto stroke +434.96 457.83 moveto +447.43 457.83 lineto stroke +444.88 452.58 moveto +444.88 475.71 lineto stroke +456.81 457.83 1.000000 4n +450.58 457.83 moveto +463.04 457.83 lineto stroke +460.49 458.58 moveto +460.49 481.86 lineto stroke +471.69 463.83 1.000000 4n +475.37 464.58 moveto +475.37 487.72 lineto stroke +487.32 472.83 1.000000 4n +491.01 473.58 moveto +491.01 493.88 lineto stroke +502.57 478.83 1.000000 4n +506.25 479.58 moveto +506.25 499.88 lineto stroke +517.88 484.83 1.000000 4n +521.56 485.58 moveto +521.56 505.92 lineto stroke +restore +% S_STAFF +% staff 7 +save +441.19 406.55 1.000000 2n +450.67 406.55 1.000000 dot +441.19 400.55 1.000000 2n +450.67 400.55 1.000000 dot +441.19 394.55 1.000000 2n +450.67 394.55 1.000000 dot +441.19 385.55 1.000000 2n +450.67 388.55 1.000000 dot +441.19 373.55 1.000000 2n +450.67 376.55 1.000000 dot +0.70 setlinewidth +434.75 373.55 moveto +447.64 373.55 lineto stroke +445.09 374.30 moveto +445.09 427.55 lineto stroke +532.95 406.55 1.000000 4n +542.21 406.55 1.000000 dot +532.95 400.55 1.000000 4n +542.21 400.55 1.000000 dot +532.95 394.55 1.000000 4n +542.21 394.55 1.000000 dot +532.95 385.55 1.000000 4n +542.21 388.55 1.000000 dot +532.95 373.55 1.000000 4n +542.21 376.55 1.000000 dot +526.72 373.55 moveto +539.18 373.55 lineto stroke +536.63 374.30 moveto +536.63 427.55 lineto stroke +534.95 368.45 moveto +534.97 368.60 lineto +543.73 366.33 552.62 365.19 561.67 365.19 curveto +570.71 365.19 579.61 366.33 588.37 368.60 curveto +588.41 368.30 lineto +579.76 365.23 570.85 363.69 561.67 363.69 curveto +552.49 363.69 543.58 365.23 534.93 368.30 curveto +fill +547.21 385.55 moveto +547.24 385.73 lineto +553.16 384.21 559.17 383.45 565.28 383.45 curveto +571.40 383.45 577.41 384.21 583.33 385.73 curveto +583.38 385.37 lineto +577.53 383.27 571.50 382.22 565.28 382.22 curveto +559.07 382.22 553.04 383.27 547.19 385.37 curveto +fill +547.21 394.55 moveto +547.24 394.73 lineto +553.16 393.21 559.17 392.45 565.28 392.45 curveto +571.40 392.45 577.41 393.21 583.33 394.73 curveto +583.38 394.37 lineto +577.53 392.27 571.50 391.22 565.28 391.22 curveto +559.07 391.22 553.04 392.27 547.19 394.37 curveto +fill +547.21 400.55 moveto +547.24 400.73 lineto +553.16 399.21 559.17 398.45 565.28 398.45 curveto +571.40 398.45 577.41 399.21 583.33 400.73 curveto +583.38 400.37 lineto +577.53 398.27 571.50 397.22 565.28 397.22 curveto +559.07 397.22 553.04 398.27 547.19 400.37 curveto +fill +547.21 411.65 moveto +547.19 411.81 lineto +554.17 414.33 561.38 415.58 568.80 415.58 curveto +576.22 415.58 583.43 414.33 590.41 411.81 curveto +590.36 411.49 lineto +583.29 413.29 576.10 414.19 568.80 414.19 curveto +561.50 414.19 554.31 413.29 547.24 411.49 curveto +fill +restore +% S_STAFF +% staff 8 +save +437.85 307.87 444.54 318.81 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +437.85 309.09 moveto +(3) show +437.85 297.67 444.54 308.19 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +437.85 298.68 moveto +(4) show +437.85 287.05 444.54 297.99 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +437.85 288.27 moveto +(5) show +437.85 276.64 444.54 287.58 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +437.85 277.86 moveto +(5) show +437.85 266.23 444.54 277.17 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +437.85 267.45 moveto +(3) show +529.60 307.87 536.30 318.81 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +529.60 309.09 moveto +(3) show +529.60 297.67 536.30 308.19 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +529.60 298.68 moveto +(4) show +529.60 287.05 536.30 297.99 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +529.60 288.27 moveto +(5) show +529.60 276.64 536.30 287.58 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +529.60 277.86 moveto +(5) show +529.60 266.23 536.30 277.17 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +529.60 267.45 moveto +(3) show +restore +% S_STAFF +% staff 9 +save +441.19 201.29 1.000000 filldiamond +0.70 setlinewidth +445.09 201.29 moveto +445.09 219.99 lineto stroke +456.81 195.29 1.000000 fillisostriangle +460.71 192.89 moveto +460.71 216.90 lineto stroke +471.69 195.29 1.000000 fillisostriangle +475.59 192.89 moveto +475.59 213.95 lineto stroke +487.32 207.29 1.000000 fillslashhead +498.89 210.29 1.000000 dot +481.34 201.89 moveto +481.34 186.29 lineto stroke +532.95 207.29 1.000000 fillslashhead +544.52 210.29 1.000000 dot +526.96 201.89 moveto +526.96 186.29 lineto stroke +newpath +444.74 221.49 moveto +475.94 215.45 lineto +475.94 212.45 lineto +444.74 218.49 lineto +closepath +fill +restore +% S_BAR +454 linenum +0.70 setlinewidth +581.34 846.43 moveto +581.34 822.43 lineto stroke +581.34 763.27 moveto +581.34 739.27 lineto stroke +581.34 697.27 moveto +581.34 678.07 lineto stroke +581.34 627.09 moveto +581.34 615.09 lineto stroke +581.34 560.07 moveto +581.34 463.83 lineto stroke +581.34 403.55 moveto +581.34 261.29 lineto stroke +581.34 219.29 moveto +581.34 195.29 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +459 linenum +/Helvetica-Oblique findfont +14 scalefont +setfont +585.52 787.40 moveto +(am) show +/Helvetica-Oblique findfont +14 scalefont +setfont +670.61 787.40 moveto +(-) show +/Helvetica-Oblique findfont +14 scalefont +setfont +626.45 787.40 moveto +(gr) show +/Ext-Helvetica-Oblique findfont +14 scalefont +setfont +(lF) show +/Helvetica-Oblique findfont +14 scalefont +setfont +(t) show +/Helvetica-Oblique findfont +14 scalefont +setfont +685.09 787.40 moveto +(en,) show +590.39 822.43 1.000000 4n +599.65 825.43 1.000000 dot +590.39 816.43 1.000000 4n +599.65 819.43 1.000000 dot +584.16 816.43 moveto +596.62 816.43 lineto stroke +594.07 817.18 moveto +594.07 843.43 lineto stroke +635.77 828.43 1.000000 4n +645.04 831.43 1.000000 dot +635.77 822.43 1.000000 4n +645.04 825.43 1.000000 dot +639.46 823.18 moveto +639.46 849.43 lineto stroke +689.96 828.43 1.000000 4n +699.22 831.43 1.000000 dot +689.96 822.43 1.000000 4n +699.22 825.43 1.000000 dot +693.64 823.18 moveto +693.64 849.43 lineto stroke +/Palatino-Italic findfont +14 scalefont +setfont +newpath +583.35 858.43 moveto +583.35 891.02 lineto +693.94 891.02 lineto +693.94 858.43 lineto +closepath +stroke +585.35 879.09 moveto +(A special note, on) show +585.35 862.71 moveto +(two lines, in a box.) show +restore +% S_STAFF +% staff 2 +save +590.39 760.27 1.000000 4n +599.65 760.27 1.000000 dot +590.39 748.27 1.000000 4n +599.65 748.27 1.000000 dot +0.70 setlinewidth +586.71 759.52 moveto +586.71 727.27 lineto stroke +635.77 754.27 1.000000 4n +645.04 754.27 1.000000 dot +635.77 748.27 1.000000 4n +645.04 748.27 1.000000 dot +632.09 753.52 moveto +632.09 727.27 lineto stroke +689.96 754.27 1.000000 4n +699.22 754.27 1.000000 dot +689.96 748.27 1.000000 4n +699.22 748.27 1.000000 dot +686.28 753.52 moveto +686.28 727.27 lineto stroke +restore +% S_STAFF +% staff 3 +save +659.85 687.67 0.800000 measrpt +/Times-Roman findfont +9 scalefont +setfont +657.61 699.67 moveto +(2) show +restore +% S_STAFF +% staff 4 +save +590.39 624.09 1.000000 xnote +599.87 624.09 1.000000 dot +0.70 setlinewidth +594.29 627.09 moveto +594.29 645.09 lineto stroke +635.77 624.09 1.000000 xnote +645.25 624.09 1.000000 dot +639.67 627.09 moveto +639.67 645.09 lineto stroke +689.96 624.09 1.000000 xnote +693.86 627.09 moveto +693.86 643.59 lineto stroke +705.19 624.09 1.000000 xnote +709.08 627.09 moveto +709.08 643.59 lineto stroke +721.29 624.09 1.000000 xnote +725.19 627.09 moveto +725.19 643.59 lineto stroke +newpath +693.51 645.09 moveto +725.54 645.09 lineto +725.54 642.09 lineto +693.51 642.09 lineto +closepath +fill +590.39 618.09 1.000000 2n +599.87 618.09 1.000000 dot +586.49 617.34 moveto +586.49 597.09 lineto stroke +689.96 618.09 1.000000 4n +699.44 618.09 1.000000 dot +686.28 617.34 moveto +686.28 597.09 lineto stroke +/Palatino-Italic findfont +14 scalefont +setfont +gsave +newpath +1.941964 1.000000 scale +308.62 656.08 9.99 0 360 arc +0.514943 1.000000 scale +2.018418 1.000000 scale +296.93 656.08 9.49 0 360 arc +eofill +grestore +584.93 651.62 moveto +(mute) show +restore +% S_STAFF +% staff 5 +save +restore +% S_STAFF +% staff 6 +save +590.39 551.07 1.000000 4n +590.39 536.07 1.000000 4n +0.70 setlinewidth +586.71 550.32 moveto +586.71 477.33 lineto stroke +606.18 542.07 1.000000 4n +606.18 493.83 1.000000 4n +599.95 493.83 moveto +612.41 493.83 lineto stroke +602.50 541.32 moveto +602.50 473.49 lineto stroke +621.41 536.07 1.000000 4n +621.41 484.83 1.000000 4n +617.73 535.32 moveto +617.73 469.79 lineto stroke +635.77 493.83 1.000000 4n +629.54 493.83 moveto +642.01 493.83 lineto stroke +635.77 478.83 1.000000 4n +632.09 493.08 moveto +632.09 462.33 lineto stroke +659.57 484.83 1.000000 4n +655.89 484.08 moveto +655.89 462.33 lineto stroke +674.80 478.83 1.000000 4n +671.12 478.08 moveto +671.12 462.33 lineto stroke +689.96 472.83 1.000000 4n +699.22 472.83 1.000000 dot +693.64 473.58 moveto +693.64 493.83 lineto stroke +newpath +586.36 478.83 moveto +618.08 471.29 lineto +618.08 468.29 lineto +586.36 475.83 lineto +closepath +fill +newpath +631.74 463.83 moveto +671.47 463.83 lineto +671.47 460.83 lineto +631.74 460.83 lineto +closepath +fill +restore +% S_STAFF +% staff 7 +save +590.39 406.55 1.000000 4n +599.65 406.55 1.000000 dot +590.39 400.55 1.000000 4n +599.65 400.55 1.000000 dot +590.39 394.55 1.000000 4n +599.65 394.55 1.000000 dot +590.39 385.55 1.000000 4n +599.65 388.55 1.000000 dot +590.39 373.55 1.000000 4n +599.65 376.55 1.000000 dot +0.70 setlinewidth +584.16 373.55 moveto +596.62 373.55 lineto stroke +594.07 374.30 moveto +594.07 427.55 lineto stroke +635.77 406.55 1.000000 2n +645.25 406.55 1.000000 dot +635.77 400.55 1.000000 2n +645.25 400.55 1.000000 dot +635.77 394.55 1.000000 2n +645.25 394.55 1.000000 dot +635.77 385.55 1.000000 2n +645.25 388.55 1.000000 dot +635.77 373.55 1.000000 2n +645.25 376.55 1.000000 dot +629.33 373.55 moveto +642.22 373.55 lineto stroke +639.67 374.30 moveto +639.67 427.55 lineto stroke +restore +% S_STAFF +% staff 8 +save +632.43 307.87 639.12 318.81 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +632.43 309.09 moveto +(3) show +632.43 297.67 639.12 308.19 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +632.43 298.68 moveto +(4) show +632.43 287.05 639.12 297.99 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +632.43 288.27 moveto +(5) show +632.43 276.64 639.12 287.58 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +632.43 277.86 moveto +(5) show +632.43 266.23 639.12 277.17 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +632.43 267.45 moveto +(3) show +restore +% S_STAFF +% staff 9 +save +659.85 207.29 1.000000 measrpt +/Times-Roman findfont +11 scalefont +setfont +657.11 222.29 moveto +(2) show +restore +% S_BAR +476 linenum +0.70 setlinewidth +738.35 846.43 moveto +738.35 822.43 lineto stroke +738.35 763.27 moveto +738.35 739.27 lineto stroke +738.35 697.27 moveto +738.35 678.07 lineto stroke +738.35 627.09 moveto +738.35 615.09 lineto stroke +738.35 560.07 moveto +738.35 463.83 lineto stroke +738.35 403.55 moveto +738.35 261.29 lineto stroke +738.35 219.29 moveto +738.35 195.29 lineto stroke +% S_SSV +% S_SSV +% S_SSV +% S_SSV +% S_FEED +% Printing header/footer +/Times-Roman findfont +12 scalefont +setfont +65.45 944.05 moveto +(Sample Songs) show +/Times-Roman findfont +12 scalefont +setfont +366.29 944.05 moveto +(This is the title) show +/Times-Roman findfont +12 scalefont +setfont +685.13 944.05 moveto +(page 2 of 3) show +/Times-Roman findfont +12 scalefont +setfont +65.45 78.33 moveto +(This is a sample remark at the bottom of the page) show +showpage +restore +%%Page: 3 3 +save +41125291 41125529 sv +0.770000 0.770000 scale +/Times-Roman findfont +12 scalefont +setfont +364.28 930.22 moveto +(First movement) show +168.05 901.55 1170.70 5 1.000000 1.000000 stf +/Helvetica-Oblique findfont +9 scalefont +setfont +100.55 855.55 moveto +(8) show +168.05 815.56 1170.70 5 1.000000 1.000000 stf +168.05 745.63 1170.70 1 1.000000 1.000000 stf +168.05 638.83 1170.70 5 1.000000 1.000000 stf +/Helvetica-Oblique findfont +9 scalefont +setfont +100.55 592.83 moveto +(8) show +168.05 570.53 1170.70 5 1.000000 1.000000 stf +168.05 483.17 1170.70 5 1.000000 1.000000 stf +/Helvetica-Oblique findfont +9 scalefont +setfont +100.55 437.17 moveto +(8) show +168.05 369.28 1170.70 6 1.735000 1.000000 stf +168.05 289.25 1170.70 5 1.000000 1.000000 stf +/Times-Roman findfont +12 scalefont +setfont +72.08 782.52 moveto +(Ch) show +/Times-Roman findfont +12 scalefont +setfont +65.45 528.65 moveto +(Kbd) show +/Times-Roman findfont +12 scalefont +setfont +70.13 350.19 moveto +(Gtr) show +94.05 844.55 728.56 bracket +95.55 578.83 486.53 brace +94.05 426.17 268.25 bracket +0.70 setlinewidth +96.05 841.55 moveto +96.05 205.25 lineto stroke +338.46 842.55 362.46 204.25 whitebox +359.46 844.55 728.56 bracket +360.96 578.83 486.53 brace +359.46 426.17 268.25 bracket +362.11 841.55 moveto +362.11 205.25 lineto stroke +% S_CLEFSIG +107.84 823.55 1.000000 gclef +108.09 749.56 1.000000 fclef +102.05 666.13 moveto +102.05 681.13 lineto stroke +104.15 666.13 moveto +104.15 681.13 lineto stroke +107.84 560.83 1.000000 gclef +108.09 504.53 1.000000 fclef +107.84 405.17 1.000000 gclef +107.84 211.25 1.000000 gclef +121.88 829.55 1.000000 flat +127.37 838.55 1.000000 flat +132.85 826.55 1.000000 flat +121.88 737.56 1.000000 flat +127.37 746.56 1.000000 flat +132.85 734.56 1.000000 flat +121.88 566.83 1.000000 flat +127.37 575.83 1.000000 flat +132.85 563.83 1.000000 flat +121.88 492.53 1.000000 flat +127.37 501.53 1.000000 flat +132.85 489.53 1.000000 flat +121.88 411.17 1.000000 flat +127.37 420.17 1.000000 flat +132.85 408.17 1.000000 flat +121.88 217.25 1.000000 flat +127.37 226.25 1.000000 flat +132.85 214.25 1.000000 flat +% S_CHHEAD +% S_STAFF +% staff 1 +save +489 linenum +/Helvetica-Oblique findfont +14 scalefont +setfont +176.94 791.60 moveto +(tr) show +/Ext-Helvetica-Oblique findfont +14 scalefont +setfont +(\\) show +/Helvetica-Oblique findfont +14 scalefont +setfont +(s) show +/Helvetica-Oblique findfont +14 scalefont +setfont +223.12 791.60 moveto +(bien!) show +182.75 829.55 1.000000 4n +174.30 829.55 1.000000 nat +192.02 832.55 1.000000 dot +182.75 811.55 1.000000 4n +173.29 811.55 1.000000 dblsharp +192.02 814.55 1.000000 dot +176.52 811.55 moveto +188.98 811.55 lineto stroke +186.43 812.30 moveto +186.43 850.55 lineto stroke +230.72 829.55 1.000000 2n +240.20 832.55 1.000000 dot +230.72 811.55 1.000000 2n +240.20 814.55 1.000000 dot +224.27 811.55 moveto +237.17 811.55 lineto stroke +234.62 812.30 moveto +234.62 850.55 lineto stroke +/Palatino-Italic findfont +15 scalefont +setfont +266.44 854.60 moveto +(D.C. al Coda ) show +/Times-Roman findfont +14 scalefont +setfont +175.47 887.81 moveto +(G) show +185.55 894.53 moveto +/Times-Roman findfont +9 scalefont +setfont +(9) show +185.55 885.67 moveto +(7) show +170.75 879.95 4.80 6 0 0 0 0 [ 3 -1 0 0 0 5 ] grid +restore +% S_STAFF +% staff 2 +save +182.75 749.56 1.000000 4n +192.02 752.56 1.000000 dot +182.75 731.56 1.000000 4n +192.02 734.56 1.000000 dot +0.70 setlinewidth +186.43 732.31 moveto +186.43 770.56 lineto stroke +230.72 749.56 1.000000 2n +240.20 752.56 1.000000 dot +230.72 731.56 1.000000 2n +240.20 734.56 1.000000 dot +234.62 732.31 moveto +234.62 770.56 lineto stroke +restore +% S_STAFF +% staff 3 +save +restore +% S_STAFF +% staff 4 +save +182.75 691.63 1.000000 4rest +191.05 694.63 1.000000 dot +230.72 676.63 1.000000 4n +239.98 676.63 1.000000 dot +0.70 setlinewidth +234.40 677.38 moveto +234.40 697.63 lineto stroke +283.91 676.63 1.000000 4n +293.17 676.63 1.000000 dot +287.59 677.38 moveto +287.59 697.63 lineto stroke +182.75 670.63 1.000000 4n +192.02 670.63 1.000000 dot +179.07 669.88 moveto +179.07 649.63 lineto stroke +230.72 655.63 1.000000 4rest +239.02 658.63 1.000000 dot +283.91 655.63 1.000000 4rest +292.21 658.63 1.000000 dot +restore +% S_STAFF +% staff 5 +save +182.75 566.83 1.000000 4n +174.30 566.83 1.000000 nat +199.38 569.83 1.000000 dot +190.12 560.83 1.000000 4n +199.38 563.83 1.000000 dot +182.75 557.83 1.000000 4n +199.38 557.83 1.000000 dot +182.75 551.83 1.000000 4n +199.38 551.83 1.000000 dot +0.70 setlinewidth +186.43 552.58 moveto +186.43 587.83 lineto stroke +230.72 566.83 1.000000 4n +247.35 569.83 1.000000 dot +238.08 560.83 1.000000 4n +247.35 563.83 1.000000 dot +230.72 557.83 1.000000 4n +247.35 557.83 1.000000 dot +230.72 551.83 1.000000 4n +247.35 551.83 1.000000 dot +234.40 552.58 moveto +234.40 587.83 lineto stroke +283.91 563.83 1.000000 4n +275.45 563.83 1.000000 nat +293.17 563.83 1.000000 dot +283.91 557.83 1.000000 4n +293.17 557.83 1.000000 dot +283.91 551.83 1.000000 4n +293.17 551.83 1.000000 dot +287.59 552.58 moveto +287.59 584.83 lineto stroke +restore +% S_STAFF +% staff 6 +save +182.75 498.53 1.000000 4n +192.02 501.53 1.000000 dot +0.70 setlinewidth +186.43 499.28 moveto +186.43 519.53 lineto stroke +230.72 495.53 1.000000 4n +239.98 495.53 1.000000 dot +234.40 496.28 moveto +234.40 516.53 lineto stroke +271.53 492.53 0.750000 gclef +283.91 504.53 1.000000 4n +293.17 507.53 1.000000 dot +280.22 503.78 moveto +280.22 483.53 lineto stroke +restore +% S_STAFF +% staff 7 +save +156.58 426.17 0.583333 4n +/Times-Roman findfont +7 scalefont +setfont +150.92 424.40 moveto +(\() show +/Times-Roman findfont +7 scalefont +setfont +159.93 424.40 moveto +(\)) show +156.58 405.17 0.583333 4n +/Times-Roman findfont +7 scalefont +setfont +150.92 403.40 moveto +(\() show +/Times-Roman findfont +7 scalefont +setfont +159.93 403.40 moveto +(\)) show +182.75 429.17 1.000000 4n +174.30 429.17 1.000000 nat +192.02 432.17 1.000000 dot +0.70 setlinewidth +176.52 429.17 moveto +188.98 429.17 lineto stroke +182.75 408.17 1.000000 4n +174.30 408.17 1.000000 nat +192.02 408.17 1.000000 dot +179.07 428.42 moveto +179.07 387.17 lineto stroke +230.72 426.17 1.000000 4n +239.98 426.17 1.000000 dot +230.72 405.17 1.000000 4n +239.98 408.17 1.000000 dot +227.04 425.42 moveto +227.04 384.17 lineto stroke +272.99 420.17 0.583333 4n +267.65 420.17 0.583333 nat +275.00 420.66 moveto +275.00 435.17 lineto stroke +276.76 432.05 0.583333 dnflag +276.76 435.17 0.583333 dnflag +283.91 423.17 1.000000 4n +293.17 426.17 1.000000 dot +280.22 422.42 moveto +280.22 402.17 lineto stroke +298.17 423.17 moveto +307.17 426.17 lineto stroke +182.75 403.07 moveto +202.63 393.49 lineto stroke +202.63 393.49 moveto +223.69 400.07 lineto stroke +184.75 434.27 moveto +207.29 440.85 lineto stroke +207.29 440.85 moveto +228.72 431.27 lineto stroke +158.58 401.57 moveto +165.07 399.50 lineto stroke +165.07 399.50 moveto +170.88 403.07 lineto stroke +157.58 433.37 moveto +168.96 439.08 lineto stroke +168.96 439.08 moveto +180.75 434.27 lineto stroke +restore +% S_STAFF +% staff 8 +save +179.40 307.42 186.10 318.37 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +179.40 308.57 moveto +(8) show +/Helvetica findfont +12 scalefont +setfont +175.08 352.94 moveto +(full) show +176.06 276.19 189.45 287.14 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +176.06 277.34 moveto +(10) show +/Helvetica findfont +12 scalefont +setfont +175.08 342.07 moveto +(full) show +0.70 setlinewidth +182.75 319.37 moveto +182.75 338.92 lineto stroke +182.75 335.50 1.000000 uwedge +227.37 307.42 234.07 318.37 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +227.37 308.57 moveto +(8) show +224.02 276.19 237.41 287.14 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +224.02 277.34 moveto +(10) show +182.75 338.92 moveto +185.15 339.08 187.55 339.08 189.95 338.92 curveto +198.81 338.35 207.66 337.58 216.33 335.49 curveto +217.99 335.09 219.65 334.70 221.13 333.78 curveto +225.01 331.34 228.84 328.84 230.72 324.36 curveto +231.08 323.50 231.08 322.64 230.72 321.79 curveto +stroke +230.72 319.37 1.000000 wedge +272.54 319.20 277.56 327.41 whitebox +/Helvetica-Bold findfont +9 scalefont +setfont +272.54 320.06 moveto +(0) show +280.56 318.05 287.25 328.56 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +280.56 319.06 moveto +(1) show +289.25 323.30 moveto +298.25 326.30 lineto stroke +restore +% S_STAFF +% staff 9 +save +503 linenum +0.70 setlinewidth +196.56 186.28 moveto +335.46 186.28 lineto stroke +/Helvetica-Oblique findfont +11 scalefont +setfont +178.15 186.28 moveto +(oo) show +182.75 211.25 1.000000 diamond +192.23 214.25 1.000000 dot +186.65 211.25 moveto +186.65 232.25 lineto stroke +283.91 211.25 1.000000 filldiamond +293.39 214.25 1.000000 dot +287.80 211.25 moveto +287.80 232.25 lineto stroke +184.75 206.15 moveto +184.77 206.30 lineto +200.65 201.85 216.84 199.62 233.33 199.62 curveto +249.82 199.62 266.01 201.85 281.88 206.30 curveto +281.93 206.01 lineto +266.16 200.75 249.96 198.12 233.33 198.12 curveto +216.70 198.12 200.50 200.75 184.73 206.01 curveto +fill +restore +% S_BAR +505 linenum +0.70 setlinewidth +335.11 841.55 moveto +335.11 817.55 lineto stroke +338.11 841.55 moveto +338.11 817.55 lineto stroke +335.11 755.56 moveto +335.11 731.56 lineto stroke +338.11 755.56 moveto +338.11 731.56 lineto stroke +335.11 679.63 moveto +335.11 667.63 lineto stroke +338.11 679.63 moveto +338.11 667.63 lineto stroke +335.11 578.83 moveto +335.11 486.53 lineto stroke +338.11 578.83 moveto +338.11 486.53 lineto stroke +335.11 423.17 moveto +335.11 271.25 lineto stroke +338.11 423.17 moveto +338.11 271.25 lineto stroke +335.11 229.25 moveto +335.11 205.25 lineto stroke +338.11 229.25 moveto +338.11 205.25 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +restore +% S_STAFF +% staff 2 +save +restore +% S_STAFF +% staff 3 +save +restore +% S_STAFF +% staff 4 +save +restore +% S_STAFF +% staff 5 +save +restore +% S_STAFF +% staff 6 +save +restore +% S_STAFF +% staff 7 +save +restore +% S_STAFF +% staff 8 +save +restore +% S_STAFF +% staff 9 +save +restore +% S_BAR +513 linenum +0.70 setlinewidth +% S_SSV +516 linenum +% S_CLEFSIG +374.25 823.55 1.000000 gclef +374.50 749.56 1.000000 fclef +374.25 560.83 1.000000 gclef +374.50 504.53 1.000000 fclef +374.25 405.17 1.000000 gclef +374.25 211.25 1.000000 gclef +388.29 829.55 1.000000 flat +393.78 838.55 1.000000 flat +399.26 826.55 1.000000 flat +388.29 737.56 1.000000 flat +393.78 746.56 1.000000 flat +399.26 734.56 1.000000 flat +388.29 566.83 1.000000 flat +393.78 575.83 1.000000 flat +399.26 563.83 1.000000 flat +388.29 492.53 1.000000 flat +393.78 501.53 1.000000 flat +399.26 489.53 1.000000 flat +388.29 411.17 1.000000 flat +393.78 420.17 1.000000 flat +399.26 408.17 1.000000 flat +388.29 217.25 1.000000 flat +393.78 226.25 1.000000 flat +399.26 214.25 1.000000 flat +% S_CHHEAD +% S_STAFF +% staff 1 +save +434.45 823.55 1.000000 2n +443.93 826.55 1.000000 dot +434.45 814.55 1.000000 2n +425.45 814.55 1.000000 flat +443.93 814.55 1.000000 dot +438.34 815.30 moveto +438.34 844.55 lineto stroke +510.12 829.55 1.000000 4n +501.67 829.55 1.000000 nat +510.12 823.55 1.000000 4n +513.80 824.30 moveto +513.80 850.55 lineto stroke +543.54 829.55 1.000000 4n +543.54 823.55 1.000000 4n +547.23 824.30 moveto +547.23 850.55 lineto stroke +/NewCenturySchlbk-BoldItalic findfont +11 scalefont +setfont +523.67 852.84 moveto +(2) show +506.09 856.84 moveto +521.67 856.84 lineto stroke +532.00 856.84 moveto +547.58 856.84 lineto stroke +506.09 856.84 moveto +506.09 853.84 lineto stroke +547.58 856.84 moveto +547.58 853.84 lineto stroke +/Times-Roman findfont +14 scalefont +setfont +505.08 891.01 moveto +(G) show +498.12 883.15 4.80 5 0 0 0 0 [ 3 -1 0 0 0 3 ] grid +/Times-Roman findfont +14 scalefont +setfont +421.80 883.01 moveto +(G) show +436.00 883.18 1.166667 dim +440.12 883.01 moveto +(7) show +422.45 875.15 4.80 5 0 0 0 0 [ 0 1 2 0 2 0 ] grid +/Palatino-Italic findfont +15 scalefont +setfont +429.45 899.74 moveto +(Coda ) show +/Palatino-Roman findfont +13 scalefont +setfont +382.66 866.84 moveto +392.45 866.84 1.083333 coda +402.24 866.84 moveto +restore +% S_STAFF +% staff 2 +save +434.45 758.56 1.000000 2n +425.45 758.56 1.000000 flat +443.93 758.56 1.000000 dot +434.45 749.56 1.000000 2n +422.47 749.56 1.000000 flat +443.93 752.56 1.000000 dot +0.70 setlinewidth +430.55 757.81 moveto +430.55 728.56 lineto stroke +510.12 752.56 1.000000 4n +510.12 743.56 1.000000 4n +501.67 743.56 1.000000 nat +/Times-Roman findfont +12 scalefont +setfont +494.29 740.53 moveto +(\() show +/Times-Roman findfont +12 scalefont +setfont +515.15 740.53 moveto +(\)) show +510.12 722.56 1.000000 4n +501.67 722.56 1.000000 nat +503.89 725.56 moveto +516.35 725.56 lineto stroke +513.80 723.31 moveto +513.80 773.56 lineto stroke +543.54 758.56 1.000000 4n +535.09 758.56 1.000000 nat +543.54 743.56 1.000000 4n +539.86 757.81 moveto +539.86 722.56 lineto stroke +/NewCenturySchlbk-BoldItalic findfont +11 scalefont +setfont +523.67 709.92 moveto +(2) show +506.09 712.28 moveto +521.67 713.58 lineto stroke +532.00 714.26 moveto +547.58 715.56 lineto stroke +506.09 712.28 moveto +506.09 715.28 lineto stroke +547.58 715.56 moveto +547.58 718.56 lineto stroke +restore +% S_STAFF +% staff 3 +save +restore +% S_STAFF +% staff 4 +save +restore +% S_STAFF +% staff 5 +save +434.45 620.83 1.000000 2n +425.45 620.83 1.000000 flat +443.93 623.83 1.000000 dot +0.70 setlinewidth +428.00 620.83 moveto +440.89 620.83 lineto stroke +428.00 614.83 moveto +440.89 614.83 lineto stroke +428.00 608.83 moveto +440.89 608.83 lineto stroke +428.00 602.83 moveto +440.89 602.83 lineto stroke +428.00 596.83 moveto +440.89 596.83 lineto stroke +428.00 590.83 moveto +440.89 590.83 lineto stroke +428.00 584.83 moveto +440.89 584.83 lineto stroke +434.45 614.83 1.000000 2n +417.97 614.83 1.000000 flat +443.93 617.83 1.000000 dot +428.00 614.83 moveto +440.89 614.83 lineto stroke +428.00 608.83 moveto +440.89 608.83 lineto stroke +428.00 602.83 moveto +440.89 602.83 lineto stroke +428.00 596.83 moveto +440.89 596.83 lineto stroke +428.00 590.83 moveto +440.89 590.83 lineto stroke +428.00 584.83 moveto +440.89 584.83 lineto stroke +434.45 608.83 1.000000 2n +443.93 611.83 1.000000 dot +428.00 608.83 moveto +440.89 608.83 lineto stroke +428.00 602.83 moveto +440.89 602.83 lineto stroke +428.00 596.83 moveto +440.89 596.83 lineto stroke +428.00 590.83 moveto +440.89 590.83 lineto stroke +428.00 584.83 moveto +440.89 584.83 lineto stroke +434.45 602.83 1.000000 2n +443.93 605.83 1.000000 dot +428.00 602.83 moveto +440.89 602.83 lineto stroke +428.00 596.83 moveto +440.89 596.83 lineto stroke +428.00 590.83 moveto +440.89 590.83 lineto stroke +428.00 584.83 moveto +440.89 584.83 lineto stroke +438.34 603.58 moveto +438.34 635.83 lineto stroke +510.12 623.83 1.000000 4n +519.39 623.83 1.000000 dot +503.89 620.83 moveto +516.35 620.83 lineto stroke +503.89 614.83 moveto +516.35 614.83 lineto stroke +503.89 608.83 moveto +516.35 608.83 lineto stroke +503.89 602.83 moveto +516.35 602.83 lineto stroke +503.89 596.83 moveto +516.35 596.83 lineto stroke +503.89 590.83 moveto +516.35 590.83 lineto stroke +503.89 584.83 moveto +516.35 584.83 lineto stroke +510.12 614.83 1.000000 4n +519.39 617.83 1.000000 dot +503.89 614.83 moveto +516.35 614.83 lineto stroke +503.89 608.83 moveto +516.35 608.83 lineto stroke +503.89 602.83 moveto +516.35 602.83 lineto stroke +503.89 596.83 moveto +516.35 596.83 lineto stroke +503.89 590.83 moveto +516.35 590.83 lineto stroke +503.89 584.83 moveto +516.35 584.83 lineto stroke +510.12 608.83 1.000000 4n +501.67 608.83 1.000000 nat +519.39 611.83 1.000000 dot +503.89 608.83 moveto +516.35 608.83 lineto stroke +503.89 602.83 moveto +516.35 602.83 lineto stroke +503.89 596.83 moveto +516.35 596.83 lineto stroke +503.89 590.83 moveto +516.35 590.83 lineto stroke +503.89 584.83 moveto +516.35 584.83 lineto stroke +510.12 602.83 1.000000 4n +519.39 605.83 1.000000 dot +503.89 602.83 moveto +516.35 602.83 lineto stroke +503.89 596.83 moveto +516.35 596.83 lineto stroke +503.89 590.83 moveto +516.35 590.83 lineto stroke +503.89 584.83 moveto +516.35 584.83 lineto stroke +513.80 603.58 moveto +513.80 638.83 lineto stroke +434.45 581.83 1.000000 2n +443.93 581.83 1.000000 dot +434.45 560.83 1.000000 2n +443.93 557.83 1.000000 dot +430.55 581.08 moveto +430.55 539.83 lineto stroke +510.12 581.83 1.000000 4n +519.39 581.83 1.000000 dot +510.12 560.83 1.000000 4n +519.39 557.83 1.000000 dot +506.44 581.08 moveto +506.44 539.83 lineto stroke +1.00 setlinewidth +[0.1 5] 0 setdash +1 setlinecap +1 setlinejoin +434.45 555.73 moveto +445.63 552.30 457.07 550.59 468.77 550.59 curveto +480.47 550.59 491.91 552.30 503.09 555.73 curveto +stroke +448.93 581.83 moveto +457.75 579.13 466.78 577.77 476.01 577.77 curveto +485.24 577.77 494.27 579.13 503.09 581.83 curveto +stroke +1.00 setlinewidth +[3 3] 0 setdash +448.93 602.83 moveto +457.75 605.54 466.78 606.90 476.01 606.90 curveto +485.24 606.90 494.27 605.54 503.09 602.83 curveto +stroke +448.93 608.83 moveto +456.64 611.20 464.52 612.38 472.59 612.38 curveto +480.65 612.38 488.54 611.20 496.25 608.83 curveto +stroke +448.93 614.83 moveto +457.75 617.54 466.78 618.90 476.01 618.90 curveto +485.24 618.90 494.27 617.54 503.09 614.83 curveto +stroke +448.93 625.93 moveto +458.75 629.48 468.87 631.51 479.30 632.02 curveto +489.73 632.53 500.00 631.50 510.12 628.93 curveto +stroke +restore +% S_STAFF +% staff 6 +save +restore +% S_STAFF +% staff 7 +save +442.24 420.17 1.000000 2n +425.78 420.17 1.000000 nat +451.72 420.17 1.000000 dot +434.45 417.17 1.000000 2n +418.61 417.17 1.000000 flat +451.72 414.17 1.000000 dot +434.45 405.17 1.000000 2n +451.72 408.17 1.000000 dot +434.45 399.17 1.000000 2n +425.78 399.17 1.000000 nat +451.72 402.17 1.000000 dot +434.45 390.17 1.000000 2n +451.72 390.17 1.000000 dot +0.70 setlinewidth +[] 0 setdash +0 setlinecap +0 setlinejoin +428.00 393.17 moveto +440.89 393.17 lineto stroke +434.45 378.17 1.000000 2n +425.78 378.17 1.000000 nat +451.72 378.17 1.000000 dot +428.00 381.17 moveto +440.89 381.17 lineto stroke +428.00 387.17 moveto +440.89 387.17 lineto stroke +428.00 393.17 moveto +440.89 393.17 lineto stroke +438.34 378.92 moveto +438.34 441.17 lineto stroke +newpath +433.34 432.47 moveto +433.34 435.47 lineto +443.34 439.87 lineto +443.34 436.87 lineto +closepath +fill +510.12 426.17 1.000000 4n +519.39 426.17 1.000000 dot +510.12 411.17 1.000000 4n +501.67 411.17 1.000000 nat +519.39 414.17 1.000000 dot +510.12 405.17 1.000000 4n +519.39 408.17 1.000000 dot +510.12 396.17 1.000000 4n +519.39 396.17 1.000000 dot +510.12 384.17 1.000000 4n +519.39 384.17 1.000000 dot +503.89 387.17 moveto +516.35 387.17 lineto stroke +503.89 393.17 moveto +516.35 393.17 lineto stroke +513.80 384.92 moveto +513.80 447.17 lineto stroke +restore +% S_STAFF +% staff 8 +save +431.10 317.83 437.79 328.78 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +431.10 318.98 moveto +(0) show +431.10 307.53 437.79 318.26 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +431.10 308.47 moveto +(2) show +431.10 297.01 437.79 307.96 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +431.10 298.16 moveto +(0) show +431.10 286.71 437.79 297.44 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +431.10 287.65 moveto +(2) show +431.10 276.41 437.79 286.92 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +431.10 277.42 moveto +(1) show +431.10 265.78 437.79 276.73 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +431.10 266.93 moveto +(0) show +newpath +429.45 251.55 moveto +429.45 254.55 lineto +439.45 258.95 lineto +439.45 255.95 lineto +closepath +fill +506.77 317.83 513.47 328.78 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +506.77 319.06 moveto +(3) show +506.77 307.42 513.47 318.37 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +506.77 308.57 moveto +(0) show +506.77 297.01 513.47 307.96 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +506.77 298.16 moveto +(0) show +506.77 286.60 513.47 297.55 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +506.77 287.75 moveto +(0) show +506.77 265.78 513.47 276.73 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +506.77 267.01 moveto +(3) show +restore +% S_STAFF +% staff 9 +save +548 linenum +/Helvetica-Oblique findfont +11 scalefont +setfont +431.86 186.28 moveto +(At) show +/Helvetica-Oblique findfont +11 scalefont +setfont +506.29 186.28 moveto +(the) show +434.45 211.25 1.000000 diamond +443.93 214.25 1.000000 dot +0.70 setlinewidth +438.34 211.25 moveto +438.34 232.25 lineto stroke +510.12 217.25 1.000000 4n +501.67 217.25 1.000000 nat +519.39 220.25 1.000000 dot +506.44 216.50 moveto +506.44 196.25 lineto stroke +restore +% S_BAR +551 linenum +0.70 setlinewidth +573.54 841.55 moveto +573.54 817.55 lineto stroke +573.54 755.56 moveto +573.54 731.56 lineto stroke +573.54 679.63 moveto +573.54 667.63 lineto stroke +573.54 578.83 moveto +573.54 486.53 lineto stroke +573.54 423.17 moveto +573.54 271.25 lineto stroke +573.54 229.25 moveto +573.54 205.25 lineto stroke +% S_SSV +555 linenum +% S_CLEFSIG +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 829.55 moveto +(2) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 817.53 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +586.25 825.67 moveto +(+) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 829.55 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 817.34 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 743.56 moveto +(2) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 731.54 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +586.25 739.68 moveto +(+) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 743.56 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 731.35 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 673.63 moveto +(2) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 661.61 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +586.25 669.75 moveto +(+) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 673.63 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 661.42 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 566.83 moveto +(2) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 554.82 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +586.25 562.96 moveto +(+) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 566.83 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 554.63 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 498.53 moveto +(2) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 486.52 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +586.25 494.66 moveto +(+) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 498.53 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 486.33 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 411.17 moveto +(2) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 399.15 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +586.25 407.29 moveto +(+) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 411.17 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 398.96 moveto +(8) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 217.25 moveto +(2) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +577.04 205.24 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +586.25 213.38 moveto +(+) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 217.25 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +595.95 205.05 moveto +(8) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +623.87 832.55 1.000000 2n +623.87 823.55 1.000000 2n +623.87 817.55 1.000000 2n +627.77 818.30 moveto +627.77 853.55 lineto stroke +684.61 832.55 1.000000 4n +693.87 832.55 1.000000 dot +684.61 823.55 1.000000 4n +693.87 826.55 1.000000 dot +684.61 817.55 1.000000 4n +693.87 820.55 1.000000 dot +688.29 818.30 moveto +688.29 853.55 lineto stroke +625.87 812.45 moveto +625.89 812.60 lineto +635.19 810.16 644.64 808.94 654.24 808.94 curveto +663.85 808.94 673.30 810.16 682.59 812.60 curveto +682.63 812.30 lineto +673.45 809.06 663.98 807.44 654.24 807.44 curveto +644.50 807.44 635.04 809.06 625.85 812.30 curveto +fill +630.12 823.55 moveto +630.14 823.70 lineto +637.92 821.72 645.82 820.74 653.85 820.74 curveto +661.87 820.74 669.78 821.72 677.56 823.70 curveto +677.60 823.40 lineto +669.93 820.63 662.01 819.24 653.85 819.24 curveto +645.69 819.24 637.77 820.63 630.10 823.40 curveto +fill +630.12 837.65 moveto +630.10 837.80 lineto +638.92 840.92 648.01 842.48 657.37 842.48 curveto +666.72 842.48 675.81 840.92 684.63 837.80 curveto +684.59 837.50 lineto +675.66 839.82 666.59 840.98 657.37 840.98 curveto +648.14 840.98 639.07 839.82 630.14 837.50 curveto +fill +/Palatino-Roman findfont +14 scalefont +setfont +674.07 855.72 moveto +684.61 855.72 1.166667 ferm +695.15 855.72 moveto +/Times-Roman findfont +14 scalefont +setfont +613.75 884.01 moveto +(Cm) show +611.87 876.15 4.80 5 3 1 2 6 [ -2 1 3 3 2 1 ] grid +restore +% S_STAFF +% staff 2 +save +623.87 761.56 1.000000 2n +0.70 setlinewidth +617.42 761.56 moveto +630.32 761.56 lineto stroke +623.87 752.56 1.000000 2n +623.87 746.56 1.000000 2n +619.97 760.81 moveto +619.97 725.56 lineto stroke +684.61 761.56 1.000000 4n +693.87 764.56 1.000000 dot +678.38 761.56 moveto +690.84 761.56 lineto stroke +684.61 752.56 1.000000 4n +693.87 752.56 1.000000 dot +684.61 746.56 1.000000 4n +693.87 746.56 1.000000 dot +680.93 760.81 moveto +680.93 725.56 lineto stroke +623.87 741.46 moveto +623.89 741.61 lineto +632.69 739.32 641.64 738.18 650.73 738.18 curveto +659.81 738.18 668.76 739.32 677.56 741.61 curveto +677.60 741.31 lineto +668.91 738.22 659.95 736.68 650.73 736.68 curveto +641.50 736.68 632.54 738.22 623.85 741.31 curveto +fill +630.12 752.56 moveto +630.10 752.71 lineto +637.77 755.48 645.69 756.87 653.85 756.87 curveto +662.01 756.87 669.93 755.48 677.60 752.71 curveto +677.56 752.41 lineto +669.78 754.38 661.87 755.37 653.85 755.37 curveto +645.82 755.37 637.92 754.38 630.14 752.41 curveto +fill +625.87 766.66 moveto +625.85 766.81 lineto +635.04 770.04 644.50 771.66 654.24 771.66 curveto +663.98 771.66 673.45 770.04 682.63 766.81 curveto +682.59 766.51 lineto +673.30 768.95 663.85 770.16 654.24 770.16 curveto +644.64 770.16 635.19 768.95 625.89 766.51 curveto +fill +/Palatino-Roman findfont +14 scalefont +setfont +674.07 773.06 moveto +684.61 773.06 1.166667 ferm +695.15 773.06 moveto +restore +% S_STAFF +% staff 3 +save +restore +% S_STAFF +% staff 4 +save +668.85 679.63 1.000000 1rest +668.85 661.63 1.000000 1rest +/Palatino-Roman findfont +14 scalefont +setfont +658.30 687.86 moveto +668.85 687.86 1.166667 ferm +679.39 687.86 moveto +restore +% S_STAFF +% staff 5 +save +623.87 548.83 1.000000 2n +0.70 setlinewidth +617.42 548.83 moveto +630.32 548.83 lineto stroke +627.77 549.58 moveto +627.77 569.83 lineto stroke +684.61 548.83 1.000000 4n +693.87 551.83 1.000000 dot +678.38 548.83 moveto +690.84 548.83 lineto stroke +688.29 549.58 moveto +688.29 569.83 lineto stroke +625.87 543.73 moveto +625.89 543.88 lineto +635.19 541.45 644.64 540.23 654.24 540.23 curveto +663.85 540.23 673.30 541.45 682.59 543.88 curveto +682.63 543.59 lineto +673.45 540.35 663.98 538.73 654.24 538.73 curveto +644.50 538.73 635.04 540.35 625.85 543.59 curveto +fill +/Palatino-Roman findfont +14 scalefont +setfont +674.07 581.01 moveto +684.61 581.01 1.166667 ferm +695.15 581.01 moveto +restore +% S_STAFF +% staff 6 +save +623.87 495.53 1.000000 2n +0.70 setlinewidth +627.77 496.28 moveto +627.77 516.53 lineto stroke +684.61 495.53 1.000000 4n +693.87 495.53 1.000000 dot +688.29 496.28 moveto +688.29 516.53 lineto stroke +625.87 490.43 moveto +625.89 490.58 lineto +635.19 488.15 644.64 486.93 654.24 486.93 curveto +663.85 486.93 673.30 488.15 682.59 490.58 curveto +682.63 490.29 lineto +673.45 487.05 663.98 485.43 654.24 485.43 curveto +644.50 485.43 635.04 487.05 625.85 490.29 curveto +fill +/Palatino-Roman findfont +14 scalefont +setfont +674.07 518.71 moveto +684.61 518.71 1.166667 ferm +695.15 518.71 moveto +1.00 setlinewidth +[3 3] 0 setdash +644.16 479.18 moveto +726.21 479.18 lineto stroke +726.21 479.18 moveto +726.21 488.18 lineto stroke +0.70 setlinewidth +[] 0 setdash +0 setlinecap +0 setlinejoin +/Palatino-Italic findfont +12 scalefont +setfont +620.88 474.68 moveto +(8va) show +restore +% S_STAFF +% staff 7 +save +623.87 456.17 1.000000 2n +0.70 setlinewidth +617.42 453.17 moveto +630.32 453.17 lineto stroke +617.42 447.17 moveto +630.32 447.17 lineto stroke +617.42 441.17 moveto +630.32 441.17 lineto stroke +617.42 435.17 moveto +630.32 435.17 lineto stroke +617.42 429.17 moveto +630.32 429.17 lineto stroke +619.97 455.42 moveto +619.97 411.17 lineto stroke +684.61 456.17 1.000000 4n +693.87 456.17 1.000000 dot +678.38 453.17 moveto +690.84 453.17 lineto stroke +678.38 447.17 moveto +690.84 447.17 lineto stroke +678.38 441.17 moveto +690.84 441.17 lineto stroke +678.38 435.17 moveto +690.84 435.17 lineto stroke +678.38 429.17 moveto +690.84 429.17 lineto stroke +680.93 455.42 moveto +680.93 411.17 lineto stroke +625.87 461.27 moveto +625.85 461.42 lineto +635.04 464.65 644.50 466.27 654.24 466.27 curveto +663.98 466.27 673.45 464.65 682.63 461.42 curveto +682.59 461.12 lineto +673.30 463.56 663.85 464.77 654.24 464.77 curveto +644.64 464.77 635.19 463.56 625.89 461.12 curveto +fill +restore +% S_STAFF +% staff 8 +save +617.18 317.83 630.57 328.78 whitebox +/Helvetica-Bold findfont +12 scalefont +setfont +617.18 318.98 moveto +(20) show +restore +% S_STAFF +% staff 9 +save +573 linenum +/Helvetica-Oblique findfont +11 scalefont +setfont +618.51 186.28 moveto +(end.) show +623.87 220.25 1.000000 rectangle +0.70 setlinewidth +619.97 220.25 moveto +619.97 199.25 lineto stroke +684.61 220.25 1.000000 fillrectangle +694.09 220.25 1.000000 dot +680.71 220.25 moveto +680.71 199.25 lineto stroke +625.87 225.35 moveto +625.85 225.50 lineto +635.04 228.74 644.50 230.36 654.24 230.36 curveto +663.98 230.36 673.45 228.74 682.63 225.50 curveto +682.59 225.21 lineto +673.30 227.64 663.85 228.86 654.24 228.86 curveto +644.64 228.86 635.19 227.64 625.89 225.21 curveto +fill +restore +% S_BAR +576 linenum +0.70 setlinewidth +733.20 841.55 moveto +733.20 817.55 lineto stroke +3.00 setlinewidth +737.20 841.55 moveto +737.20 817.55 lineto stroke +0.70 setlinewidth +733.20 755.56 moveto +733.20 731.56 lineto stroke +3.00 setlinewidth +737.20 755.56 moveto +737.20 731.56 lineto stroke +0.70 setlinewidth +733.20 679.63 moveto +733.20 667.63 lineto stroke +3.00 setlinewidth +737.20 679.63 moveto +737.20 667.63 lineto stroke +0.70 setlinewidth +733.20 578.83 moveto +733.20 486.53 lineto stroke +3.00 setlinewidth +737.20 578.83 moveto +737.20 486.53 lineto stroke +0.70 setlinewidth +733.20 423.17 moveto +733.20 271.25 lineto stroke +3.00 setlinewidth +737.20 423.17 moveto +737.20 271.25 lineto stroke +0.70 setlinewidth +733.20 229.25 moveto +733.20 205.25 lineto stroke +3.00 setlinewidth +737.20 229.25 moveto +737.20 205.25 lineto stroke +0.70 setlinewidth +% S_SSV +% S_SSV +% S_SSV +% S_SSV +% Printing header/footer +/Times-Roman findfont +12 scalefont +setfont +65.45 944.05 moveto +(Sample Songs) show +/Times-Roman findfont +12 scalefont +setfont +366.29 944.05 moveto +(This is the title) show +/Times-Roman findfont +12 scalefont +setfont +685.13 944.05 moveto +(page 3 of 3) show +/Times-Roman findfont +12 scalefont +setfont +65.45 78.33 moveto +(This is a sample remark at the bottom of the page) show +showpage +restore +%%Trailer +%%DocumentFonts: /Times-Roman /Times-BoldItalic /Helvetica /Helvetica-Oblique /Helvetica-Bold /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic /Palatino-Roman /Palatino-Italic /Palatino-Bold /Ext-Helvetica-Oblique +%%Pages: 3 diff --git a/mup/docs/star.mup b/mup/docs/star.mup new file mode 100644 index 0000000..fa3e11c --- /dev/null +++ b/mup/docs/star.mup @@ -0,0 +1,211 @@ +//!Mup-Arkkra + +// sample of a Mup input file + +header + title (18) "The Star Spangled Banner" + title ital (12) "(The United States National Anthem)" + title (9) "Text: Francis Scott Key" "Tune: J. S. Smith" + title (9) "" "arr: William J. Krauss" + +score + topmargin = 0.5 + bottommargin = 0.5 + leftmargin = 0.6 + rightmargin = 0.6 + scale = 0.7 + packfact = 1.2 + key = 3# + time = 3/4 + staffs = 2 + brace = 1-2 + barstyle = 1-2 + measnum = y + vscheme = 2o + beamstyle = 4,4,4 + endingstyle = top + +staff 2 + clef = bass + +define LYRICS lyrics between 1&2: @ + +music + // Starts on a pickup, so use space + // at beginning of measure. + // Voices are in unison for the first + // few notes, so specify two voices + // at once. + 1 1-2: 2s; 8.e<>; 16c; + 2 1-2: 2s; 8.e<>; 16c; + LYRICS 2s; 4; [1] "Oh_"; + // Since the first two sections are + // almost the same, use a repeat + repeatstart + + 1 1: a-; c; e; + 1 2: a-; c; b-; + 2 1: a-; a; b; + 2 2: a-; a; g; + LYRICS [1] "say. can you"; \ + [2] "stripes and bright"; + bar + + 1 1: 2a; 8.c+; 16b; + 1 2: 2c; 8.; 16; + 2 1: 2a; 8.g; 16; + 2 2: 2f; 8.e#; 16; + LYRICS [1] "see, by the"; \ + [2] "stars, through the"; + bar + + 1 1: a; c; d#; + 1 2: c; ; b-; + 2 1: a; ; ; + 2 2: f; ; b-; + LYRICS [1] "dawn's ear-ly"; \ + [2] "per-il-ous"; + bar + + 1 1: e; r; 8e; ; + 1 2: b-; r; 8b-; ; + 2 1: g; r; 8g; ; + 2 2: e; r; 8e; ; + LYRICS [1] "light what so"; \ + [2] "fight, o'er the"; + bar + + 1 1: 4.c+; 8b; 4a; + 1 2: 4.e; 8; 4; + 2 1: 4.a; 8g; 4a; + 2 2: 4.a-; 8b-; 4c; + LYRICS [1] "proud-ly we"; \ + [2] "ram-parts we"; + bar + + 1 1: 2g; 8.f; 16g; + 1 2: 2e; 8.; 16; + 2 1: 2b; 8.; 16; + 2 2: 2e; 8.d; 16; + LYRICS [1] "hailed, At the"; \ + [2] "watched, were so"; + bar + + 1 1: a; ; e; + 1 2: e; ; ; + 2 1: a; ; e; + 2 2: c; ; e; + LYRICS [1] "twi-light's last"; \ + [2] "gal-lant-ly"; + bar ending "1." + + 1-2 1-2: c; 8a-; r; 8.e; 16c; + LYRICS [1] "gleam-ing, whose broad"; + repeatend ending "2." + + 1 1: c; 8a-; r; 8.c+; 16; + 1 2: c; 8a-; r; 8.e; 16; + 2 1: c; 8a-; r; 8.a; 16; + 2 2: c; 8a-; r; 8.a-; 16; + LYRICS [2] "stream-ing? And the"; + bar endending + + 1 1: c+; d+; e+; + 1 2: e; ; ; + 2 1: a; b; c+; + 2 2: a-; ; ; + // continue to mark as verse 2 from now on, + // so that the lyrics will line up properly + // with the lyrics of the second ending. + LYRICS [2] "rock-ets' red"; + bar + +// Define a mapping, and use the chord-at-a-time input method for the +// next several measures. Specify the voices in bottom to top order. +define M [ 2 2; 2 1; 1 2; 1 1 ] @ + + M: a-c+ee+; rrrr; 8a-bed+; a-aec+; + LYRICS [2] "glare, the bombs"; + bar + + M: egeb; egec+; eged+; + LYRICS [2] "burst-ing in"; + bar + + M: eged+; rrrr; eged+; + LYRICS [2] "air, gave"; + bar + + M: 4.a-aec+; 8b-geb; 4caea; + LYRICS [2] "proof through the"; + bar + + M: 2ebeg; 8.ebdf; 16ebdg; + LYRICS [2] "night that our"; + bar + + M: faca; facc; b-ab-d#; + LYRICS [2] "flag was still"; + bar + + M: egb-e; rrrr; egb-e; + LYRICS [2] "there. Oh"; + bar + + 1 1: 4a; ; 8<>; g; + 1 2: 4c; b-; 4a-; + 2 1: e; ; ; + 2 2: a-; b-; c; + LYRICS [2] "say, does that"; + bar + + 1 1: f; ; ; + 1 2: d; ; e; + 2 1: a; ; a#; + 2 2: d; ; c; + LYRICS [2] "star-span-gled"; + bar + + 1 1: 4b; 8d+<>; c+; b<>; a; + 1 2: 4d; 4f; ; + 2 1: b; 8<>; a#; b<>; b#; + 2 2: b-; 8<>; c; d<>; d#; + LYRICS [2] "ban-ner yet"; + bar + + mussym(12) 1-2: 2 "ferm"; + 1 1: a<>; 8g; r; e; ; + 1 2: 4.e; 8r; e; ; + 2 1: c+<>; 8b; r; g; ; + 2 2: 4.e; 8r; d; ; + LYRICS [2] "wave_ o'er the"; + bar + + 1 1: 4.a<>; 8b; c+; d+; + 1 2: 4.e<>; 8; ; ; + 2 1: 4.a<>; 8g; a; ; + 2 2: 4.c<>; 8e; a-; b-; + LYRICS [2] "land_ of the"; + bar + + mussym(12) 1-2: 1 "ferm"; + 1 1: e+; r; 8a; b; + 1 2: e; r; 8d; ; + 2 1: a; r; 8a; ; + 2 2: c; r; 8f; fn; + LYRICS [2] "free and the"; + bar + + 1 1: 4.c+; 8d+; 4b; + 1 2: 4.e; 8; 4d; + 2 1: 4.a; 8; 4g; + 2 2: 4.e; 8; 4; + LYRICS [2] "home of the"; + bar + + 1 1: 2a; 4s; + 1 2: 2c; 4s; + 2 1: 2e; 4s; + 2 2: 2a-; 4s; + LYRICS [2] "brave?"; + endbar diff --git a/mup/docs/star.ps b/mup/docs/star.ps new file mode 100644 index 0000000..b53038d --- /dev/null +++ b/mup/docs/star.ps @@ -0,0 +1,4854 @@ +%!PS-Adobe-1.0 +%%Creator: Mup +%%Title: music: from /home/johnkr/mup/5.3/doc/arkkra/star.mup +%%CreationDate: Sat Dec 9 16:59:22 2006 +%%Pages: (atend) +%%DocumentFonts: (atend) +%%BoundingBox: 0 0 612 792 +%%EndComments +% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises +% All rights reserved + +% Mup PostScript Prolog 5.3 for use with Mup 5.3 + +% lwid is used as the width of a standard (thin) line in the music +% character definitions. +/lwid 70 def +/halflwid lwid 2 div def + +% Define the following for use in do_upshortnote, do_dnshortnote, and +% do_shortrest; it has to be done outside of the music font definition. +/utildict 10 dict def +utildict begin + /setnumflags { /numflags exch def } def + /sethooksm1 { /hooksm1 exch def } def + /setoffsets { /offsets exch def } def + /setx { /x exch def } def + /sety { /y exch def } def +end + +% Define a music character font. Each music character is defined as if it +% were a normal ASCII character in a strange font where "A" looks like a +% treble clef, "B" looks like a bass clef, etc. + +/mfont0 100 dict def +mfont0 begin + /FontType 3 def + /FontMatrix [ .001 0 0 0.001 0 0 ] def + /FontBBox [ -2000 -4030 2000 4030 ] def + /FontName (Mfont0) def + + % set up Encoding vector with standard names + /Encoding 256 array def + StandardEncoding Encoding copy + pop + + % the following definitions are used for quarter rests + /topx -170 def /topy 950 def + /cor1x 250 def /cor1y 450 def + /cor2x -300 def /cor2y 200 def + /cor3x 250 def /cor3y -400 def + + % the following definitions are used for double sharps + /limit 300 halflwid add def + /off 70 def + /inbendsmall limit 200 sub def + /inbendbig limit 20 sub def + /outbendsmall 100 def + /outbendbig outbendsmall off add def + + %%%%% define routines that will be used by multiple characters %%%%% + /do_1n { + gsave + newpath -10 rotate 1.6 1 scale + 0 0 325 0 360 arc %outer ellipse + 1 1.6 div 1 scale 10 rotate %back to original + 35 rotate 0.85 1.1 scale + 0 0 275 0 360 arc %inner ellipse + eofill + grestore + } def + /do_upflag { + -315 0 moveto + -300 100 -100 480 0 600 curveto + 300 960 350 1500 200 1700 curveto + 130 1700 lineto + 350 1200 50 650 -315 600 curveto + fill + } def + /do_flat { + -250 -400 moveto %outer edge of loop + 500 0 350 650 -250 160 curveto + -250 160 lwid sub lineto %inner edge of loop + 100 400 300 0 -250 -400 lwid add curveto + fill + + lwid setlinewidth %stem + -250 1100 moveto -250 -400 lineto stroke + } def + /do_diamond { + newpath + 420 0 moveto 0 300 lineto -420 0 lineto + 0 -300 lineto closepath + 259 -29 moveto -41 185 lineto -259 29 lineto + 41 -185 lineto closepath + eofill + } def + /do_2n { + gsave + newpath 25 rotate 1.4 1 scale + 0 0 315 0 360 arc %outer ellipse + 1 1.4 div 1 scale %back to original + 1.3 0.5 scale + 0 0 310 0 360 arc %inner ellipse + eofill + grestore + } def + /do_4n { + gsave + newpath 25 rotate 1.35 1 scale + 0 0 310 0 360 arc fill + grestore + } def + /do_com { + newpath + 330 250 150 0 360 arc fill %knob at upper right + 465 300 moveto %outer boundary + 410 500 200 635 0 635 curveto + -750 635 -750 -635 0 -635 curveto + 350 -635 480 -300 500 -100 curveto + 430 -100 lineto %inner boundary + 380 -300 250 -565 0 -565 curveto + -450 -565 -450 565 0 565 curveto + 200 565 370 350 395 300 curveto + fill + } def + /do_ferm { + 0 0 800 lwid sub 0 180 arc %inner arc + -800 0 lineto + 0 270 lwid sub 800 180 0 arcn %outer arc + 800 0 lineto fill + 0 120 120 0 360 arc fill %the dot + } def + /do_mor { + gsave + 0.7 1 scale %scrunch the following horizontally + 45 rotate %to pretend all lines horz or vertical + 0 1 1 { + pop %we don't need the loop variable + %one half of the mordent + 0 40 moveto 350 40 lineto 350 -460 lineto + 750 -460 lineto 750 -540 lineto + 150 -540 lineto 150 -40 lineto + 0 -40 lineto fill + 180 rotate %to do the other half + } for + grestore + } def + /do_turn { + gsave + 0 1 1 { + pop %we don't need the loop variable + 0 -100 moveto %outer boundary + 200 -400 625 -400 625 0 curveto + 625 200 500 325 300 325 curveto + 300 185 lineto %inner boundary + 450 255 555 150 555 0 curveto + 555 -350 250 -250 0 100 curveto + fill + 300 255 70 0 360 arc fill %knob on end + 180 rotate %to do the other half + } for + grestore + } def + + /do_upshortnote { + utildict begin + setnumflags %set numflags from the stack + gsave + -330 0 translate %half a flag width + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto + 370 2100 numflags 2 sub flagsep mul add lineto stroke + 670 2100 numflags 2 sub flagsep mul add translate + 1 -1 scale %reflect across X axis + 0 1 numflags 1 sub { + do_upflag %do an upflag + pop %we don't need the loop variable + 0 flagsep translate + } for + grestore + end + } def + + /do_dnshortnote { + utildict begin + setnumflags %set numflags from the stack + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto + -370 -2100 numflags 2 sub flagsep mul sub lineto stroke + gsave + -70 -2100 numflags 2 sub flagsep mul sub translate + 0 1 numflags 1 sub { + do_upflag %do an upflag + pop %we don't need the loop variable + 0 flagsep translate + } for + grestore + end + } def + + /do_shortrest { + utildict begin + sety setx setoffsets sethooksm1 %set variable from the stack + gsave + -105.8 offsets mul -600 offsets mul translate + 0 1 hooksm1 { %loop once per hook + newpath + 1 setlinewidth + gsave + 1 1.2 scale + -150 300 1.2 div 140 0 360 arc fill %the dot + grestore + lwid setlinewidth + -50 700 550 255 315 arc %rest of the hook + hooksm1 lt { stroke 105.8 600 translate } if + } for + x y lineto stroke + grestore + end + } def + + + % subsidiary dictionary of character definitions + /CharStrings 128 dict def + CharStrings begin + + /.notdef {} def + + % Here are the definitions of the characters. A stepsize here + % is 300 units (assuming the character is drawn at its default + % size). + + % gclef + /A { + newpath + %start with inner curl, inside boundary + -50 -300 moveto + -450 600 700 700 750 0 curveto + 750 -800 -700 -800 -700 200 curveto + -700 900 500 1400 520 2250 curveto + 520 2900 300 3000 200 3000 curveto + 100 3000 -400 2500 -200 1800 curveto + 350 -600 lineto + 720 -1600 0 -1650 -400 -1400 curveto + + %go back to start, drawing the other boundary + -400 -1480 lineto + 0 -1700 800 -1700 430 -600 curveto + -120 1800 lineto + -300 2400 200 2800 250 2800 curveto + 400 2800 430 2700 430 2450 curveto + 430 1800 -900 1200 -900 300 curveto + -750 -900 800 -900 850 0 curveto + 900 1100 -750 900 -120 -300 curveto fill + + %circle at the bottom + -300 -1250 250 0 360 arc fill + } def + + % fclef + /B { + newpath + %start with outside boundary, at bottom + -1000 -1700 moveto + 100 -1100 500 -600 450 0 curveto + 450 850 -1100 850 -950 0 curveto + + %go back to start, drawing the other boundary + -880 0 lineto + -920 400 -600 560 -300 560 curveto + 0 560 150 400 150 0 curveto + 150 -400 100 -900 -1000 -1620 curveto fill + + %circle at the left + newpath + -700 0 250 0 360 arc fill + + %do the two dots after the main curve + 700 -300 100 0 360 arc fill + 700 300 100 0 360 arc fill + } def + + % cclef + /C { + gsave + %do upper curved part, then scale to do mirror image + 0 1 1 { + pop %we don't need the loop variable + %outer boundary of curve + -170 0 moveto 100 300 lineto + 400 -200 750 300 750 650 curveto + 750 1100 450 1235 250 1235 curveto + 0 1235 -143 1100 -143 950 curveto + + %inner boundary of curve + 0 950 lineto + 0 1100 30 1165 250 1165 curveto + 300 1165 450 1100 450 650 curveto + 450 400 400 -100 100 400 curveto + -270 0 lineto fill + %stroke + %-270 0 moveto 100 400 lineto + %400 -100 450 400 450 650 curveto + %450 1100 300 1165 250 1165 curveto + %30 1165 0 1100 0 950 curveto + %stroke + + %elliptical ball at end of curve + gsave + 1.3 1 scale + 10 950 120 0 360 arc fill + grestore + 1 -1 scale %reflect across X axis + } for + grestore + + % two vertical lines on the left + 300 setlinewidth -600 -1200 halflwid sub moveto + -600 1200 halflwid add lineto stroke + lwid setlinewidth -300 -1200 halflwid sub moveto + -300 1200 halflwid add lineto stroke + } def + + % dblwhole + /D { + do_1n %do a whole note + lwid setlinewidth + -490 -600 moveto -490 600 lineto stroke + 490 -600 moveto 490 600 lineto stroke + } def + + % 1n + /E { + do_1n %do a whole note + } def + + % 2n + /F { + do_2n %do a half note + } def + + % 4n + /G { + do_4n %do a quarter note head + } def + + % upflag + /H { + do_upflag %do an upflag + } def + + % dnflag + /I { + gsave + 1 -1 scale %reflect across X axis + do_upflag %do an upflag + grestore + } def + + % dwhrest + /J { + 300 setlinewidth + 0 0 moveto 0 600 lineto stroke + } def + + % 1rest + /K { + lwid setlinewidth + -750 600 moveto 750 600 lineto stroke + 300 setlinewidth + -400 450 moveto 400 450 lineto stroke + } def + + % 2rest + /L { + lwid setlinewidth + -750 0 moveto 750 0 lineto stroke + 300 setlinewidth + -400 150 moveto 400 150 lineto stroke + } def + + % 4rest + /M { + newpath + cor3x cor3y halflwid add moveto + %-400 -200 -450 -650 50 -950 lwid add curveto + -450 -50 -450 -650 50 -950 lwid add curveto + -150 -650 -100 -250 cor3x cor3y halflwid sub curveto + fill + + cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto + cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto + fill + + lwid setlinewidth + topx topy moveto cor1x cor1y lineto stroke + cor2x cor2y moveto cor3x cor3y lineto stroke + } def + + % 8rest + /N { + 0 0 0 -600 do_shortrest + } def + + % 16rest + /O { + 1 1 100 -1200 do_shortrest + } def + + % 32rest + /P { + 2 1 0 -1800 do_shortrest + } def + + % 64rest + /Q { + 3 2 -80 -2100 do_shortrest + } def + + % 128rest + /R { + 4 2 -150 -2700 do_shortrest + } def + + % 256rest + /S { + 5 3 -280 -3300 do_shortrest + } def + + % dot + /T { + newpath + 0 0 120 0 360 arc fill + } def + + % nat + /U { + % fill crossbars so that we can do parallelograms + -235 -470 moveto -235 -270 lineto + 235 -130 lineto 235 -330 lineto fill + -235 130 moveto -235 330 lineto + 235 470 lineto 235 270 lineto fill + + % vertical strokes + lwid setlinewidth + -200 -380 moveto -200 850 lineto stroke + 200 -850 moveto 200 380 lineto stroke + } def + + % sharp + /V { + % fill crossbars so that we can do parallelograms + -325 -480 moveto -325 -280 lineto + 325 -120 lineto 325 -320 lineto fill + -325 120 moveto -325 320 lineto + 325 480 lineto 325 280 lineto fill + + % vertical strokes + lwid setlinewidth + -150 -930 moveto -150 880 lineto stroke + 150 -880 moveto 150 930 lineto stroke + } def + + % flat + /W { + do_flat %do a flat + } def + + % dblsharp + /X { + gsave + 0 1 3 { %loop once for each of 4 sticks + pop %we don't need the loop variable + 0 off neg moveto + outbendbig outbendsmall lineto + inbendbig inbendsmall lineto + limit limit lineto + inbendsmall inbendbig lineto + outbendsmall outbendbig lineto + off neg 0 lineto + fill + -90 rotate + } for + grestore + } def + + % dblflat + /Y { + -290 580 290 { %loop once for each flat + + gsave + 1 setlinewidth + 0 translate %translate left/right (loop var) + do_flat %do a flat + grestore + + } for + } def + + % xnote + /Z { + gsave + 1.15 1 scale 120 setlinewidth 1 setlinecap %round + -300 -300 moveto 300 300 lineto stroke + -300 300 moveto 300 -300 lineto stroke + grestore + } def + + % dwhdiamond + /a { + do_diamond %do a diamond + lwid setlinewidth + -420 -600 moveto -420 600 lineto stroke + 420 -600 moveto 420 600 lineto stroke + } def + + % diamond + /b { + do_diamond %do a diamond + } def + + % filldiamond + /c { + 420 0 moveto 0 300 lineto + -420 0 lineto 0 -300 lineto fill + } def + + % up2n + /d { + lwid setlinewidth + 380 0 moveto 380 2100 lineto stroke + do_2n %do a half note + } def + + % dn2n + /e { + lwid setlinewidth + -380 0 moveto -380 -2100 lineto stroke + do_2n %do a half note + } def + + % up4n + /f { + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto 370 2100 lineto stroke + } def + + % dn4n + /g { + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto -370 -2100 lineto stroke + } def + + % up8n + /h { + gsave + -330 0 translate % half a flag width + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto 370 2100 lineto stroke + 670 2100 translate + 1 -1 scale %reflect across X axis + do_upflag %do an upflag + grestore + } def + + % dn8n + /i { + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto -370 -2100 lineto stroke + gsave + -70 -2100 translate + do_upflag %do an upflag + grestore + } def + + % up16n + /j { + 2 do_upshortnote + } def + + % dn16n + /k { + 2 do_dnshortnote + } def + + % up32n + /l { + 3 do_upshortnote + } def + + % dn32n + /m { + 3 do_dnshortnote + } def + + % up64n + /n { + 4 do_upshortnote + } def + + % dn64n + /o { + 4 do_dnshortnote + } def + + % up128n + /p { + 5 do_upshortnote + } def + + % dn128n + /q { + 5 do_dnshortnote + } def + + % up256n + /r { + 6 do_upshortnote + } def + + % dn256n + /s { + 6 do_dnshortnote + } def + + % com + /t { + do_com %do a common time symbol + } def + + % cut + /u { + do_com %do a common time symbol + lwid setlinewidth + 0 -900 moveto 0 900 lineto stroke + } def + + % begped + /v { + lwid setlinewidth + -200 600 moveto -200 0 lineto 200 0 lineto stroke + } def + + % pedal + /w { + lwid setlinewidth + -500 0 moveto -450 0 lineto 0 600 lineto + 450 0 lineto 500 0 lineto stroke + } def + + % endped + /x { + lwid setlinewidth + 200 600 moveto 200 0 lineto -200 0 lineto stroke + } def + + % dnbow + /y { + lwid setlinewidth + -350 0 moveto -350 900 lineto stroke + 350 0 moveto 350 900 lineto stroke + 200 setlinewidth + -350 800 moveto 350 800 lineto stroke + } def + + % upbow + /z { + lwid setlinewidth + -300 900 moveto 0 0 lineto 300 900 lineto stroke + } def + + % wedge + /one { + 0 0 moveto -150 500 lineto 150 500 lineto fill + } def + + % uwedge + /two { + -150 0 moveto 150 0 lineto 0 500 lineto fill + } def + + % ferm + /three { + newpath + do_ferm %do a right side up fermata + } def + + % uferm + /four { + newpath + gsave + 0 270 lwid sub 800 add translate %baseline at bottom + 180 rotate %upside down + do_ferm %do a right side up fermata + grestore + } def + + % sign + /five { + gsave + %do upper left curved part, upper right dot; + %then rotate 180 to do other half + 0 1 1 { + pop %we don't need the loop variable + 0 100 moveto %inner boundary + -1000 300 -400 750 -200 700 curveto + -200 800 lineto %outer boundary + -550 900 -1100 100 0 -100 curveto + fill + %dot at end of curve + -200 700 100 0 360 arc fill + %dot in upper right quadrant + 500 200 70 0 360 arc fill + 180 rotate + } for + grestore + + %slash through middle + lwid setlinewidth + -400 -800 moveto 400 800 lineto stroke + } def + + % coda + /six { + newpath + gsave + 0.6 1 scale + 0 0 550 0 360 arc %outside boundary + 1 0.6 div 1 scale %back to original + 0.9 1 scale + 0 0 650 0 360 arc %inside boundary + eofill + grestore + lwid setlinewidth + 0 -850 moveto 0 850 lineto stroke + -800 0 moveto 800 0 lineto stroke + } def + + % mor + /seven { + do_mor %do a mordent + } def + + % invmor + /eight { + do_mor %do a mordent + lwid setlinewidth + 0 -450 moveto 0 450 lineto stroke + } def + + % turn + /nine { + do_turn %do a turn + } def + + % invturn + /zero { + gsave + 1 -1 scale %reflect across X axis + do_turn %do a turn + grestore + } def + + % acc_gt + /numbersign { + lwid setlinewidth + -500 300 moveto 500 0 lineto -500 -300 lineto stroke + } def + + % acc_hat + /dollar { + newpath + -365 0 moveto 0 860 lineto 365 0 lineto + 150 0 lineto -75 530 lineto -300 0 lineto fill + } def + + % acc_uhat + /quotedbl { + newpath + 365 860 moveto 0 0 lineto -365 860 lineto + -150 860 lineto 75 330 lineto 300 860 lineto fill + } def + + % tr + /asterisk { + %vertical bar of t + -350 1000 moveto -550 200 lineto + -612.5 -50 -212.5 -50 -160 200 curveto + -230 200 lineto + -300 50 -420 50 -400 200 curveto + -200 1000 lineto fill + + %crossbar of t and vertical bar of r + -700 600 moveto -160 600 lineto + 20 600 30 520 60 440 curveto + -50 0 lineto 70 0 lineto 180 440 lineto + 190 480 100 670 -150 670 curveto + -690 670 lineto fill + + %horizontal curve of r + 100 480 moveto + 300 630 450 700 650 550 curveto + 560 480 lineto + 450 630 300 560 100 390 curveto + fill + + %knob at end of r + 600 460 100 0 360 arc fill + } def + + % leg + /comma { + 100 setlinewidth + -400 0 moveto 400 0 lineto stroke + } def + + % rr + /hyphen { + 100 setlinewidth + -400 0 moveto 0 1000 lineto stroke + 0 0 moveto 400 1000 lineto stroke + } def + + % measrpt + /period { + newpath -450 400 150 0 360 arc fill + newpath 450 -400 150 0 360 arc fill + 200 setlinewidth + -550 -600 moveto 550 600 lineto stroke + } def + + % copyright + /slash { + lwid setlinewidth + newpath 0 400 400 0 360 arc stroke + newpath 0 400 200 45 315 arc stroke + } def + + % dim + /quoteleft { + 50 setlinewidth + newpath 0 640 220 0 360 arc stroke + } def + + % halfdim + /quoteright { + 50 setlinewidth + newpath 0 640 220 0 360 arc stroke + newpath -340 300 moveto 340 980 lineto stroke + } def + + % triangle + /asciicircum { + 50 setlinewidth + newpath -340 -10 moveto 0 710 lineto + 340 -10 lineto closepath stroke + } def + + % qwhrest + /ampersand { + 300 setlinewidth + 0 -600 moveto 0 600 lineto stroke + } def + + % ll1rest + /exclam { + 310 setlinewidth + -400 455 moveto 400 450 lineto stroke + } def + + % ll2rest + /at { + 310 setlinewidth + -400 145 moveto 400 150 lineto stroke + } def + end + + /BuildChar { + + exch begin + Encoding exch get + + dup + Mcbbox0 exch get + aload pop setcachedevice + + CharStrings exch get + exec + end + } def +end + + +% Define another music character font, since there are too many to fit in one +% font. It works the same way as the first one. + +/mfont1 100 dict def +mfont1 begin + /FontType 3 def + /FontMatrix [ .001 0 0 0.001 0 0 ] def + /FontBBox [ -2000 -4030 2000 4030 ] def + /FontName (Mfont1) def + + % set up Encoding vector with standard names + /Encoding 256 array def + StandardEncoding Encoding copy + pop + + %%%%% define routines that will be used by multiple characters %%%%% + + /do_dwh_bars { + % the two bars surrounding a double whole note + lwid setlinewidth + -420 -600 moveto -420 600 lineto stroke + 420 -600 moveto 420 600 lineto stroke + } def + /do_righttriangle { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto + 350 150 moveto -140 150 lineto 350 -213 lineto + eofill + } def + /do_fillrighttriangle { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto + fill + } def + /do_rectangle { + newpath + 420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto + 350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto + eofill + } def + /do_isostriangle { + newpath + 0 300 moveto -420 -270 lineto 420 -270 lineto + 0 182 moveto -245 -150 lineto 245 -150 lineto + eofill + } def + /do_piewedge { + newpath + 0 -300 moveto 0 -244 514 35 145 arc + 0 -209 moveto 0 -244 394 43 137 arc + eofill + } def + /do_semicircle { + newpath + gsave + 1 1.357 scale 420 199 moveto 0 199 420 180 360 arc + 1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc + eofill + grestore + } def + /do_slashhead { + newpath + lwid setlinewidth + -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto + closepath stroke + } def + + % subsidiary dictionary of character definitions + /CharStrings 128 dict def + CharStrings begin + + /.notdef {} def + + % Here are the definitions of the characters. A stepsize here + % is 300 units (assuming the character is drawn at its default + % size). + + % dwhrighttriangle + /A { + do_righttriangle + do_dwh_bars + } def + + % righttriangle + /B { + do_righttriangle + } def + + % fillrighttriangle + /C { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto + 420 -300 lineto + fill + } def + + % udwhrighttriangle + /D { + gsave + 180 rotate + do_righttriangle + do_dwh_bars + grestore + } def + + % urighttriangle + /E { + gsave + 180 rotate + do_righttriangle + grestore + } def + + % ufillrighttriangle + /F { + gsave + 180 rotate + do_fillrighttriangle + grestore + } def + + % dwhrectangle + /G { + do_rectangle + do_dwh_bars + } def + + % rectangle + /H { + do_rectangle + } def + + % fillrectangle + /I { + newpath + 420 270 moveto -420 270 lineto -420 -270 lineto + 420 -270 lineto + fill + } def + + % dwhisostriangle + /J { + do_isostriangle + do_dwh_bars + } def + + % isostriangle + /K { + do_isostriangle + } def + + % fillisostriangle + /L { + newpath + 0 300 moveto -420 -270 lineto 420 -270 lineto + fill + } def + + % dwhpiewedge + /M { + do_piewedge + do_dwh_bars + } def + + % piewedge + /N { + do_piewedge + } def + + % fillpiewedge + /O { + newpath + 0 -300 moveto 0 -244 514 35 145 arc + fill + } def + + % dwhsemicircle + /P { + do_semicircle + do_dwh_bars + } def + + % semicircle + /Q { + do_semicircle + } def + + % fillsemicircle + /R { + newpath + gsave + 1 570 420 div scale + 420 199 moveto 0 199 420 180 360 arc + fill + grestore + } def + + % dwhslashhead + /S { + do_slashhead + lwid setlinewidth + -650 -600 moveto -650 600 lineto stroke + 650 -600 moveto 650 600 lineto stroke + } def + + % slashhead + /T { + do_slashhead + } def + + % fillslashhead + /U { + newpath + 200 setlinewidth + -550 -600 moveto 550 600 lineto stroke + } def + + % blankhead + /V { + %print nothing + } def + end + + /BuildChar { + + exch begin + Encoding exch get + + dup + Mcbbox1 exch get + aload pop setcachedevice + + CharStrings exch get + exec + end + } def +end + + +% General routines for printing any music character, invoked by each music +% character's specific routine below. The scaling factor (default 1) needs +% to be multiplied by 10 to get the actual size. These routines restore the +% preexisting current font when they are done. + +/printmchar0 { + gsave + /musicchar exch def + /Mfont0 findfont exch 10 mul scalefont setfont moveto + musicchar show + grestore +} def +/printmchar1 { + gsave + /musicchar exch def + /Mfont1 findfont exch 10 mul scalefont setfont moveto + musicchar show + grestore +} def + +% Define each music character name to be a routine that prints the character. +% Each character is to be invoked as in this example: +% 100 200 1 gclef % at (100, 200), scale to default size & print + +/gclef { (A) printmchar0 } def +/fclef { (B) printmchar0 } def +/cclef { (C) printmchar0 } def +/dblwhole { (D) printmchar0 } def +/1n { (E) printmchar0 } def +/2n { (F) printmchar0 } def +/4n { (G) printmchar0 } def +/upflag { (H) printmchar0 } def +/dnflag { (I) printmchar0 } def +/dwhrest { (J) printmchar0 } def +/1rest { (K) printmchar0 } def +/2rest { (L) printmchar0 } def +/4rest { (M) printmchar0 } def +/8rest { (N) printmchar0 } def +/16rest { (O) printmchar0 } def +/32rest { (P) printmchar0 } def +/64rest { (Q) printmchar0 } def +/128rest { (R) printmchar0 } def +/256rest { (S) printmchar0 } def +/dot { (T) printmchar0 } def +/nat { (U) printmchar0 } def +/sharp { (V) printmchar0 } def +/flat { (W) printmchar0 } def +/dblsharp { (X) printmchar0 } def +/dblflat { (Y) printmchar0 } def +/xnote { (Z) printmchar0 } def +/dwhdiamond { (a) printmchar0 } def +/diamond { (b) printmchar0 } def +/filldiamond { (c) printmchar0 } def +/up2n { (d) printmchar0 } def +/dn2n { (e) printmchar0 } def +/up4n { (f) printmchar0 } def +/dn4n { (g) printmchar0 } def +/up8n { (h) printmchar0 } def +/dn8n { (i) printmchar0 } def +/up16n { (j) printmchar0 } def +/dn16n { (k) printmchar0 } def +/up32n { (l) printmchar0 } def +/dn32n { (m) printmchar0 } def +/up64n { (n) printmchar0 } def +/dn64n { (o) printmchar0 } def +/up128n { (p) printmchar0 } def +/dn128n { (q) printmchar0 } def +/up256n { (r) printmchar0 } def +/dn256n { (s) printmchar0 } def +/com { (t) printmchar0 } def +/cut { (u) printmchar0 } def +/begped { (v) printmchar0 } def +/pedal { (w) printmchar0 } def +/endped { (x) printmchar0 } def +/dnbow { (y) printmchar0 } def +/upbow { (z) printmchar0 } def +/wedge { (1) printmchar0 } def +/uwedge { (2) printmchar0 } def +/ferm { (3) printmchar0 } def +/uferm { (4) printmchar0 } def +/sign { (5) printmchar0 } def +/coda { (6) printmchar0 } def +/mor { (7) printmchar0 } def +/invmor { (8) printmchar0 } def +/turn { (9) printmchar0 } def +/invturn { (0) printmchar0 } def +/acc_gt { (#) printmchar0 } def +/acc_hat { ($) printmchar0 } def +/acc_uhat { (") printmchar0 } def +/tr { (*) printmchar0 } def +/leg { (,) printmchar0 } def +/rr { (-) printmchar0 } def +/measrpt { (.) printmchar0 } def +/copyright { (/) printmchar0 } def +/dim { (`) printmchar0 } def +/halfdim { (') printmchar0 } def +/triangle { (^) printmchar0 } def +/qwhrest { (&) printmchar0 } def +/ll1rest { (!) printmchar0 } def +/ll2rest { (@) printmchar0 } def +/dwhrighttriangle { (A) printmchar1 } def +/righttriangle { (B) printmchar1 } def +/fillrighttriangle { (C) printmchar1 } def +/udwhrighttriangle { (D) printmchar1 } def +/urighttriangle { (E) printmchar1 } def +/ufillrighttriangle { (F) printmchar1 } def +/dwhrectangle { (G) printmchar1 } def +/rectangle { (H) printmchar1 } def +/fillrectangle { (I) printmchar1 } def +/dwhisostriangle { (J) printmchar1 } def +/isostriangle { (K) printmchar1 } def +/fillisostriangle { (L) printmchar1 } def +/dwhpiewedge { (M) printmchar1 } def +/piewedge { (N) printmchar1 } def +/fillpiewedge { (O) printmchar1 } def +/dwhsemicircle { (P) printmchar1 } def +/semicircle { (Q) printmchar1 } def +/fillsemicircle { (R) printmchar1 } def +/dwhslashhead { (S) printmchar1 } def +/slashhead { (T) printmchar1 } def +/fillslashhead { (U) printmchar1 } def +/blankhead { (V) printmchar1 } def + + +% Define routines for Mup output other than music characters. + +/stepsize 3 def % define a step size as 3 points (at default magnification) + +% x1 y1 x2 lines dist staffscale staff +% draw a staff starting at x1, y1 and extending to x2 with "lines" +% lines, 2*dist*stepsize apart, scaled by staffscale +/staff { + /staffscale exch def + /dist exch def + /lines exch def + /x2 exch def + /y1 exch def + /x1 exch def + 0.7 staffscale mul sb setlinewidth + 1 lines sub 2 lines 1 sub { % loop from bottom line to top line + dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto + stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke + } for +} def + +% x y1 y2 bracket draw a bracket; y1 is the top +/bracket { + /y2 exch def + /y1 exch def + /x exch def + gsave + 3 setlinewidth + x 2 sub y1 1 add moveto + x 2 sub y2 1 sub lineto + stroke + x 2 sub y1 1 add moveto + x 1 sub y1 1 add x 3 add y1 1 add x 5 add y1 6 add curveto + x 6 add y1 5 add lineto + x 5 add y1 2 add x 1 add y1 2 sub x 2 sub y1 2 sub curveto + fill + x 2 sub y2 1 sub moveto + x 1 sub y2 1 sub x 3 add y2 1 sub x 5 add y2 6 sub curveto + x 6 add y2 5 sub lineto + x 5 add y2 2 sub x 1 add y2 2 add x 2 sub y2 2 add curveto + fill + grestore +} def + +% x y1 y2 brace draw a brace; y1 is the top +/brace { + /y2 exch def + /y1 exch def + /x exch def + gsave + x 9 sub y1 y2 add 2 div translate + /topy y1 y2 sub 2 div 1 sub def + 0 1 1 { + pop + %0 topy moveto 0 0 lineto stroke + 0 0 moveto + 16 topy 0.2 mul -11 topy 0.6 mul 8 topy curveto + 8.7 topy lineto + -7 topy 0.7 mul 20 topy 0.3 mul 1 0 curveto + fill + 1 -1 scale % flip to do bottom half + } for + grestore +} def + +% endx endy wavy staffscale draw a wavy line from current point to here, +% scaled by staffscale +/wavy { + /staffscale exch def + /endy exch def % define the end point of the line + /endx exch def + currentpoint % line starts at current point + /begy exch def % define the beginning point of the line + /begx exch def + gsave + /dx endx begx sub def % find delta x and delta y + /dy endy begy sub def + /r dx dx mul dy dy mul add sqrt def % hypotenuse + /theta dy dx atan def % angle with positive x axis + begx begy translate % change axes so that we can draw the line + theta rotate % from (0, 0) to (r, 0) + staffscale staffscale scale % scale everything by staffscale + /scaledr r staffscale div def % but scale r in reverse to keep length + + % Each outer loop draws one cycle of the squiggle. It continues until + % we are at or beyond the desired end point. + 0 0 moveto + 0 6 scaledr { + gsave + % first loop draws left half of squiggle; second draws right + 0 1 1 { + 0.0 0.4 moveto + 2.0 1.9 3.4 2.3 3.9 0.0 curveto + 2.1 0.0 lineto + 1.9 0.8 1.4 0.7 0.0 -0.4 curveto + fill + pop 180 rotate -6 0 translate + } for + grestore + + pop 6 0 translate % shift axes right one squiggle + } for + + grestore +} def + +% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid +% print a guitar grid diagram +/grid { + /grid_positions exch def % 0="o", -1="x", -2=nothing, positive=dot + /curver exch def % right string for curve, 0 if none + /curvel exch def % left string for curve, 0 if none + /numvert exch def % vertical position to print fretno, 0 if none + /fretno exch def % fret no. to print at right, 0 if none + /frets exch def % number of fret lines + /space exch def % points between two neighboring lines + /y exch def % y coord of top fret line + /x exch def % x coord of left strings + + gsave + /strings grid_positions length def % number of strings + /lmarky 0.4 space mul y add def % lowest Y of a "o" or "x" + space 10 div setlinewidth + 2 setlinecap + + % draw the lines of the grid + 0 1 strings 1 sub { % loop from left string to right string + dup space mul x add y moveto + space mul x add frets 1 sub space mul y exch sub lineto stroke + } for + 0 -1 1 frets sub { % loop from top fret (nut) to bottom fret + dup space mul y add x exch moveto + space mul y add strings 1 sub space mul x add exch lineto stroke + } for + + % draw the curved line if there is one + curvel 0 gt { + % within strings curvel to curver, find smallest positive fret + /minfret 1000 def + curvel 1 curver { + /strno exch def + /grid_p grid_positions strno 1 sub get def + grid_p 0 gt grid_p minfret lt and { + /minfret grid_p def + } if + } for + + % if curve goes above top fret, other marks must be higher + minfret 1 eq { + /hmarky 1.2 space mul y add def + } { + /hmarky lmarky def + } ifelse + + /strdiff curver curvel sub def + space 8 div setlinewidth + + % set endpoint coords of curve; higher if curve is short + /curvex1 curvel 1 sub space mul x add def + /curvex2 curver 1 sub space mul x add def + /curvey 1 minfret sub space mul y add def + strdiff 3 lt { + /curvey 0.2 strdiff div space mul curvey add def + } if + + % move to left end, set other points, draw curve + curvex1 curvey moveto + + curvex1 curvex2 curvex1 sub 3 div add + curvey space 0.4 strdiff sqrt mul mul add + + curvex2 curvex2 curvex1 sub 3 div sub + curvey space 0.4 strdiff sqrt mul mul add + + curvex2 curvey curveto stroke + } if + + space 10 div setlinewidth + + % draw dots and x and o marks + 0 1 strings 1 sub { % loop from left string to right string + /strno exch def % first string is 0 + /grid_p grid_positions strno get def + /strx strno space mul x add def + + % set Y of mark higher if curved line covers this string + strno 1 add curvel ge strno 1 add curver le and { + /marky hmarky def + } { + /marky lmarky def + } ifelse + + grid_p -1 eq { % draw an X above the string + /xhwid space 3 div def + strx xhwid sub marky xhwid sub moveto + strx xhwid add marky xhwid add lineto stroke + strx xhwid sub marky xhwid add moveto + strx xhwid add marky xhwid sub lineto stroke + } if + grid_p 0 eq { % draw a circle above the string + strx marky space 0.3 mul 0 360 arc stroke + } if + grid_p 1 ge { % draw a dot by the proper fret + strx y grid_p space mul sub space 3 div add + space 3 div 0 360 arc fill + } if + } for + + % print "X fr" if requested + fretno 0 gt { + /Palatino-Roman findfont space 1.9 mul scalefont setfont + x strings 0.5 sub space mul add + y space numvert 0.3 add mul sub moveto + fretno 2 string cvs show ( fr) show + } if + grestore +} def + +% x1 y1 x2 y2 whitebox draw a white rectangle with opposite +% corners of (x1,y1) and (x2,y2) +/whitebox { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + 1.0 setgray + newpath + x1 y1 moveto + x1 y2 lineto + x2 y2 lineto + x2 y1 lineto + closepath + fill + stroke + 0.0 setgray +} def + + +/LineNum 0 def +/InputFile (unknown) def + +% n linenum +/linenum { + /LineNum exch def +} def + +% (inputfilename) inputfile +/inputfile { + /InputFile exch def +} def + +% find size of Encoding and make a dictionary +% that size for bounding box information +mfont0 begin +/dictsize Encoding length def +mfont0 /Mcbbox0 dictsize dict put + +% temporarily redefine printmchar0 to get code +5 dict begin +/printmchar0 { {} forall } def + +Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put +Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put +Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put +Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put +Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put +Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put +Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put +Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put +Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put +Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put +Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put +Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put +Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put +Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put +Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put +Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put +Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put +Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put +Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put +Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put +Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put +Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put +Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put +Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put +Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put +Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put +Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put +Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put +Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put +Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put +Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put +Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put +Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put +Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put +Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put +Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put +Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put +Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put +Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put +Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put +Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put +Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put +Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put +Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put +Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put +Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put +Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put +Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put +Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put +Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put +Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put +Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put +Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put +Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put +Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put +Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put +Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put +Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put +Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put +Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put +Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put +Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put +Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put +Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put +Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put +Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put +Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put +Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put +Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put +Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put +Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put +Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put + +end +end + +/Mfont0 mfont0 definefont + + +% find size of Encoding and make a dictionary +% that size for bounding box information +mfont1 begin +/dictsize Encoding length def +mfont1 /Mcbbox1 dictsize dict put + +% temporarily redefine printmchar1 to get code +5 dict begin +/printmchar1 { {} forall } def + +Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put +Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put +Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put +Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put + +end +end + +/Mfont1 mfont1 definefont + +/makeExtEncoding { + /extendedencoding 256 array def + StandardEncoding extendedencoding copy + extendedencoding 32 /exclamdown put + extendedencoding 33 /cent put + extendedencoding 34 /sterling put + extendedencoding 35 /yen put + extendedencoding 36 /quotedblleft put + extendedencoding 37 /guillemotleft put + extendedencoding 38 /guillemotright put + extendedencoding 39 /guilsinglleft put + extendedencoding 40 /guilsinglright put + extendedencoding 41 /dagger put + extendedencoding 42 /daggerdbl put + extendedencoding 43 /bullet put + extendedencoding 44 /quotedblbase put + extendedencoding 45 /quotedblright put + extendedencoding 46 /questiondown put + extendedencoding 47 /grave put + extendedencoding 48 /acute put + extendedencoding 49 /macron put + extendedencoding 50 /breve put + extendedencoding 51 /dotaccent put + extendedencoding 52 /dieresis put + extendedencoding 53 /ring put + extendedencoding 54 /cedilla put + extendedencoding 55 /hungarumlaut put + extendedencoding 56 /ogonek put + extendedencoding 57 /caron put + extendedencoding 58 /emdash put + extendedencoding 59 /AE put + extendedencoding 60 /ae put + extendedencoding 61 /ordfeminine put + extendedencoding 62 /ordmasculine put + extendedencoding 63 /Lslash put + extendedencoding 64 /lslash put + extendedencoding 65 /Oslash put + extendedencoding 66 /oslash put + extendedencoding 67 /OE put + extendedencoding 68 /oe put + extendedencoding 69 /dotlessi put + extendedencoding 70 /germandbls put + extendedencoding 71 /Aacute put + extendedencoding 72 /aacute put + extendedencoding 73 /Acircumflex put + extendedencoding 74 /acircumflex put + extendedencoding 75 /Adieresis put + extendedencoding 76 /adieresis put + extendedencoding 77 /Agrave put + extendedencoding 78 /agrave put + extendedencoding 79 /Aring put + extendedencoding 80 /aring put + extendedencoding 81 /Atilde put + extendedencoding 82 /atilde put + extendedencoding 83 /Ccedilla put + extendedencoding 84 /ccedilla put + extendedencoding 85 /Eacute put + extendedencoding 86 /eacute put + extendedencoding 87 /Ecircumflex put + extendedencoding 88 /ecircumflex put + extendedencoding 89 /Edieresis put + extendedencoding 90 /edieresis put + extendedencoding 91 /Egrave put + extendedencoding 92 /egrave put + extendedencoding 93 /Iacute put + extendedencoding 94 /iacute put + extendedencoding 95 /Icircumflex put + extendedencoding 96 /icircumflex put + extendedencoding 97 /Idieresis put + extendedencoding 98 /idieresis put + extendedencoding 99 /Igrave put + extendedencoding 100 /igrave put + extendedencoding 101 /Ntilde put + extendedencoding 102 /ntilde put + extendedencoding 103 /Oacute put + extendedencoding 104 /oacute put + extendedencoding 105 /Ocircumflex put + extendedencoding 106 /ocircumflex put + extendedencoding 107 /Odieresis put + extendedencoding 108 /odieresis put + extendedencoding 109 /Ograve put + extendedencoding 110 /ograve put + extendedencoding 111 /Otilde put + extendedencoding 112 /otilde put + extendedencoding 113 /Scaron put + extendedencoding 114 /scaron put + extendedencoding 115 /Uacute put + extendedencoding 116 /uacute put + extendedencoding 117 /Ucircumflex put + extendedencoding 118 /ucircumflex put + extendedencoding 119 /Udieresis put + extendedencoding 120 /udieresis put + extendedencoding 121 /Ugrave put + extendedencoding 122 /ugrave put + extendedencoding 123 /Ydieresis put + extendedencoding 124 /ydieresis put + extendedencoding 125 /Zcaron put + extendedencoding 126 /zcaron put + extendedencoding 127 /space put +} def + +/makeExtendedFont { + findfont + dup length dict /newdict exch def + { 1 index /FID ne + { newdict 3 1 roll put } + { pop pop } + ifelse + } forall + newdict /Encoding extendedencoding put + newdict /UniqueID newdict /UniqueID get 1 add put + newdict definefont pop +} def +/flagsep 1.60 300 mul def % 1.60 stepsizes +/scv 147460 def /sf 962 string def +/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def +[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa +[ 961 ] 1341740116 fa +[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa +[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa +[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa +[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa +[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa +[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa +[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa +[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa +[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa +[ 795 ] 1622189328 fa +[ 463 45 40 41 50 45 84 ] 304180545 fa +[ 494 40 41 49 45 43 84 ] 251711819 fa +[ 149 203 37 144 ] 358262127 fa +[ 456 142 52 ] 95949173 fa +[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa +[ 839 5 13 12 13 13 48 ] 1943250302 fa +[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa +[ 798 1 3 1 ] 1277775234 fa +[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa +[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa +[ 193 49 180 8 17 134 ] 831070621 fa +[ 353 366 ] 1033403809 fa +[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa +[ 423 8 109 ] 508918194 fa +[ 328 6 30 6 31 6 269 ] 212071871 fa +[ 390 357 2 ] 1671244225 fa +[ 500 ] 347047368 fa +[ 558 ] 1276946910 fa +[ 651 ] 2109048312 fa +[ 644 ] 1914352160 fa +[ 520 ] 471204394 fa +[ 512 5 2 ] 1930983991 fa +[ 665 ] 154021439 fa +[ 513 ] 777103941 fa +[ 514 ] 260959830 fa +[ 530 239 ] 1284535922 fa +[ 510 ] 1982423675 fa +[ 150 ] 1969948305 fa +[ 511 7 134 ] 1407991454 fa +[ 144 371 ] 1896661664 fa +[ 464 52 ] 1444653737 fa +[ 509 81 ] 1712172720 fa +[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa +[ 954 ] 1802916616 fa +[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa +[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa +[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa +[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa +[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa +[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa +[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa +[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa +[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa +[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa +[ 960 ] 75399990 fa +[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa +[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa +[ 901 ] 422446918 fa +[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa +[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa +[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa +[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa +[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa +[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa +[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa +[ 780 32 ] 847653755 fa +[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa +[ 724 83 7 ] 1643402114 fa +[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa +[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa +[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa +[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa +[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa +[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa +[ 944 8 ] 1770206109 fa +[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa +[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa +[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa +[ 912 9 11 ] 273962927 fa +[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa +[ 130 683 ] 1406620603 fa +[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa +[ 861 13 9 4 12 8 17 3 ] 1447963591 fa +[ 67 143 8 128 115 435 19 2 ] 477757388 fa +[ 490 35 ] 1151262673 fa +[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa +[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa +sf cvx exec +%%EndProlog +%%Page: 1 1 +save +1216322504 1216321786 sv +0.700000 0.700000 scale +% S_SSV +(/home/johnkr/mup/5.3/doc/arkkra/star.mup) inputfile +12 linenum +% S_SSV +29 linenum +% S_FEED +252.00 1502.60 812.57 5 1.000000 1.000000 stf +252.00 1393.03 812.57 5 1.000000 1.000000 stf +107.50 1010.60 877.03 brace +0.70 setlinewidth +108.00 1010.60 moveto +108.00 877.03 lineto stroke +% S_CLEFSIG +119.79 992.60 1.000000 gclef +120.05 895.03 1.000000 fclef +134.41 1010.60 1.000000 sharp +141.05 1001.60 1.000000 sharp +147.69 1013.60 1.000000 sharp +134.41 895.03 1.000000 sharp +141.05 886.03 1.000000 sharp +147.69 898.03 1.000000 sharp +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +154.01 998.60 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +154.01 986.58 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +154.01 889.03 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +154.01 877.02 moveto +(4) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +41 linenum +195.97 942.88 moveto +218.78 942.88 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +175.38 942.88 moveto +(Oh) show +180.53 986.60 1.000000 4n +189.79 989.60 1.000000 dot +184.21 987.35 moveto +184.21 1005.39 lineto stroke +214.75 980.60 1.000000 4n +208.52 980.60 moveto +220.98 980.60 lineto stroke +218.43 981.35 moveto +218.43 999.39 lineto stroke +newpath +183.86 1006.89 moveto +218.78 1000.89 lineto +218.78 997.89 lineto +183.86 1003.89 lineto +closepath +fill +newpath +218.08 995.89 moveto +210.02 997.31 lineto +210.02 994.31 lineto +218.08 992.89 lineto +closepath +fill +180.53 986.60 1.000000 4n +189.79 989.60 1.000000 dot +176.85 985.85 moveto +176.85 967.81 lineto stroke +214.75 980.60 1.000000 4n +208.52 980.60 moveto +220.98 980.60 lineto stroke +211.07 979.85 moveto +211.07 961.81 lineto stroke +newpath +176.50 969.31 moveto +211.42 963.31 lineto +211.42 960.31 lineto +176.50 966.31 lineto +closepath +fill +newpath +210.72 968.31 moveto +202.66 969.72 lineto +202.66 966.72 lineto +210.72 965.31 lineto +closepath +fill +180.53 981.50 moveto +180.61 981.69 lineto +184.68 979.23 189.03 977.49 193.68 976.46 curveto +198.32 975.44 203.00 975.19 207.73 975.71 curveto +207.72 975.29 lineto +202.95 974.22 198.18 974.21 193.41 975.26 curveto +188.64 976.32 184.32 978.33 180.45 981.31 curveto +fill +194.79 991.70 moveto +194.80 991.93 lineto +198.45 992.99 202.09 992.97 205.73 991.88 curveto +209.37 990.79 212.41 988.79 214.87 985.90 curveto +214.63 985.50 lineto +211.93 987.92 208.84 989.65 205.37 990.69 curveto +201.90 991.73 198.37 991.99 194.79 991.47 curveto +fill +restore +% S_STAFF +% staff 2 +save +180.53 892.03 1.000000 4n +189.79 892.03 1.000000 dot +0.70 setlinewidth +184.21 892.78 moveto +184.21 910.83 lineto stroke +214.75 886.03 1.000000 4n +218.43 886.78 moveto +218.43 904.82 lineto stroke +newpath +183.86 912.33 moveto +218.78 906.33 lineto +218.78 903.33 lineto +183.86 909.33 lineto +closepath +fill +newpath +218.08 901.32 moveto +210.02 902.74 lineto +210.02 899.74 lineto +218.08 898.32 lineto +closepath +fill +180.53 892.03 1.000000 4n +189.79 892.03 1.000000 dot +176.85 891.28 moveto +176.85 873.24 lineto stroke +214.75 886.03 1.000000 4n +211.07 885.28 moveto +211.07 867.24 lineto stroke +newpath +176.50 874.74 moveto +211.42 868.74 lineto +211.42 865.74 lineto +176.50 871.74 lineto +closepath +fill +newpath +210.72 873.74 moveto +202.66 875.15 lineto +202.66 872.15 lineto +210.72 870.74 lineto +closepath +fill +180.53 886.93 moveto +180.61 887.13 lineto +184.68 884.66 189.03 882.92 193.68 881.90 curveto +198.32 880.87 203.00 880.62 207.73 881.14 curveto +207.72 880.72 lineto +202.95 879.65 198.18 879.64 193.41 880.69 curveto +188.64 881.75 184.32 883.76 180.45 886.74 curveto +fill +194.79 897.13 moveto +194.80 897.36 lineto +198.45 898.42 202.09 898.41 205.73 897.31 curveto +209.37 896.22 212.41 894.22 214.87 891.33 curveto +214.63 890.93 lineto +211.93 893.35 208.84 895.08 205.37 896.12 curveto +201.90 897.17 198.37 897.43 194.79 896.90 curveto +fill +restore +% S_BAR +44 linenum +239.31 1001.60 1.000000 dot +239.31 995.60 1.000000 dot +239.31 892.03 1.000000 dot +239.31 886.03 1.000000 dot +0.70 setlinewidth +236.31 1010.60 moveto +236.31 877.03 lineto stroke +3.00 setlinewidth +232.31 1010.60 moveto +232.31 877.03 lineto stroke +0.70 setlinewidth +% S_CHHEAD +% S_STAFF +% staff 1 +save +46 linenum +/Times-Roman findfont +12 scalefont +setfont +248.23 942.88 moveto +(say.) show +/Times-Roman findfont +12 scalefont +setfont +292.86 942.88 moveto +(can) show +/Times-Roman findfont +12 scalefont +setfont +335.46 942.88 moveto +(you) show +46 linenum +/Times-Roman findfont +12 scalefont +setfont +245.17 929.56 moveto +(stripes) show +/Times-Roman findfont +12 scalefont +setfont +292.70 929.56 moveto +(and) show +/Times-Roman findfont +12 scalefont +setfont +332.82 929.56 moveto +(bright) show +252.98 974.60 1.000000 4n +246.75 974.60 moveto +259.21 974.60 lineto stroke +246.75 980.60 moveto +259.21 980.60 lineto stroke +256.66 975.35 moveto +256.66 998.60 lineto stroke +297.02 980.60 1.000000 4n +290.79 980.60 moveto +303.25 980.60 lineto stroke +300.70 981.35 moveto +300.70 1001.60 lineto stroke +339.94 986.60 1.000000 4n +343.63 987.35 moveto +343.63 1007.60 lineto stroke +252.98 974.60 1.000000 4n +246.75 974.60 moveto +259.21 974.60 lineto stroke +246.75 980.60 moveto +259.21 980.60 lineto stroke +249.30 973.85 moveto +249.30 953.60 lineto stroke +297.02 980.60 1.000000 4n +290.79 980.60 moveto +303.25 980.60 lineto stroke +293.34 979.85 moveto +293.34 959.60 lineto stroke +339.94 977.60 1.000000 4n +333.71 980.60 moveto +346.18 980.60 lineto stroke +336.26 976.85 moveto +336.26 956.60 lineto stroke +restore +% S_STAFF +% staff 2 +save +252.98 880.03 1.000000 4n +0.70 setlinewidth +256.66 880.78 moveto +256.66 901.03 lineto stroke +297.02 901.03 1.000000 4n +300.70 901.78 moveto +300.70 922.03 lineto stroke +339.94 904.03 1.000000 4n +343.63 904.78 moveto +343.63 925.03 lineto stroke +252.98 880.03 1.000000 4n +249.30 879.28 moveto +249.30 859.03 lineto stroke +297.02 901.03 1.000000 4n +293.34 900.28 moveto +293.34 880.03 lineto stroke +339.94 898.03 1.000000 4n +336.26 897.28 moveto +336.26 877.03 lineto stroke +restore +% S_BAR +53 linenum +0.70 setlinewidth +382.54 1010.60 moveto +382.54 877.03 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +54 linenum +/Times-Roman findfont +12 scalefont +setfont +394.16 942.88 moveto +(see,) show +/Times-Roman findfont +12 scalefont +setfont +463.54 942.88 moveto +(by) show +/Times-Roman findfont +12 scalefont +setfont +499.31 942.88 moveto +(the) show +54 linenum +/Times-Roman findfont +12 scalefont +setfont +392.51 929.56 moveto +(stars,) show +/Times-Roman findfont +12 scalefont +setfont +457.24 929.56 moveto +(through) show +/Times-Roman findfont +12 scalefont +setfont +499.31 929.56 moveto +(the) show +398.75 995.60 1.000000 2n +402.65 996.35 moveto +402.65 1016.60 lineto stroke +466.53 1001.60 1.000000 4n +475.79 1001.60 1.000000 dot +470.21 1002.35 moveto +470.21 1020.77 lineto stroke +502.96 998.60 1.000000 4n +506.64 999.35 moveto +506.64 1017.77 lineto stroke +newpath +469.86 1022.27 moveto +506.99 1019.27 lineto +506.99 1016.27 lineto +469.86 1019.27 lineto +closepath +fill +newpath +506.29 1014.27 moveto +498.23 1014.93 lineto +498.23 1011.93 lineto +506.29 1011.27 lineto +closepath +fill +398.75 980.60 1.000000 2n +392.31 980.60 moveto +405.20 980.60 lineto stroke +394.86 979.85 moveto +394.86 959.60 lineto stroke +466.53 980.60 1.000000 4n +475.79 977.60 1.000000 dot +460.29 980.60 moveto +472.76 980.60 lineto stroke +462.84 979.85 moveto +462.84 961.10 lineto stroke +502.96 980.60 1.000000 4n +496.73 980.60 moveto +509.19 980.60 lineto stroke +499.28 979.85 moveto +499.28 961.10 lineto stroke +newpath +462.49 962.60 moveto +499.63 962.60 lineto +499.63 959.60 lineto +462.49 959.60 lineto +closepath +fill +newpath +498.93 967.60 moveto +490.87 967.60 lineto +490.87 964.60 lineto +498.93 964.60 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +398.75 901.03 1.000000 2n +0.70 setlinewidth +402.65 901.78 moveto +402.65 922.03 lineto stroke +466.53 898.03 1.000000 4n +475.79 898.03 1.000000 dot +470.21 898.78 moveto +470.21 917.53 lineto stroke +502.96 898.03 1.000000 4n +506.64 898.78 moveto +506.64 917.53 lineto stroke +newpath +469.86 919.03 moveto +506.99 919.03 lineto +506.99 916.03 lineto +469.86 916.03 lineto +closepath +fill +newpath +506.29 914.03 moveto +498.23 914.03 lineto +498.23 911.03 lineto +506.29 911.03 lineto +closepath +fill +398.75 895.03 1.000000 2n +394.86 894.28 moveto +394.86 874.03 lineto stroke +466.53 892.03 1.000000 4n +457.17 892.03 1.000000 sharp +475.79 892.03 1.000000 dot +462.84 891.28 moveto +462.84 872.53 lineto stroke +502.96 892.03 1.000000 4n +499.28 891.28 moveto +499.28 872.53 lineto stroke +newpath +462.49 874.03 moveto +499.63 874.03 lineto +499.63 871.03 lineto +462.49 871.03 lineto +closepath +fill +newpath +498.93 879.03 moveto +490.87 879.03 lineto +490.87 876.03 lineto +498.93 876.03 lineto +closepath +fill +restore +% S_BAR +61 linenum +0.70 setlinewidth +520.01 1010.60 moveto +520.01 877.03 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +62 linenum +/Times-Roman findfont +12 scalefont +setfont +524.95 942.88 moveto +(dawn's) show +/Times-Roman findfont +12 scalefont +setfont +602.20 942.88 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +572.65 942.88 moveto +(ear) show +/Times-Roman findfont +12 scalefont +setfont +620.13 942.88 moveto +(ly) show +62 linenum +/Times-Roman findfont +12 scalefont +setfont +557.85 929.56 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +528.79 929.56 moveto +(per) show +/Times-Roman findfont +12 scalefont +setfont +598.29 929.56 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +574.65 929.56 moveto +(il) show +/Times-Roman findfont +12 scalefont +setfont +618.30 929.56 moveto +(ous) show +533.59 995.60 1.000000 4n +537.28 996.35 moveto +537.28 1016.60 lineto stroke +577.30 980.60 1.000000 4n +571.06 980.60 moveto +583.53 980.60 lineto stroke +580.98 981.35 moveto +580.98 1001.60 lineto stroke +622.46 983.60 1.000000 4n +613.10 983.60 1.000000 sharp +626.14 984.35 moveto +626.14 1004.60 lineto stroke +533.59 980.60 1.000000 4n +527.36 980.60 moveto +539.83 980.60 lineto stroke +529.91 979.85 moveto +529.91 959.60 lineto stroke +577.30 980.60 1.000000 4n +571.06 980.60 moveto +583.53 980.60 lineto stroke +573.61 979.85 moveto +573.61 959.60 lineto stroke +622.46 977.60 1.000000 4n +616.22 980.60 moveto +628.69 980.60 lineto stroke +618.77 976.85 moveto +618.77 956.60 lineto stroke +restore +% S_STAFF +% staff 2 +save +533.59 901.03 1.000000 4n +0.70 setlinewidth +537.28 901.78 moveto +537.28 922.03 lineto stroke +577.30 901.03 1.000000 4n +580.98 901.78 moveto +580.98 922.03 lineto stroke +622.46 901.03 1.000000 4n +626.14 901.78 moveto +626.14 922.03 lineto stroke +533.59 895.03 1.000000 4n +529.91 894.28 moveto +529.91 874.03 lineto stroke +577.30 895.03 1.000000 4n +573.61 894.28 moveto +573.61 874.03 lineto stroke +622.46 883.03 1.000000 4n +618.77 882.28 moveto +618.77 862.03 lineto stroke +restore +% S_BAR +69 linenum +0.70 setlinewidth +663.57 1010.60 moveto +663.57 877.03 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +70 linenum +/Times-Roman findfont +12 scalefont +setfont +672.07 942.88 moveto +(light) show +/Times-Roman findfont +12 scalefont +setfont +752.92 942.88 moveto +(what) show +/Times-Roman findfont +12 scalefont +setfont +783.82 942.88 moveto +(so) show +70 linenum +/Times-Roman findfont +12 scalefont +setfont +671.15 929.56 moveto +(fight,) show +/Times-Roman findfont +12 scalefont +setfont +753.93 929.56 moveto +(o'er) show +/Times-Roman findfont +12 scalefont +setfont +782.83 929.56 moveto +(the) show +677.54 986.60 1.000000 4n +681.22 987.35 moveto +681.22 1007.60 lineto stroke +721.69 1010.60 1.000000 4rest +758.73 986.60 1.000000 4n +762.42 987.35 moveto +762.42 1006.10 lineto stroke +786.49 986.60 1.000000 4n +790.17 987.35 moveto +790.17 1006.10 lineto stroke +newpath +762.07 1007.60 moveto +790.52 1007.60 lineto +790.52 1004.60 lineto +762.07 1004.60 lineto +closepath +fill +677.54 977.60 1.000000 4n +671.31 980.60 moveto +683.77 980.60 lineto stroke +673.86 976.85 moveto +673.86 956.60 lineto stroke +721.69 968.60 1.000000 4rest +758.73 977.60 1.000000 4n +752.50 980.60 moveto +764.97 980.60 lineto stroke +755.05 976.85 moveto +755.05 958.10 lineto stroke +786.49 977.60 1.000000 4n +780.25 980.60 moveto +792.72 980.60 lineto stroke +782.80 976.85 moveto +782.80 958.10 lineto stroke +newpath +754.70 959.60 moveto +783.15 959.60 lineto +783.15 956.60 lineto +754.70 956.60 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +677.54 898.03 1.000000 4n +0.70 setlinewidth +681.22 898.78 moveto +681.22 919.03 lineto stroke +721.69 907.03 1.000000 4rest +758.73 898.03 1.000000 4n +762.42 898.78 moveto +762.42 917.53 lineto stroke +786.49 898.03 1.000000 4n +790.17 898.78 moveto +790.17 917.53 lineto stroke +newpath +762.07 919.03 moveto +790.52 919.03 lineto +790.52 916.03 lineto +762.07 916.03 lineto +closepath +fill +677.54 892.03 1.000000 4n +673.86 891.28 moveto +673.86 871.03 lineto stroke +721.69 877.03 1.000000 4rest +758.73 892.03 1.000000 4n +755.05 891.28 moveto +755.05 872.53 lineto stroke +786.49 892.03 1.000000 4n +782.80 891.28 moveto +782.80 872.53 lineto stroke +newpath +754.70 874.03 moveto +783.15 874.03 lineto +783.15 871.03 lineto +754.70 871.03 lineto +closepath +fill +restore +% S_BAR +77 linenum +0.70 setlinewidth +812.22 1010.60 moveto +812.22 877.03 lineto stroke +% S_FEED +215.71 1309.03 812.57 5 1.000000 1.000000 stf +/Times-Roman findfont +11 scalefont +setfont +76.21 831.03 moveto +(5) show +215.71 1196.34 812.57 5 1.000000 1.000000 stf +71.21 817.03 680.34 brace +71.71 817.03 moveto +71.71 680.34 lineto stroke +512.40 831.03 moveto +512.40 842.03 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +515.40 832.03 moveto +(1.) show +512.40 842.03 moveto +663.97 842.03 lineto stroke +663.97 842.03 moveto +663.97 831.03 lineto stroke +667.97 831.03 moveto +667.97 842.03 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +670.97 832.03 moveto +(2.) show +667.97 842.03 moveto +810.22 842.03 lineto stroke +% S_CLEFSIG +83.51 799.03 1.000000 gclef +83.76 698.34 1.000000 fclef +98.12 817.03 1.000000 sharp +104.76 808.03 1.000000 sharp +111.40 820.03 1.000000 sharp +98.12 698.34 1.000000 sharp +104.76 689.34 1.000000 sharp +111.40 701.34 1.000000 sharp +% S_CHHEAD +% S_STAFF +% staff 1 +save +78 linenum +/Times-Roman findfont +12 scalefont +setfont +170.50 746.26 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +130.63 746.26 moveto +(proud) show +/Times-Roman findfont +12 scalefont +setfont +185.51 746.26 moveto +(ly) show +/Times-Roman findfont +12 scalefont +setfont +214.49 746.26 moveto +(we) show +78 linenum +/Times-Roman findfont +12 scalefont +setfont +165.30 732.94 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +132.94 732.94 moveto +(ram) show +/Times-Roman findfont +12 scalefont +setfont +182.01 732.94 moveto +(parts) show +/Times-Roman findfont +12 scalefont +setfont +214.49 732.94 moveto +(we) show +138.59 808.03 1.000000 4n +147.85 808.03 1.000000 dot +142.27 808.78 moveto +142.27 829.03 lineto stroke +187.83 805.03 1.000000 4n +191.51 805.78 moveto +191.51 826.03 lineto stroke +194.53 826.03 1.000000 dnflag +217.98 802.03 1.000000 4n +221.67 802.78 moveto +221.67 823.03 lineto stroke +138.59 793.03 1.000000 4n +147.85 790.03 1.000000 dot +134.91 792.28 moveto +134.91 772.03 lineto stroke +187.83 793.03 1.000000 4n +184.15 792.28 moveto +184.15 772.03 lineto stroke +187.17 772.03 1.000000 upflag +217.98 793.03 1.000000 4n +214.30 792.28 moveto +214.30 772.03 lineto stroke +restore +% S_STAFF +% staff 2 +save +138.59 704.34 1.000000 4n +147.85 707.34 1.000000 dot +0.70 setlinewidth +142.27 705.09 moveto +142.27 725.34 lineto stroke +187.83 701.34 1.000000 4n +191.51 702.09 moveto +191.51 722.34 lineto stroke +194.53 722.34 1.000000 dnflag +217.98 704.34 1.000000 4n +221.67 705.09 moveto +221.67 725.34 lineto stroke +138.59 683.34 1.000000 4n +147.85 683.34 1.000000 dot +134.91 682.59 moveto +134.91 662.34 lineto stroke +187.83 686.34 1.000000 4n +184.15 685.59 moveto +184.15 665.34 lineto stroke +187.17 665.34 1.000000 upflag +217.98 689.34 1.000000 4n +214.30 688.59 moveto +214.30 668.34 lineto stroke +restore +% S_BAR +85 linenum +0.70 setlinewidth +255.25 817.03 moveto +255.25 680.34 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +86 linenum +/Times-Roman findfont +12 scalefont +setfont +265.25 746.26 moveto +(hailed,) show +/Times-Roman findfont +12 scalefont +setfont +334.23 746.26 moveto +(At) show +/Times-Roman findfont +12 scalefont +setfont +363.54 746.26 moveto +(the) show +86 linenum +/Times-Roman findfont +12 scalefont +setfont +262.58 732.94 moveto +(watched,) show +/Times-Roman findfont +12 scalefont +setfont +331.41 732.94 moveto +(were) show +/Times-Roman findfont +12 scalefont +setfont +364.53 732.94 moveto +(so) show +273.31 799.03 1.000000 2n +277.21 799.78 moveto +277.21 820.03 lineto stroke +333.54 796.03 1.000000 4n +350.17 796.03 1.000000 dot +337.22 796.78 moveto +337.22 815.89 lineto stroke +367.20 799.03 1.000000 4n +370.88 799.78 moveto +370.88 818.89 lineto stroke +newpath +336.87 817.39 moveto +371.23 820.39 lineto +371.23 817.39 lineto +336.87 814.39 lineto +closepath +fill +newpath +370.53 815.39 moveto +362.46 814.67 lineto +362.46 811.67 lineto +370.53 812.39 lineto +closepath +fill +273.31 793.03 1.000000 2n +269.41 792.28 moveto +269.41 772.03 lineto stroke +340.90 793.03 1.000000 4n +350.17 790.03 1.000000 dot +337.22 792.28 moveto +337.22 773.53 lineto stroke +367.20 793.03 1.000000 4n +363.51 792.28 moveto +363.51 773.53 lineto stroke +newpath +336.87 775.03 moveto +363.86 775.03 lineto +363.86 772.03 lineto +336.87 772.03 lineto +closepath +fill +newpath +363.16 780.03 moveto +355.10 780.03 lineto +355.10 777.03 lineto +363.16 777.03 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +273.31 707.34 1.000000 2n +0.70 setlinewidth +277.21 708.09 moveto +277.21 728.34 lineto stroke +337.22 707.34 1.000000 4n +346.49 707.34 1.000000 dot +340.90 708.09 moveto +340.90 726.84 lineto stroke +367.20 707.34 1.000000 4n +370.88 708.09 moveto +370.88 726.84 lineto stroke +newpath +340.55 728.34 moveto +371.23 728.34 lineto +371.23 725.34 lineto +340.55 725.34 lineto +closepath +fill +newpath +370.53 723.34 moveto +362.46 723.34 lineto +362.46 720.34 lineto +370.53 720.34 lineto +closepath +fill +273.31 695.34 1.000000 2n +269.41 694.59 moveto +269.41 674.34 lineto stroke +337.22 692.34 1.000000 4n +346.49 689.34 1.000000 dot +333.54 691.59 moveto +333.54 672.84 lineto stroke +367.20 692.34 1.000000 4n +363.51 691.59 moveto +363.51 672.84 lineto stroke +newpath +333.19 674.34 moveto +363.86 674.34 lineto +363.86 671.34 lineto +333.19 671.34 lineto +closepath +fill +newpath +363.16 679.34 moveto +355.10 679.34 lineto +355.10 676.34 lineto +363.16 676.34 lineto +closepath +fill +restore +% S_BAR +93 linenum +0.70 setlinewidth +383.09 817.03 moveto +383.09 680.34 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +94 linenum +/Times-Roman findfont +12 scalefont +setfont +412.73 746.26 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +389.54 746.26 moveto +(twi) show +/Times-Roman findfont +12 scalefont +setfont +423.66 746.26 moveto +(light's) show +/Times-Roman findfont +12 scalefont +setfont +468.64 746.26 moveto +(last) show +94 linenum +/Times-Roman findfont +12 scalefont +setfont +413.57 732.94 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +389.70 732.94 moveto +(gal) show +/Times-Roman findfont +12 scalefont +setfont +455.61 732.94 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +425.82 732.94 moveto +(lant) show +/Times-Roman findfont +12 scalefont +setfont +470.47 732.94 moveto +(ly) show +394.35 802.03 1.000000 4n +398.03 802.78 moveto +398.03 823.03 lineto stroke +431.29 802.03 1.000000 4n +434.97 802.78 moveto +434.97 823.03 lineto stroke +472.80 793.03 1.000000 4n +476.48 793.78 moveto +476.48 814.03 lineto stroke +394.35 793.03 1.000000 4n +390.67 792.28 moveto +390.67 772.03 lineto stroke +431.29 793.03 1.000000 4n +427.61 792.28 moveto +427.61 772.03 lineto stroke +472.80 793.03 1.000000 4n +469.11 792.28 moveto +469.11 772.03 lineto stroke +restore +% S_STAFF +% staff 2 +save +394.35 704.34 1.000000 4n +0.70 setlinewidth +398.03 705.09 moveto +398.03 725.34 lineto stroke +431.29 704.34 1.000000 4n +434.97 705.09 moveto +434.97 725.34 lineto stroke +472.80 695.34 1.000000 4n +476.48 696.09 moveto +476.48 716.34 lineto stroke +394.35 689.34 1.000000 4n +390.67 688.59 moveto +390.67 668.34 lineto stroke +431.29 689.34 1.000000 4n +427.61 688.59 moveto +427.61 668.34 lineto stroke +472.80 695.34 1.000000 4n +469.11 694.59 moveto +469.11 674.34 lineto stroke +restore +% S_BAR +100 linenum +0.70 setlinewidth +510.40 817.03 moveto +510.40 680.34 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +102 linenum +/Times-Roman findfont +12 scalefont +setfont +549.46 746.26 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +515.31 746.26 moveto +(gleam) show +/Times-Roman findfont +12 scalefont +setfont +557.30 746.26 moveto +(ing,) show +/Times-Roman findfont +12 scalefont +setfont +597.13 746.26 moveto +(whose) show +/Times-Roman findfont +12 scalefont +setfont +630.75 746.26 moveto +(broad) show +523.62 787.03 1.000000 4n +517.39 787.03 moveto +529.85 787.03 lineto stroke +527.30 787.78 moveto +527.30 808.03 lineto stroke +561.88 781.03 1.000000 4n +555.64 781.03 moveto +568.11 781.03 lineto stroke +555.64 787.03 moveto +568.11 787.03 lineto stroke +565.56 781.78 moveto +565.56 805.03 lineto stroke +568.58 805.03 1.000000 dnflag +584.77 817.03 1.000000 8rest +604.78 793.03 1.000000 4n +614.04 796.03 1.000000 dot +608.46 793.78 moveto +608.46 811.79 lineto stroke +637.56 787.03 1.000000 4n +631.33 787.03 moveto +643.79 787.03 lineto stroke +641.24 787.78 moveto +641.24 805.79 lineto stroke +newpath +608.11 813.29 moveto +641.59 807.29 lineto +641.59 804.29 lineto +608.11 810.29 lineto +closepath +fill +newpath +640.89 802.29 moveto +632.83 803.77 lineto +632.83 800.77 lineto +640.89 799.29 lineto +closepath +fill +523.62 787.03 1.000000 4n +517.39 787.03 moveto +529.85 787.03 lineto stroke +519.94 786.28 moveto +519.94 766.03 lineto stroke +561.88 781.03 1.000000 4n +555.64 781.03 moveto +568.11 781.03 lineto stroke +555.64 787.03 moveto +568.11 787.03 lineto stroke +558.19 780.28 moveto +558.19 760.03 lineto stroke +561.22 760.03 1.000000 upflag +584.77 763.03 1.000000 8rest +604.78 793.03 1.000000 4n +614.04 796.03 1.000000 dot +601.10 792.28 moveto +601.10 774.27 lineto stroke +637.56 787.03 1.000000 4n +631.33 787.03 moveto +643.79 787.03 lineto stroke +633.88 786.28 moveto +633.88 768.27 lineto stroke +newpath +600.75 775.77 moveto +634.23 769.77 lineto +634.23 766.77 lineto +600.75 772.77 lineto +closepath +fill +newpath +633.53 774.77 moveto +625.46 776.25 lineto +625.46 773.25 lineto +633.53 771.77 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +523.62 689.34 1.000000 4n +0.70 setlinewidth +527.30 690.09 moveto +527.30 710.34 lineto stroke +561.88 683.34 1.000000 4n +565.56 684.09 moveto +565.56 704.34 lineto stroke +568.58 704.34 1.000000 dnflag +584.77 710.34 1.000000 8rest +604.78 695.34 1.000000 4n +614.04 695.34 1.000000 dot +608.46 696.09 moveto +608.46 714.10 lineto stroke +637.56 689.34 1.000000 4n +641.24 690.09 moveto +641.24 708.10 lineto stroke +newpath +608.11 715.60 moveto +641.59 709.60 lineto +641.59 706.60 lineto +608.11 712.60 lineto +closepath +fill +newpath +640.89 704.60 moveto +632.83 706.07 lineto +632.83 703.07 lineto +640.89 701.60 lineto +closepath +fill +523.62 689.34 1.000000 4n +519.94 688.59 moveto +519.94 668.34 lineto stroke +561.88 683.34 1.000000 4n +558.19 682.59 moveto +558.19 662.34 lineto stroke +561.22 662.34 1.000000 upflag +584.77 668.34 1.000000 8rest +604.78 695.34 1.000000 4n +614.04 695.34 1.000000 dot +601.10 694.59 moveto +601.10 676.57 lineto stroke +637.56 689.34 1.000000 4n +633.88 688.59 moveto +633.88 670.57 lineto stroke +newpath +600.75 678.07 moveto +634.23 672.07 lineto +634.23 669.07 lineto +600.75 675.07 lineto +closepath +fill +newpath +633.53 677.07 moveto +625.46 678.55 lineto +625.46 675.55 lineto +633.53 674.07 lineto +closepath +fill +restore +% S_BAR +104 linenum +661.97 808.03 1.000000 dot +661.97 802.03 1.000000 dot +661.97 695.34 1.000000 dot +661.97 689.34 1.000000 dot +0.70 setlinewidth +665.97 817.03 moveto +665.97 680.34 lineto stroke +3.00 setlinewidth +669.97 817.03 moveto +669.97 680.34 lineto stroke +0.70 setlinewidth +% S_CHHEAD +% S_STAFF +% staff 1 +save +106 linenum +/Times-Roman findfont +12 scalefont +setfont +710.73 732.94 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +675.03 732.94 moveto +(stream) show +/Times-Roman findfont +12 scalefont +setfont +717.47 732.94 moveto +(ing?) show +/Times-Roman findfont +12 scalefont +setfont +761.54 732.94 moveto +(And) show +/Times-Roman findfont +12 scalefont +setfont +792.68 732.94 moveto +(the) show +684.01 787.03 1.000000 4n +677.78 787.03 moveto +690.24 787.03 lineto stroke +687.69 787.78 moveto +687.69 808.03 lineto stroke +722.62 781.03 1.000000 4n +716.38 781.03 moveto +728.85 781.03 lineto stroke +716.38 787.03 moveto +728.85 787.03 lineto stroke +726.30 781.78 moveto +726.30 805.03 lineto stroke +729.32 805.03 1.000000 dnflag +745.53 817.03 1.000000 8rest +766.69 808.03 1.000000 4n +775.95 808.03 1.000000 dot +770.37 808.78 moveto +770.37 827.53 lineto stroke +796.33 808.03 1.000000 4n +800.01 808.78 moveto +800.01 827.53 lineto stroke +newpath +770.02 829.03 moveto +800.36 829.03 lineto +800.36 826.03 lineto +770.02 826.03 lineto +closepath +fill +newpath +799.66 824.03 moveto +791.60 824.03 lineto +791.60 821.03 lineto +799.66 821.03 lineto +closepath +fill +684.01 787.03 1.000000 4n +677.78 787.03 moveto +690.24 787.03 lineto stroke +680.33 786.28 moveto +680.33 766.03 lineto stroke +722.62 781.03 1.000000 4n +716.38 781.03 moveto +728.85 781.03 lineto stroke +716.38 787.03 moveto +728.85 787.03 lineto stroke +718.93 780.28 moveto +718.93 760.03 lineto stroke +721.96 760.03 1.000000 upflag +745.53 763.03 1.000000 8rest +766.69 793.03 1.000000 4n +775.95 790.03 1.000000 dot +763.01 792.28 moveto +763.01 773.53 lineto stroke +796.33 793.03 1.000000 4n +792.65 792.28 moveto +792.65 773.53 lineto stroke +newpath +762.66 775.03 moveto +793.00 775.03 lineto +793.00 772.03 lineto +762.66 772.03 lineto +closepath +fill +newpath +792.30 780.03 moveto +784.24 780.03 lineto +784.24 777.03 lineto +792.30 777.03 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +684.01 689.34 1.000000 4n +0.70 setlinewidth +687.69 690.09 moveto +687.69 710.34 lineto stroke +722.62 683.34 1.000000 4n +726.30 684.09 moveto +726.30 704.34 lineto stroke +729.32 704.34 1.000000 dnflag +745.53 704.34 1.000000 8rest +766.69 704.34 1.000000 4n +775.95 707.34 1.000000 dot +770.37 705.09 moveto +770.37 723.84 lineto stroke +796.33 704.34 1.000000 4n +800.01 705.09 moveto +800.01 723.84 lineto stroke +newpath +770.02 725.34 moveto +800.36 725.34 lineto +800.36 722.34 lineto +770.02 722.34 lineto +closepath +fill +newpath +799.66 720.34 moveto +791.60 720.34 lineto +791.60 717.34 lineto +799.66 717.34 lineto +closepath +fill +684.01 689.34 1.000000 4n +680.33 688.59 moveto +680.33 668.34 lineto stroke +722.62 683.34 1.000000 4n +718.93 682.59 moveto +718.93 662.34 lineto stroke +721.96 662.34 1.000000 upflag +745.53 668.34 1.000000 8rest +766.69 683.34 1.000000 4n +775.95 683.34 1.000000 dot +763.01 682.59 moveto +763.01 663.84 lineto stroke +796.33 683.34 1.000000 4n +792.65 682.59 moveto +792.65 663.84 lineto stroke +newpath +762.66 665.34 moveto +793.00 665.34 lineto +793.00 662.34 lineto +762.66 662.34 lineto +closepath +fill +newpath +792.30 670.34 moveto +784.24 670.34 lineto +784.24 667.34 lineto +792.30 667.34 lineto +closepath +fill +restore +% S_BAR +111 linenum +0.70 setlinewidth +812.22 817.03 moveto +812.22 680.34 lineto stroke +% S_FEED +215.71 1112.34 812.57 5 1.000000 1.000000 stf +/Times-Roman findfont +11 scalefont +setfont +76.21 634.34 moveto +(10) show +215.71 1025.09 812.57 5 1.000000 1.000000 stf +71.21 620.34 509.09 brace +71.71 620.34 moveto +71.71 509.09 lineto stroke +% S_CLEFSIG +83.51 602.34 1.000000 gclef +83.76 527.09 1.000000 fclef +98.12 620.34 1.000000 sharp +104.76 611.34 1.000000 sharp +111.40 623.34 1.000000 sharp +98.12 527.09 1.000000 sharp +104.76 518.09 1.000000 sharp +111.40 530.09 1.000000 sharp +% S_CHHEAD +% S_STAFF +% staff 1 +save +113 linenum +/Times-Roman findfont +12 scalefont +setfont +159.96 564.62 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +129.45 564.62 moveto +(rock) show +/Times-Roman findfont +12 scalefont +setfont +172.23 564.62 moveto +(ets') show +/Times-Roman findfont +12 scalefont +setfont +214.63 564.62 moveto +(red) show +135.75 611.34 1.000000 4n +139.43 612.09 moveto +139.43 632.34 lineto stroke +176.55 614.34 1.000000 4n +180.23 615.09 moveto +180.23 635.34 lineto stroke +218.45 617.34 1.000000 4n +222.13 618.09 moveto +222.13 638.34 lineto stroke +135.75 596.34 1.000000 4n +132.07 595.59 moveto +132.07 575.34 lineto stroke +176.55 596.34 1.000000 4n +172.86 595.59 moveto +172.86 575.34 lineto stroke +218.45 596.34 1.000000 4n +214.77 595.59 moveto +214.77 575.34 lineto stroke +restore +% S_STAFF +% staff 2 +save +135.75 533.09 1.000000 4n +0.70 setlinewidth +139.43 533.84 moveto +139.43 554.09 lineto stroke +176.55 536.09 1.000000 4n +180.23 536.84 moveto +180.23 557.09 lineto stroke +218.45 539.09 1.000000 4n +212.22 539.09 moveto +224.68 539.09 lineto stroke +222.13 539.84 moveto +222.13 560.09 lineto stroke +135.75 512.09 1.000000 4n +132.07 511.34 moveto +132.07 491.09 lineto stroke +176.55 512.09 1.000000 4n +172.86 511.34 moveto +172.86 491.09 lineto stroke +218.45 512.09 1.000000 4n +214.77 511.34 moveto +214.77 491.09 lineto stroke +restore +% S_BAR +122 linenum +0.70 setlinewidth +257.45 620.34 moveto +257.45 509.09 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +127 linenum +/Times-Roman findfont +12 scalefont +setfont +264.47 564.62 moveto +(glare,) show +/Times-Roman findfont +12 scalefont +setfont +344.84 564.62 moveto +(the) show +/Times-Roman findfont +12 scalefont +setfont +363.46 564.62 moveto +(bombs) show +271.21 617.34 1.000000 4n +274.89 618.09 moveto +274.89 638.34 lineto stroke +313.19 620.34 1.000000 4rest +348.49 614.34 1.000000 4n +352.18 615.09 moveto +352.18 633.31 lineto stroke +371.45 611.34 1.000000 4n +375.13 612.09 moveto +375.13 630.31 lineto stroke +newpath +351.83 634.81 moveto +375.48 631.81 lineto +375.48 628.81 lineto +351.83 631.81 lineto +closepath +fill +271.21 596.34 1.000000 4n +267.52 595.59 moveto +267.52 575.34 lineto stroke +313.19 596.34 1.000000 4rest +348.49 596.34 1.000000 4n +344.81 595.59 moveto +344.81 576.84 lineto stroke +371.45 596.34 1.000000 4n +367.77 595.59 moveto +367.77 576.84 lineto stroke +newpath +344.46 578.34 moveto +368.12 578.34 lineto +368.12 575.34 lineto +344.46 575.34 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +271.21 539.09 1.000000 4n +0.70 setlinewidth +264.97 539.09 moveto +277.44 539.09 lineto stroke +274.89 539.84 moveto +274.89 560.09 lineto stroke +313.19 533.09 1.000000 4rest +348.49 536.09 1.000000 4n +352.18 536.84 moveto +352.18 555.06 lineto stroke +371.45 533.09 1.000000 4n +375.13 533.84 moveto +375.13 552.06 lineto stroke +newpath +351.83 556.56 moveto +375.48 553.56 lineto +375.48 550.56 lineto +351.83 553.56 lineto +closepath +fill +271.21 512.09 1.000000 4n +267.52 511.34 moveto +267.52 491.09 lineto stroke +313.19 509.09 1.000000 4rest +348.49 512.09 1.000000 4n +344.81 511.34 moveto +344.81 492.59 lineto stroke +371.45 512.09 1.000000 4n +367.77 511.34 moveto +367.77 492.59 lineto stroke +newpath +344.46 494.09 moveto +368.12 494.09 lineto +368.12 491.09 lineto +344.46 491.09 lineto +closepath +fill +restore +% S_BAR +130 linenum +0.70 setlinewidth +398.93 620.34 moveto +398.93 509.09 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +131 linenum +/Times-Roman findfont +12 scalefont +setfont +437.54 564.62 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +404.82 564.62 moveto +(burst) show +/Times-Roman findfont +12 scalefont +setfont +449.35 564.62 moveto +(ing) show +/Times-Roman findfont +12 scalefont +setfont +493.24 564.62 moveto +(in) show +411.79 608.34 1.000000 4n +415.47 609.09 moveto +415.47 629.34 lineto stroke +453.17 611.34 1.000000 4n +456.85 612.09 moveto +456.85 632.34 lineto stroke +495.57 614.34 1.000000 4n +499.25 615.09 moveto +499.25 635.34 lineto stroke +411.79 596.34 1.000000 4n +408.11 595.59 moveto +408.11 575.34 lineto stroke +453.17 596.34 1.000000 4n +449.49 595.59 moveto +449.49 575.34 lineto stroke +495.57 596.34 1.000000 4n +491.88 595.59 moveto +491.88 575.34 lineto stroke +restore +% S_STAFF +% staff 2 +save +411.79 530.09 1.000000 4n +0.70 setlinewidth +415.47 530.84 moveto +415.47 551.09 lineto stroke +453.17 530.09 1.000000 4n +456.85 530.84 moveto +456.85 551.09 lineto stroke +495.57 530.09 1.000000 4n +499.25 530.84 moveto +499.25 551.09 lineto stroke +411.79 524.09 1.000000 4n +408.11 523.34 moveto +408.11 503.09 lineto stroke +453.17 524.09 1.000000 4n +449.49 523.34 moveto +449.49 503.09 lineto stroke +495.57 524.09 1.000000 4n +491.88 523.34 moveto +491.88 503.09 lineto stroke +restore +% S_BAR +134 linenum +0.70 setlinewidth +533.82 620.34 moveto +533.82 509.09 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +135 linenum +/Times-Roman findfont +12 scalefont +setfont +543.38 564.62 moveto +(air,) show +/Times-Roman findfont +12 scalefont +setfont +621.21 564.62 moveto +(gave) show +547.29 614.34 1.000000 4n +550.97 615.09 moveto +550.97 635.34 lineto stroke +587.76 620.34 1.000000 4rest +626.86 614.34 1.000000 4n +630.54 615.09 moveto +630.54 635.34 lineto stroke +547.29 596.34 1.000000 4n +543.61 595.59 moveto +543.61 575.34 lineto stroke +587.76 596.34 1.000000 4rest +626.86 596.34 1.000000 4n +623.18 595.59 moveto +623.18 575.34 lineto stroke +restore +% S_STAFF +% staff 2 +save +547.29 530.09 1.000000 4n +0.70 setlinewidth +550.97 530.84 moveto +550.97 551.09 lineto stroke +587.76 539.09 1.000000 4rest +626.86 530.09 1.000000 4n +630.54 530.84 moveto +630.54 551.09 lineto stroke +547.29 524.09 1.000000 4n +543.61 523.34 moveto +543.61 503.09 lineto stroke +587.76 509.09 1.000000 4rest +626.86 524.09 1.000000 4n +623.18 523.34 moveto +623.18 503.09 lineto stroke +restore +% S_BAR +138 linenum +0.70 setlinewidth +666.78 620.34 moveto +666.78 509.09 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +139 linenum +/Times-Roman findfont +12 scalefont +setfont +674.29 564.62 moveto +(proof) show +/Times-Roman findfont +12 scalefont +setfont +723.20 564.62 moveto +(through) show +/Times-Roman findfont +12 scalefont +setfont +769.65 564.62 moveto +(the) show +680.75 611.34 1.000000 4n +690.01 611.34 1.000000 dot +684.43 612.09 moveto +684.43 632.34 lineto stroke +732.49 608.34 1.000000 4n +736.17 609.09 moveto +736.17 629.34 lineto stroke +739.20 629.34 1.000000 dnflag +773.30 605.34 1.000000 4n +776.99 606.09 moveto +776.99 626.34 lineto stroke +680.75 596.34 1.000000 4n +690.01 593.34 1.000000 dot +677.07 595.59 moveto +677.07 575.34 lineto stroke +732.49 596.34 1.000000 4n +728.81 595.59 moveto +728.81 575.34 lineto stroke +731.83 575.34 1.000000 upflag +773.30 596.34 1.000000 4n +769.62 595.59 moveto +769.62 575.34 lineto stroke +restore +% S_STAFF +% staff 2 +save +680.75 533.09 1.000000 4n +690.01 536.09 1.000000 dot +0.70 setlinewidth +684.43 533.84 moveto +684.43 554.09 lineto stroke +732.49 530.09 1.000000 4n +736.17 530.84 moveto +736.17 551.09 lineto stroke +739.20 551.09 1.000000 dnflag +773.30 533.09 1.000000 4n +776.99 533.84 moveto +776.99 554.09 lineto stroke +680.75 512.09 1.000000 4n +690.01 512.09 1.000000 dot +677.07 511.34 moveto +677.07 491.09 lineto stroke +732.49 515.09 1.000000 4n +728.81 514.34 moveto +728.81 494.09 lineto stroke +731.83 494.09 1.000000 upflag +773.30 518.09 1.000000 4n +769.62 517.34 moveto +769.62 497.09 lineto stroke +restore +% S_BAR +142 linenum +0.70 setlinewidth +812.22 620.34 moveto +812.22 509.09 lineto stroke +% S_FEED +215.71 941.09 812.57 5 1.000000 1.000000 stf +/Times-Roman findfont +11 scalefont +setfont +76.21 463.09 moveto +(15) show +215.71 844.77 812.57 5 1.000000 1.000000 stf +71.21 449.09 328.77 brace +71.71 449.09 moveto +71.71 328.77 lineto stroke +% S_CLEFSIG +83.51 431.09 1.000000 gclef +83.76 346.77 1.000000 fclef +98.12 449.09 1.000000 sharp +104.76 440.09 1.000000 sharp +111.40 452.09 1.000000 sharp +98.12 346.77 1.000000 sharp +104.76 337.77 1.000000 sharp +111.40 349.77 1.000000 sharp +% S_CHHEAD +% S_STAFF +% staff 1 +save +143 linenum +/Times-Roman findfont +12 scalefont +setfont +134.40 381.37 moveto +(night) show +/Times-Roman findfont +12 scalefont +setfont +202.88 381.37 moveto +(that) show +/Times-Roman findfont +12 scalefont +setfont +234.86 381.37 moveto +(our) show +140.54 431.09 1.000000 2n +144.44 431.84 moveto +144.44 452.09 lineto stroke +207.36 428.09 1.000000 4n +216.62 428.09 1.000000 dot +211.04 428.84 moveto +211.04 447.97 lineto stroke +238.84 431.09 1.000000 4n +242.52 431.84 moveto +242.52 450.97 lineto stroke +newpath +210.69 449.47 moveto +242.87 452.47 lineto +242.87 449.47 lineto +210.69 446.47 lineto +closepath +fill +newpath +242.17 447.47 moveto +234.11 446.70 lineto +234.11 443.70 lineto +242.17 444.47 lineto +closepath +fill +140.54 425.09 1.000000 2n +136.64 424.34 moveto +136.64 404.09 lineto stroke +207.36 422.09 1.000000 4n +216.62 422.09 1.000000 dot +203.68 421.34 moveto +203.68 402.59 lineto stroke +238.84 422.09 1.000000 4n +235.16 421.34 moveto +235.16 402.59 lineto stroke +newpath +203.33 404.09 moveto +235.51 404.09 lineto +235.51 401.09 lineto +203.33 401.09 lineto +closepath +fill +newpath +234.81 409.09 moveto +226.74 409.09 lineto +226.74 406.09 lineto +234.81 406.09 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +140.54 355.77 1.000000 2n +0.70 setlinewidth +144.44 356.52 moveto +144.44 376.77 lineto stroke +207.36 355.77 1.000000 4n +216.62 355.77 1.000000 dot +211.04 356.52 moveto +211.04 375.27 lineto stroke +238.84 355.77 1.000000 4n +242.52 356.52 moveto +242.52 375.27 lineto stroke +newpath +210.69 376.77 moveto +242.87 376.77 lineto +242.87 373.77 lineto +210.69 373.77 lineto +closepath +fill +newpath +242.17 371.77 moveto +234.11 371.77 lineto +234.11 368.77 lineto +242.17 368.77 lineto +closepath +fill +140.54 343.77 1.000000 2n +136.64 343.02 moveto +136.64 322.77 lineto stroke +207.36 343.77 1.000000 4n +216.62 343.77 1.000000 dot +203.68 343.02 moveto +203.68 324.27 lineto stroke +238.84 343.77 1.000000 4n +235.16 343.02 moveto +235.16 324.27 lineto stroke +newpath +203.33 325.77 moveto +235.51 325.77 lineto +235.51 322.77 lineto +203.33 322.77 lineto +closepath +fill +newpath +234.81 330.77 moveto +226.74 330.77 lineto +226.74 327.77 lineto +234.81 327.77 lineto +closepath +fill +restore +% S_BAR +146 linenum +0.70 setlinewidth +255.78 449.09 moveto +255.78 328.77 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +147 linenum +/Times-Roman findfont +12 scalefont +setfont +262.95 381.37 moveto +(flag) show +/Times-Roman findfont +12 scalefont +setfont +303.16 381.37 moveto +(was) show +/Times-Roman findfont +12 scalefont +setfont +347.89 381.37 moveto +(still) show +267.60 434.09 1.000000 4n +271.28 434.84 moveto +271.28 455.09 lineto stroke +307.83 419.09 1.000000 4n +301.59 419.09 moveto +314.06 419.09 lineto stroke +311.51 419.84 moveto +311.51 440.09 lineto stroke +352.38 422.09 1.000000 4n +343.02 422.09 1.000000 sharp +356.06 422.84 moveto +356.06 443.09 lineto stroke +267.60 419.09 1.000000 4n +261.37 419.09 moveto +273.83 419.09 lineto stroke +263.92 418.34 moveto +263.92 398.09 lineto stroke +307.83 419.09 1.000000 4n +301.59 419.09 moveto +314.06 419.09 lineto stroke +304.14 418.34 moveto +304.14 398.09 lineto stroke +352.38 416.09 1.000000 4n +346.14 419.09 moveto +358.61 419.09 lineto stroke +348.69 415.34 moveto +348.69 395.09 lineto stroke +restore +% S_STAFF +% staff 2 +save +267.60 352.77 1.000000 4n +0.70 setlinewidth +271.28 353.52 moveto +271.28 373.77 lineto stroke +307.83 352.77 1.000000 4n +311.51 353.52 moveto +311.51 373.77 lineto stroke +352.38 352.77 1.000000 4n +356.06 353.52 moveto +356.06 373.77 lineto stroke +267.60 346.77 1.000000 4n +263.92 346.02 moveto +263.92 325.77 lineto stroke +307.83 346.77 1.000000 4n +304.14 346.02 moveto +304.14 325.77 lineto stroke +352.38 334.77 1.000000 4n +348.69 334.02 moveto +348.69 313.77 lineto stroke +restore +% S_BAR +150 linenum +0.70 setlinewidth +392.85 449.09 moveto +392.85 328.77 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +151 linenum +/Times-Roman findfont +12 scalefont +setfont +400.10 381.37 moveto +(there.) show +/Times-Roman findfont +12 scalefont +setfont +487.90 381.37 moveto +(Oh) show +406.84 425.09 1.000000 4n +410.52 425.84 moveto +410.52 446.09 lineto stroke +450.19 449.09 1.000000 4rest +491.56 425.09 1.000000 4n +495.24 425.84 moveto +495.24 446.09 lineto stroke +406.84 416.09 1.000000 4n +400.60 419.09 moveto +413.07 419.09 lineto stroke +403.15 415.34 moveto +403.15 395.09 lineto stroke +450.19 407.09 1.000000 4rest +491.56 416.09 1.000000 4n +485.32 419.09 moveto +497.79 419.09 lineto stroke +487.87 415.34 moveto +487.87 395.09 lineto stroke +restore +% S_STAFF +% staff 2 +save +406.84 349.77 1.000000 4n +0.70 setlinewidth +410.52 350.52 moveto +410.52 370.77 lineto stroke +450.19 358.77 1.000000 4rest +491.56 349.77 1.000000 4n +495.24 350.52 moveto +495.24 370.77 lineto stroke +406.84 343.77 1.000000 4n +403.15 343.02 moveto +403.15 322.77 lineto stroke +450.19 328.77 1.000000 4rest +491.56 343.77 1.000000 4n +487.87 343.02 moveto +487.87 322.77 lineto stroke +restore +% S_BAR +154 linenum +0.70 setlinewidth +531.61 449.09 moveto +531.61 328.77 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +155 linenum +/Times-Roman findfont +12 scalefont +setfont +538.55 381.37 moveto +(say,) show +/Times-Roman findfont +12 scalefont +setfont +579.19 381.37 moveto +(does) show +/Times-Roman findfont +12 scalefont +setfont +619.89 381.37 moveto +(that) show +543.30 434.09 1.000000 4n +546.98 434.84 moveto +546.98 455.09 lineto stroke +584.68 434.09 1.000000 4n +588.37 434.84 moveto +588.37 455.09 lineto stroke +624.37 434.09 1.000000 4n +628.06 434.84 moveto +628.06 453.13 lineto stroke +650.59 431.09 1.000000 4n +654.27 431.84 moveto +654.27 450.13 lineto stroke +newpath +627.71 454.63 moveto +654.62 451.63 lineto +654.62 448.63 lineto +627.71 451.63 lineto +closepath +fill +543.30 419.09 1.000000 4n +537.07 419.09 moveto +549.53 419.09 lineto stroke +539.62 418.34 moveto +539.62 398.09 lineto stroke +584.68 416.09 1.000000 4n +578.45 419.09 moveto +590.92 419.09 lineto stroke +581.00 415.34 moveto +581.00 395.09 lineto stroke +624.37 413.09 1.000000 4n +618.14 413.09 moveto +630.61 413.09 lineto stroke +618.14 419.09 moveto +630.61 419.09 lineto stroke +620.69 412.34 moveto +620.69 392.09 lineto stroke +630.41 439.19 moveto +630.38 439.42 lineto +633.76 441.00 637.30 441.52 640.99 440.97 curveto +644.68 440.42 647.91 438.90 650.68 436.40 curveto +650.50 435.97 lineto +647.55 437.96 644.32 439.22 640.80 439.74 curveto +637.29 440.27 633.83 440.00 630.43 438.96 curveto +fill +restore +% S_STAFF +% staff 2 +save +543.30 343.77 1.000000 4n +0.70 setlinewidth +546.98 344.52 moveto +546.98 364.77 lineto stroke +584.68 343.77 1.000000 4n +588.37 344.52 moveto +588.37 364.77 lineto stroke +624.37 343.77 1.000000 4n +628.06 344.52 moveto +628.06 364.77 lineto stroke +543.30 331.77 1.000000 4n +539.62 331.02 moveto +539.62 310.77 lineto stroke +584.68 334.77 1.000000 4n +581.00 334.02 moveto +581.00 313.77 lineto stroke +624.37 337.77 1.000000 4n +620.69 337.02 moveto +620.69 316.77 lineto stroke +restore +% S_BAR +161 linenum +0.70 setlinewidth +674.88 449.09 moveto +674.88 328.77 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +162 linenum +/Times-Roman findfont +12 scalefont +setfont +708.09 381.37 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +681.59 381.37 moveto +(star) show +/Times-Roman findfont +12 scalefont +setfont +752.77 381.37 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +720.31 381.37 moveto +(span) show +/Times-Roman findfont +12 scalefont +setfont +766.27 381.37 moveto +(gled) show +686.90 428.09 1.000000 4n +690.58 428.84 moveto +690.58 449.09 lineto stroke +726.79 428.09 1.000000 4n +730.48 428.84 moveto +730.48 449.09 lineto stroke +767.73 428.09 1.000000 4n +771.42 428.84 moveto +771.42 449.09 lineto stroke +686.90 422.09 1.000000 4n +683.22 421.34 moveto +683.22 401.09 lineto stroke +726.79 422.09 1.000000 4n +723.11 421.34 moveto +723.11 401.09 lineto stroke +775.10 425.09 1.000000 4n +771.42 424.34 moveto +771.42 404.09 lineto stroke +restore +% S_STAFF +% staff 2 +save +686.90 352.77 1.000000 4n +0.70 setlinewidth +690.58 353.52 moveto +690.58 373.77 lineto stroke +726.79 352.77 1.000000 4n +730.48 353.52 moveto +730.48 373.77 lineto stroke +771.42 352.77 1.000000 4n +762.06 352.77 1.000000 sharp +775.10 353.52 moveto +775.10 373.77 lineto stroke +686.90 340.77 1.000000 4n +683.22 340.02 moveto +683.22 319.77 lineto stroke +726.79 340.77 1.000000 4n +723.11 340.02 moveto +723.11 319.77 lineto stroke +771.42 337.77 1.000000 4n +767.73 337.02 moveto +767.73 316.77 lineto stroke +restore +% S_BAR +168 linenum +0.70 setlinewidth +812.22 449.09 moveto +812.22 328.77 lineto stroke +% S_FEED +215.71 760.77 812.57 5 1.000000 1.000000 stf +/Times-Roman findfont +11 scalefont +setfont +76.21 282.77 moveto +(20) show +215.71 658.50 812.57 5 1.000000 1.000000 stf +71.21 268.77 142.50 brace +71.71 268.77 moveto +71.71 142.50 lineto stroke +% S_CLEFSIG +83.51 250.77 1.000000 gclef +83.76 160.50 1.000000 fclef +98.12 268.77 1.000000 sharp +104.76 259.77 1.000000 sharp +111.40 271.77 1.000000 sharp +98.12 160.50 1.000000 sharp +104.76 151.50 1.000000 sharp +111.40 163.50 1.000000 sharp +% S_CHHEAD +% S_STAFF +% staff 1 +save +169 linenum +/Times-Roman findfont +12 scalefont +setfont +151.54 207.05 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +128.56 207.05 moveto +(ban) show +/Times-Roman findfont +12 scalefont +setfont +160.23 207.05 moveto +(ner) show +/Times-Roman findfont +12 scalefont +setfont +206.13 207.05 moveto +(yet) show +133.87 256.77 1.000000 4n +137.56 257.52 moveto +137.56 277.77 lineto stroke +164.05 262.77 1.000000 4n +167.73 263.52 moveto +167.73 281.85 lineto stroke +192.78 259.77 1.000000 4n +196.46 260.52 moveto +196.46 278.85 lineto stroke +209.78 256.77 1.000000 4n +213.46 257.52 moveto +213.46 275.95 lineto stroke +247.99 253.77 1.000000 4n +251.67 254.52 moveto +251.67 272.95 lineto stroke +newpath +167.38 283.35 moveto +196.81 280.35 lineto +196.81 277.35 lineto +167.38 280.35 lineto +closepath +fill +newpath +213.11 277.45 moveto +252.02 274.45 lineto +252.02 271.45 lineto +213.11 274.45 lineto +closepath +fill +133.87 241.77 1.000000 4n +130.19 241.02 moveto +130.19 220.77 lineto stroke +164.05 247.77 1.000000 4n +160.37 247.02 moveto +160.37 226.77 lineto stroke +209.78 247.77 1.000000 4n +206.10 247.02 moveto +206.10 226.77 lineto stroke +215.81 261.87 moveto +215.80 262.07 lineto +221.16 263.65 226.63 264.19 232.21 263.67 curveto +237.78 263.15 243.06 261.61 248.04 259.06 curveto +247.94 258.68 lineto +242.84 260.68 237.55 261.94 232.09 262.45 curveto +226.63 262.96 221.21 262.70 215.83 261.67 curveto +fill +170.08 267.87 moveto +170.06 268.09 lineto +173.85 269.68 177.79 270.20 181.86 269.66 curveto +185.94 269.12 189.61 267.59 192.86 265.08 curveto +192.70 264.66 lineto +189.29 266.65 185.62 267.91 181.70 268.43 curveto +177.78 268.95 173.92 268.69 170.10 267.64 curveto +fill +restore +% S_STAFF +% staff 2 +save +133.87 169.50 1.000000 4n +0.70 setlinewidth +137.56 170.25 moveto +137.56 190.50 lineto stroke +164.05 169.50 1.000000 4n +167.73 170.25 moveto +167.73 188.57 lineto stroke +192.78 166.50 1.000000 4n +183.43 166.50 1.000000 sharp +196.46 167.25 moveto +196.46 185.57 lineto stroke +209.78 169.50 1.000000 4n +213.46 170.25 moveto +213.46 189.00 lineto stroke +247.99 169.50 1.000000 4n +238.64 169.50 1.000000 sharp +251.67 170.25 moveto +251.67 189.00 lineto stroke +newpath +167.38 190.07 moveto +196.81 187.07 lineto +196.81 184.07 lineto +167.38 187.07 lineto +closepath +fill +newpath +213.11 190.50 moveto +252.02 190.50 lineto +252.02 187.50 lineto +213.11 187.50 lineto +closepath +fill +133.87 148.50 1.000000 4n +130.19 147.75 moveto +130.19 127.50 lineto stroke +164.05 148.50 1.000000 4n +160.37 147.75 moveto +160.37 128.57 lineto stroke +192.78 151.50 1.000000 4n +189.10 150.75 moveto +189.10 131.57 lineto stroke +209.78 154.50 1.000000 4n +206.10 153.75 moveto +206.10 135.00 lineto stroke +247.99 154.50 1.000000 4n +230.00 154.50 1.000000 sharp +244.31 153.75 moveto +244.31 135.00 lineto stroke +newpath +160.02 130.07 moveto +189.45 133.07 lineto +189.45 130.07 lineto +160.02 127.07 lineto +closepath +fill +newpath +205.75 136.50 moveto +244.66 136.50 lineto +244.66 133.50 lineto +205.75 133.50 lineto +closepath +fill +209.78 149.40 moveto +209.87 149.63 lineto +211.90 148.09 214.18 147.32 216.73 147.32 curveto +219.27 147.32 221.56 148.09 223.59 149.63 curveto +223.77 149.16 lineto +221.87 147.10 219.53 146.07 216.73 146.07 curveto +213.93 146.07 211.58 147.10 209.69 149.16 curveto +fill +164.05 143.40 moveto +164.07 143.62 lineto +167.72 142.58 171.42 142.32 175.18 142.84 curveto +178.94 143.36 182.43 144.61 185.66 146.61 curveto +185.83 146.18 lineto +182.77 143.67 179.27 142.15 175.35 141.61 curveto +171.43 141.07 167.65 141.59 164.02 143.17 curveto +fill +215.81 174.60 moveto +215.78 174.79 lineto +220.95 176.87 226.33 177.91 231.90 177.91 curveto +237.48 177.91 242.85 176.87 248.02 174.79 curveto +247.96 174.40 lineto +242.71 175.92 237.36 176.68 231.90 176.68 curveto +226.44 176.68 221.09 175.92 215.84 174.40 curveto +fill +170.08 174.60 moveto +170.06 174.82 lineto +173.85 176.40 177.79 176.93 181.86 176.39 curveto +185.94 175.85 189.61 174.32 192.86 171.81 curveto +192.70 171.38 lineto +189.29 173.38 185.62 174.64 181.70 175.16 curveto +177.78 175.68 173.92 175.41 170.10 174.37 curveto +fill +restore +% S_BAR +175 linenum +0.70 setlinewidth +267.65 268.77 moveto +267.65 142.50 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +177 linenum +/Times-Roman findfont +12 scalefont +setfont +273.37 207.05 moveto +(wave) show +/Times-Roman findfont +12 scalefont +setfont +342.95 207.05 moveto +(o'er) show +/Times-Roman findfont +12 scalefont +setfont +367.81 207.05 moveto +(the) show +281.18 253.77 1.000000 4n +284.86 254.52 moveto +284.86 274.77 lineto stroke +311.60 250.77 1.000000 4n +315.28 251.52 moveto +315.28 271.77 lineto stroke +318.31 271.77 1.000000 dnflag +330.83 268.77 1.000000 8rest +347.75 244.77 1.000000 4n +351.44 245.52 moveto +351.44 264.27 lineto stroke +371.47 244.77 1.000000 4n +375.15 245.52 moveto +375.15 264.27 lineto stroke +newpath +351.09 265.77 moveto +375.50 265.77 lineto +375.50 262.77 lineto +351.09 262.77 lineto +closepath +fill +281.18 244.77 1.000000 4n +290.45 241.77 1.000000 dot +277.50 244.02 moveto +277.50 223.77 lineto stroke +330.83 226.77 1.000000 8rest +347.75 244.77 1.000000 4n +344.07 244.02 moveto +344.07 225.27 lineto stroke +371.47 244.77 1.000000 4n +367.78 244.02 moveto +367.78 225.27 lineto stroke +newpath +343.72 226.77 moveto +368.13 226.77 lineto +368.13 223.77 lineto +343.72 223.77 lineto +closepath +fill +287.21 258.87 moveto +287.19 259.09 lineto +291.27 260.67 295.47 261.19 299.81 260.66 curveto +304.15 260.13 308.10 258.60 311.67 256.08 curveto +311.53 255.66 lineto +307.81 257.66 303.85 258.92 299.66 259.43 curveto +295.47 259.95 291.33 259.69 287.23 258.65 curveto +fill +/Times-Roman findfont +12 scalefont +setfont +302.57 273.78 moveto +311.60 273.78 1.000000 ferm +320.64 273.78 moveto +restore +% S_STAFF +% staff 2 +save +281.18 172.50 1.000000 4n +0.70 setlinewidth +274.95 172.50 moveto +287.41 172.50 lineto stroke +284.86 173.25 moveto +284.86 193.50 lineto stroke +311.60 169.50 1.000000 4n +315.28 170.25 moveto +315.28 190.50 lineto stroke +318.31 190.50 1.000000 dnflag +330.83 172.50 1.000000 8rest +347.75 163.50 1.000000 4n +351.44 164.25 moveto +351.44 183.00 lineto stroke +371.47 163.50 1.000000 4n +375.15 164.25 moveto +375.15 183.00 lineto stroke +newpath +351.09 184.50 moveto +375.50 184.50 lineto +375.50 181.50 lineto +351.09 181.50 lineto +closepath +fill +281.18 157.50 1.000000 4n +290.45 157.50 1.000000 dot +277.50 156.75 moveto +277.50 136.50 lineto stroke +330.83 142.50 1.000000 8rest +347.75 154.50 1.000000 4n +344.07 153.75 moveto +344.07 135.00 lineto stroke +371.47 154.50 1.000000 4n +367.78 153.75 moveto +367.78 135.00 lineto stroke +newpath +343.72 136.50 moveto +368.13 136.50 lineto +368.13 133.50 lineto +343.72 133.50 lineto +closepath +fill +287.21 177.60 moveto +287.19 177.82 lineto +291.27 179.40 295.47 179.92 299.81 179.39 curveto +304.15 178.86 308.10 177.33 311.67 174.80 curveto +311.53 174.39 lineto +307.81 176.39 303.85 177.65 299.66 178.16 curveto +295.47 178.68 291.33 178.42 287.23 177.38 curveto +fill +/Times-Roman findfont +12 scalefont +setfont +302.57 192.50 moveto +311.60 192.50 1.000000 ferm +320.64 192.50 moveto +restore +% S_BAR +183 linenum +0.70 setlinewidth +392.12 268.77 moveto +392.12 142.50 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +184 linenum +425.08 207.05 moveto +451.12 207.05 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +398.51 207.05 moveto +(land) show +/Times-Roman findfont +12 scalefont +setfont +462.92 207.05 moveto +(of) show +/Times-Roman findfont +12 scalefont +setfont +480.90 207.05 moveto +(the) show +405.15 253.77 1.000000 4n +414.41 253.77 1.000000 dot +408.83 254.52 moveto +408.83 274.77 lineto stroke +447.09 256.77 1.000000 4n +450.77 257.52 moveto +450.77 277.77 lineto stroke +453.79 277.77 1.000000 dnflag +465.41 259.77 1.000000 4n +469.09 260.52 moveto +469.09 279.90 lineto stroke +484.55 262.77 1.000000 4n +488.24 263.52 moveto +488.24 282.90 lineto stroke +newpath +468.74 281.40 moveto +488.59 284.40 lineto +488.59 281.40 lineto +468.74 278.40 lineto +closepath +fill +405.15 244.77 1.000000 4n +414.41 241.77 1.000000 dot +401.47 244.02 moveto +401.47 223.77 lineto stroke +447.09 244.77 1.000000 4n +443.40 244.02 moveto +443.40 223.77 lineto stroke +446.43 223.77 1.000000 upflag +465.41 244.77 1.000000 4n +461.73 244.02 moveto +461.73 225.27 lineto stroke +484.55 244.77 1.000000 4n +480.87 244.02 moveto +480.87 225.27 lineto stroke +newpath +461.38 226.77 moveto +481.22 226.77 lineto +481.22 223.77 lineto +461.38 223.77 lineto +closepath +fill +405.15 239.67 moveto +405.18 239.86 lineto +410.89 238.34 416.69 237.58 422.60 237.58 curveto +428.51 237.58 434.32 238.34 440.03 239.86 curveto +440.08 239.48 lineto +434.44 237.40 428.61 236.36 422.60 236.36 curveto +416.59 236.36 410.76 237.40 405.12 239.48 curveto +fill +419.41 258.87 moveto +419.35 259.07 lineto +423.52 261.61 428.04 263.14 432.89 263.66 curveto +437.75 264.19 442.48 263.66 447.10 262.08 curveto +447.07 261.66 lineto +442.43 262.69 437.75 262.95 433.03 262.44 curveto +428.30 261.93 423.78 260.67 419.48 258.67 curveto +fill +restore +% S_STAFF +% staff 2 +save +405.15 166.50 1.000000 4n +414.41 169.50 1.000000 dot +0.70 setlinewidth +408.83 167.25 moveto +408.83 187.50 lineto stroke +447.09 163.50 1.000000 4n +450.77 164.25 moveto +450.77 184.50 lineto stroke +453.79 184.50 1.000000 dnflag +465.41 166.50 1.000000 4n +469.09 167.25 moveto +469.09 186.00 lineto stroke +484.55 166.50 1.000000 4n +488.24 167.25 moveto +488.24 186.00 lineto stroke +newpath +468.74 187.50 moveto +488.59 187.50 lineto +488.59 184.50 lineto +468.74 184.50 lineto +closepath +fill +405.15 151.50 1.000000 4n +414.41 151.50 1.000000 dot +401.47 150.75 moveto +401.47 130.50 lineto stroke +447.09 157.50 1.000000 4n +443.40 156.75 moveto +443.40 136.50 lineto stroke +446.43 136.50 1.000000 upflag +465.41 145.50 1.000000 4n +461.73 144.75 moveto +461.73 125.36 lineto stroke +484.55 148.50 1.000000 4n +480.87 147.75 moveto +480.87 128.36 lineto stroke +newpath +461.38 126.86 moveto +481.22 129.86 lineto +481.22 126.86 lineto +461.38 123.86 lineto +closepath +fill +405.15 146.40 moveto +405.15 146.58 lineto +411.11 146.07 417.05 146.32 422.96 147.34 curveto +428.86 148.35 434.54 150.10 439.99 152.57 curveto +440.11 152.22 lineto +434.82 149.19 429.17 147.17 423.16 146.13 curveto +417.15 145.10 411.15 145.13 405.15 146.21 curveto +fill +419.41 171.60 moveto +419.40 171.81 lineto +424.02 173.39 428.75 173.92 433.61 173.39 curveto +438.46 172.87 442.98 171.33 447.15 168.80 curveto +447.02 168.39 lineto +442.72 170.40 438.20 171.66 433.47 172.17 curveto +428.75 172.68 424.07 172.42 419.43 171.39 curveto +fill +restore +% S_BAR +190 linenum +0.70 setlinewidth +505.20 268.77 moveto +505.20 142.50 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +192 linenum +/Times-Roman findfont +12 scalefont +setfont +512.28 207.05 moveto +(free) show +/Times-Roman findfont +12 scalefont +setfont +573.45 207.05 moveto +(and) show +/Times-Roman findfont +12 scalefont +setfont +603.21 207.05 moveto +(the) show +516.92 265.77 1.000000 4n +520.61 266.52 moveto +520.61 286.77 lineto stroke +549.57 268.77 1.000000 4rest +577.77 253.77 1.000000 4n +581.45 254.52 moveto +581.45 273.68 lineto stroke +606.86 256.77 1.000000 4n +610.54 257.52 moveto +610.54 276.68 lineto stroke +newpath +581.10 275.18 moveto +610.89 278.18 lineto +610.89 275.18 lineto +581.10 272.18 lineto +closepath +fill +516.92 244.77 1.000000 4n +513.24 244.02 moveto +513.24 223.77 lineto stroke +549.57 238.77 1.000000 4rest +577.77 241.77 1.000000 4n +574.08 241.02 moveto +574.08 222.27 lineto stroke +606.86 241.77 1.000000 4n +603.18 241.02 moveto +603.18 222.27 lineto stroke +newpath +573.73 223.77 moveto +603.53 223.77 lineto +603.53 220.77 lineto +573.73 220.77 lineto +closepath +fill +/Times-Roman findfont +12 scalefont +setfont +507.89 288.78 moveto +516.92 288.78 1.000000 ferm +525.96 288.78 moveto +restore +% S_STAFF +% staff 2 +save +516.92 166.50 1.000000 4n +0.70 setlinewidth +520.61 167.25 moveto +520.61 187.50 lineto stroke +549.57 178.50 1.000000 4rest +577.77 166.50 1.000000 4n +581.45 167.25 moveto +581.45 186.00 lineto stroke +606.86 166.50 1.000000 4n +610.54 167.25 moveto +610.54 186.00 lineto stroke +newpath +581.10 187.50 moveto +610.89 187.50 lineto +610.89 184.50 lineto +581.10 184.50 lineto +closepath +fill +516.92 151.50 1.000000 4n +513.24 150.75 moveto +513.24 130.50 lineto stroke +549.57 142.50 1.000000 4rest +577.77 160.50 1.000000 4n +574.08 159.75 moveto +574.08 141.00 lineto stroke +606.86 160.50 1.000000 4n +598.41 160.50 1.000000 nat +603.18 159.75 moveto +603.18 141.00 lineto stroke +newpath +573.73 142.50 moveto +603.53 142.50 lineto +603.53 139.50 lineto +573.73 139.50 lineto +closepath +fill +/Times-Roman findfont +12 scalefont +setfont +507.89 189.50 moveto +516.92 189.50 1.000000 ferm +525.96 189.50 moveto +restore +% S_BAR +198 linenum +0.70 setlinewidth +627.51 268.77 moveto +627.51 142.50 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +199 linenum +/Times-Roman findfont +12 scalefont +setfont +633.72 207.05 moveto +(home) show +/Times-Roman findfont +12 scalefont +setfont +679.95 207.05 moveto +(of) show +/Times-Roman findfont +12 scalefont +setfont +700.20 207.05 moveto +(the) show +640.38 259.77 1.000000 4n +649.64 259.77 1.000000 dot +644.06 260.52 moveto +644.06 280.77 lineto stroke +682.43 262.77 1.000000 4n +686.11 263.52 moveto +686.11 283.77 lineto stroke +689.14 283.77 1.000000 dnflag +703.85 256.77 1.000000 4n +707.53 257.52 moveto +707.53 277.77 lineto stroke +640.38 244.77 1.000000 4n +649.64 241.77 1.000000 dot +636.70 244.02 moveto +636.70 223.77 lineto stroke +682.43 244.77 1.000000 4n +678.75 244.02 moveto +678.75 223.77 lineto stroke +681.77 223.77 1.000000 upflag +703.85 241.77 1.000000 4n +700.17 241.02 moveto +700.17 220.77 lineto stroke +restore +% S_STAFF +% staff 2 +save +640.38 166.50 1.000000 4n +649.64 169.50 1.000000 dot +0.70 setlinewidth +644.06 167.25 moveto +644.06 187.50 lineto stroke +682.43 166.50 1.000000 4n +686.11 167.25 moveto +686.11 187.50 lineto stroke +689.14 187.50 1.000000 dnflag +703.85 163.50 1.000000 4n +707.53 164.25 moveto +707.53 184.50 lineto stroke +640.38 157.50 1.000000 4n +649.64 157.50 1.000000 dot +636.70 156.75 moveto +636.70 136.50 lineto stroke +682.43 157.50 1.000000 4n +678.75 156.75 moveto +678.75 136.50 lineto stroke +681.77 136.50 1.000000 upflag +703.85 157.50 1.000000 4n +700.17 156.75 moveto +700.17 136.50 lineto stroke +restore +% S_BAR +205 linenum +0.70 setlinewidth +735.86 268.77 moveto +735.86 142.50 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +206 linenum +/Times-Roman findfont +12 scalefont +setfont +744.15 207.05 moveto +(brave?) show +752.13 253.77 1.000000 2n +756.03 254.52 moveto +756.03 274.77 lineto stroke +752.13 238.77 1.000000 2n +745.68 238.77 moveto +758.58 238.77 lineto stroke +748.23 238.02 moveto +748.23 217.77 lineto stroke +restore +% S_STAFF +% staff 2 +save +752.13 157.50 1.000000 2n +0.70 setlinewidth +756.03 158.25 moveto +756.03 178.50 lineto stroke +752.13 145.50 1.000000 2n +748.23 144.75 moveto +748.23 124.50 lineto stroke +restore +% S_BAR +211 linenum +0.70 setlinewidth +807.07 268.77 moveto +807.07 142.50 lineto stroke +3.00 setlinewidth +811.07 268.77 moveto +811.07 142.50 lineto stroke +0.70 setlinewidth +% Printing header/footer +/Times-Roman findfont +18 scalefont +setfont +342.53 1065.42 moveto +(The Star Spangled Banner) show +/Times-Italic findfont +12 scalefont +setfont +348.37 1052.60 moveto +(\(The United States National Anthem\)) show +/Times-Roman findfont +9 scalefont +setfont +61.71 1042.99 moveto +(Text: Francis Scott Key) show +/Times-Roman findfont +9 scalefont +setfont +750.26 1042.99 moveto +(Tune: J. S. Smith) show +/Times-Roman findfont +9 scalefont +setfont +61.71 1033.38 moveto +/Times-Roman findfont +9 scalefont +setfont +733.19 1033.38 moveto +(arr: William J. Krauss) show +showpage +restore +%%Trailer +%%DocumentFonts: /Times-Roman /Times-Italic /NewCenturySchlbk-Bold +%%Pages: 1 diff --git a/mup/docs/template.mup b/mup/docs/template.mup new file mode 100644 index 0000000..aa12d23 --- /dev/null +++ b/mup/docs/template.mup @@ -0,0 +1,142 @@ +//!Mup-Arkkra +// This is a Mup input file template. +// Lines starting with // are "comments" that are here for your benefit. +// You can remove them without affecting the output. + +///////////////////////////////////////////////////////////////////////// +// things to go on the top of the first page +top + + // centered title. + // The number in parentheses is the text point size. + // Make it bigger if you want a bigger title or smaller if you + // want a smaller title + title (18) "Replace this with the title of your song" + + // subtitle + // If you want a subtitle, remove the // from the beginning + // of the next line and fill in the appropriate subtitle text + // title (14) "Replace this with the subtitle" + + // composer info + // The first pair of double quotes enclose what to left justify, + // the second encloses what to right justify. + // If you want more than one line, add similar lines of input + title "" "Replace this with composer info" + + +///////////////////////////////////////////////////////////////////////// +// things to go on the bottom on the first page +bottom + // If you want a copyright notice, remove the // + // from the next line and edit in the appropriate information + // title "\(copyright) Copyright Replace this with year and name" + + +///////////////////////////////////////////////////////////////////////// +// things to go on the top of pages other than the first +top2 + // This example will give a centered page number between dashes. + // You can customize as you wish. + title "- \% -" + + +///////////////////////////////////////////////////////////////////////// +// things to go at the bottom of pages other than the first +bottom2 + // if you want things printed at the bottom of pages of than + // the first page, place them here + + +///////////////////////////////////////////////////////////////////////// +// score-wide parameters +// +// You may or may not need to change some items in this section +// +// The values given as examples are the default values that Mup uses +// if you don't specify anything for them +score + // time signature. Can be cut, com, + // or two numbers with a / between them + time = 4/4 + + // key signature. Value is a number from 0 to 7 + // followed by # or & for number of sharps or flats. + key = 0# + + // how many staffs. Can be a number from 1 to 40 + staffs = 1 + + // clef. Can be treble, treble8, 8treble, frenchviolin, + // soprano, mezzosoprano, alto, tenor, baritone, or bass + clef = treble + + // Note: there are many more parameters that can be set, + // but they are not included in this simple template. + // There are parameters to set margins, control how things + // are laid out on the page, transpositions value, font and size + // for text and lyrics, etc + + +///////////////////////////////////////////////////////////////////////// +// You can set some parameters for specific staffs, +// to override the score-wide parameters. For example, +// if you specify staffs = 2 in the score-wide parameters above, +// and want to use bass clef on staff 2, even though the score-wide +// clef parameter is set to treble, you can do +// staff 2 +// clef = bass + + +///////////////////////////////////////////////////////////////////////// +// music input starts here +music + + +// For each measure, you enter one line of input for each staff, +// then indicate what kind of barline to print. +// The following specifies that staff 1 contains a measure of rest +// and that an ordinary bar line is to be used at the end of the measure. + +1: mr; +bar + +// Usually, a measure of input for one staff consists of one or more chords +// Each chord is specified by +// time_value notes ; +// where time_value is something like +// 4 for a quarter note +// 8 for an eighth note +// 4. for a dotted-quarter note +// etc and notes is a list of one or more notes, specified as a pitch from +// a to g, optionally followed by an accidental (#, &, x, &&, or n for sharp, +// flat, double sharp, double flat, or natural respectively). +// Examples: +// 4c; +// 2. ceg; +// 16 f#; +// 1 d b&; +// (Spaces are optional, you can put them in if you want, but don't have to) +// +// So a complete measure might look something like: +// 1: 4e; 4d; 2c; +// bar +// +// If you want a note in a different octave than the default octave +// (the octave from middle-C up for treble clef, +// or the octave below middle-C for bass clef), +// you can add a + for each octave to go up or - for each octave to go down. +// For example: +// 1: c+; gc+e+; a&-; f#---; +// +// There are many other things you can specify, such as ties, slurs, grace +// notes, etc, and there are also many shortcuts you can use to save typing. +// Consult the Mup documentation for more details. + +// Other bar types you may want to use are +// repeatstart +// repeatend +// repeatboth +// dblbar +// endbar +// invisbar diff --git a/mup/docs/uguide.ps b/mup/docs/uguide.ps new file mode 100644 index 0000000..8bc10a7 --- /dev/null +++ b/mup/docs/uguide.ps @@ -0,0 +1,30255 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.17.2 +%%CreationDate: Mon Dec 4 22:55:33 2006 +%%DocumentNeededResources: font Times-BoldItalic +%%+ font Times-Roman +%%+ font Times-Bold +%%+ font Courier +%%+ font Times-Italic +%%+ font AvantGarde-Book +%%+ font AvantGarde-Demi +%%+ font AvantGarde-BookOblique +%%+ font AvantGarde-DemiOblique +%%+ font Bookman-Light +%%+ font Bookman-Demi +%%+ font Bookman-LightItalic +%%+ font Bookman-DemiItalic +%%+ font Courier-Bold +%%+ font Courier-Oblique +%%+ font Courier-BoldOblique +%%+ font Helvetica +%%+ font Helvetica-Bold +%%+ font Helvetica-Oblique +%%+ font Helvetica-BoldOblique +%%+ font NewCenturySchlbk-Roman +%%+ font NewCenturySchlbk-Bold +%%+ font NewCenturySchlbk-Italic +%%+ font NewCenturySchlbk-BoldItalic +%%+ font Palatino-Roman +%%+ font Palatino-Bold +%%+ font Palatino-Italic +%%+ font Palatino-BoldItalic +%%DocumentSuppliedResources: file mugex102.ps +%%+ file mugex101.ps +%%+ file mugex100.ps +%%+ file mugex99.ps +%%+ file mugex98.ps +%%+ file mugex97.ps +%%+ file mugex96.ps +%%+ file mugex95.ps +%%+ file mugex94.ps +%%+ file mugex93.ps +%%+ file mugex92.ps +%%+ file mugex91.ps +%%+ file mugex90.ps +%%+ file mugex89.ps +%%+ file mugex88.ps +%%+ file mugex87.ps +%%+ file mugex86.ps +%%+ file mugex85.ps +%%+ file mugex84.ps +%%+ file mugex83.ps +%%+ file mugex82.ps +%%+ file mugex81.ps +%%+ file mugex80.ps +%%+ file mugex79.ps +%%+ file mugex78.ps +%%+ file mugex77.ps +%%+ file mugex76.ps +%%+ file mugex75.ps +%%+ file mugex74.ps +%%+ file mugex73.ps +%%+ file mugex72.ps +%%+ file mugex71.ps +%%+ file mugex70.ps +%%+ file mugex69.ps +%%+ file mugex68.ps +%%+ file mugex67.ps +%%+ file mugex66.ps +%%+ file mugex65.ps +%%+ file extchar.ps +%%+ file muschar.ps +%%+ file mugex64.ps +%%+ file mugex63.ps +%%+ file mugex62.ps +%%+ file mugex61.ps +%%+ file mugex60.ps +%%+ file mugex59.ps +%%+ file mugex58.ps +%%+ file mugex57.ps +%%+ file mugex56.ps +%%+ file mugex55.ps +%%+ file mugex54.ps +%%+ file mugex53.ps +%%+ file mugex52.ps +%%+ file mugex51.ps +%%+ file mugex50.ps +%%+ file mugex49.ps +%%+ file mugex48.ps +%%+ file mugex47.ps +%%+ file mugex46.ps +%%+ file mugex45.ps +%%+ file mugex44.ps +%%+ file mugex43.ps +%%+ file mugex42.ps +%%+ file mugex41.ps +%%+ file mugex40.ps +%%+ file mugex39.ps +%%+ file mugex38.ps +%%+ file mugex37.ps +%%+ file mugex36.ps +%%+ file mugex35.ps +%%+ file mugex34.ps +%%+ file mugex33.ps +%%+ file mugex32.ps +%%+ file mugex31.ps +%%+ file mugex30.ps +%%+ file mugex29.ps +%%+ file mugex28.ps +%%+ file mugex27.ps +%%+ file mugex26.ps +%%+ file mugex25.ps +%%+ file mugex24.ps +%%+ file mugex23.ps +%%+ file mugex22.ps +%%+ file mugex21.ps +%%+ file mugex20.ps +%%+ file mugex19.ps +%%+ file mugex18.ps +%%+ file mugex17.ps +%%+ file mugex16.ps +%%+ file mugex15.ps +%%+ file mugex14.ps +%%+ file mugex13.ps +%%+ file mugex12.ps +%%+ file mugex11.ps +%%+ file mugex10.ps +%%+ file mugex9.ps +%%+ file mugex8.ps +%%+ file mugex7.ps +%%+ file mugex6.ps +%%+ file mugex5.ps +%%+ file mugex4.ps +%%+ file mugex3.ps +%%+ file mugex2.ps +%%+ file mugex1.ps +%%+ procset grops 1.17 2 +%%Pages: 172 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises +% All rights reserved + +% Mup PostScript Prolog 5.3 for use with Mup 5.3 + +% lwid is used as the width of a standard (thin) line in the music +% character definitions. +/lwid 70 def +/halflwid lwid 2 div def + +% Define the following for use in do_upshortnote, do_dnshortnote, and +% do_shortrest; it has to be done outside of the music font definition. +/utildict 10 dict def +utildict begin + /setnumflags { /numflags exch def } def + /sethooksm1 { /hooksm1 exch def } def + /setoffsets { /offsets exch def } def + /setx { /x exch def } def + /sety { /y exch def } def +end + +% Define a music character font. Each music character is defined as if it +% were a normal ASCII character in a strange font where "A" looks like a +% treble clef, "B" looks like a bass clef, etc. + +/mfont0 100 dict def +mfont0 begin + /FontType 3 def + /FontMatrix [ .001 0 0 0.001 0 0 ] def + /FontBBox [ -2000 -4030 2000 4030 ] def + /FontName (Mfont0) def + + % set up Encoding vector with standard names + /Encoding 256 array def + StandardEncoding Encoding copy + pop + + % the following definitions are used for quarter rests + /topx -170 def /topy 950 def + /cor1x 250 def /cor1y 450 def + /cor2x -300 def /cor2y 200 def + /cor3x 250 def /cor3y -400 def + + % the following definitions are used for double sharps + /limit 300 halflwid add def + /off 70 def + /inbendsmall limit 200 sub def + /inbendbig limit 20 sub def + /outbendsmall 100 def + /outbendbig outbendsmall off add def + + %%%%% define routines that will be used by multiple characters %%%%% + /do_1n { + gsave + newpath -10 rotate 1.6 1 scale + 0 0 325 0 360 arc %outer ellipse + 1 1.6 div 1 scale 10 rotate %back to original + 35 rotate 0.85 1.1 scale + 0 0 275 0 360 arc %inner ellipse + eofill + grestore + } def + /do_upflag { + -315 0 moveto + -300 100 -100 480 0 600 curveto + 300 960 350 1500 200 1700 curveto + 130 1700 lineto + 350 1200 50 650 -315 600 curveto + fill + } def + /do_flat { + -250 -400 moveto %outer edge of loop + 500 0 350 650 -250 160 curveto + -250 160 lwid sub lineto %inner edge of loop + 100 400 300 0 -250 -400 lwid add curveto + fill + + lwid setlinewidth %stem + -250 1100 moveto -250 -400 lineto stroke + } def + /do_diamond { + newpath + 420 0 moveto 0 300 lineto -420 0 lineto + 0 -300 lineto closepath + 259 -29 moveto -41 185 lineto -259 29 lineto + 41 -185 lineto closepath + eofill + } def + /do_2n { + gsave + newpath 25 rotate 1.4 1 scale + 0 0 315 0 360 arc %outer ellipse + 1 1.4 div 1 scale %back to original + 1.3 0.5 scale + 0 0 310 0 360 arc %inner ellipse + eofill + grestore + } def + /do_4n { + gsave + newpath 25 rotate 1.35 1 scale + 0 0 310 0 360 arc fill + grestore + } def + /do_com { + newpath + 330 250 150 0 360 arc fill %knob at upper right + 465 300 moveto %outer boundary + 410 500 200 635 0 635 curveto + -750 635 -750 -635 0 -635 curveto + 350 -635 480 -300 500 -100 curveto + 430 -100 lineto %inner boundary + 380 -300 250 -565 0 -565 curveto + -450 -565 -450 565 0 565 curveto + 200 565 370 350 395 300 curveto + fill + } def + /do_ferm { + 0 0 800 lwid sub 0 180 arc %inner arc + -800 0 lineto + 0 270 lwid sub 800 180 0 arcn %outer arc + 800 0 lineto fill + 0 120 120 0 360 arc fill %the dot + } def + /do_mor { + gsave + 0.7 1 scale %scrunch the following horizontally + 45 rotate %to pretend all lines horz or vertical + 0 1 1 { + pop %we don't need the loop variable + %one half of the mordent + 0 40 moveto 350 40 lineto 350 -460 lineto + 750 -460 lineto 750 -540 lineto + 150 -540 lineto 150 -40 lineto + 0 -40 lineto fill + 180 rotate %to do the other half + } for + grestore + } def + /do_turn { + gsave + 0 1 1 { + pop %we don't need the loop variable + 0 -100 moveto %outer boundary + 200 -400 625 -400 625 0 curveto + 625 200 500 325 300 325 curveto + 300 185 lineto %inner boundary + 450 255 555 150 555 0 curveto + 555 -350 250 -250 0 100 curveto + fill + 300 255 70 0 360 arc fill %knob on end + 180 rotate %to do the other half + } for + grestore + } def + + /do_upshortnote { + utildict begin + setnumflags %set numflags from the stack + gsave + -330 0 translate %half a flag width + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto + 370 2100 numflags 2 sub flagsep mul add lineto stroke + 670 2100 numflags 2 sub flagsep mul add translate + 1 -1 scale %reflect across X axis + 0 1 numflags 1 sub { + do_upflag %do an upflag + pop %we don't need the loop variable + 0 flagsep translate + } for + grestore + end + } def + + /do_dnshortnote { + utildict begin + setnumflags %set numflags from the stack + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto + -370 -2100 numflags 2 sub flagsep mul sub lineto stroke + gsave + -70 -2100 numflags 2 sub flagsep mul sub translate + 0 1 numflags 1 sub { + do_upflag %do an upflag + pop %we don't need the loop variable + 0 flagsep translate + } for + grestore + end + } def + + /do_shortrest { + utildict begin + sety setx setoffsets sethooksm1 %set variable from the stack + gsave + -105.8 offsets mul -600 offsets mul translate + 0 1 hooksm1 { %loop once per hook + newpath + 1 setlinewidth + gsave + 1 1.2 scale + -150 300 1.2 div 140 0 360 arc fill %the dot + grestore + lwid setlinewidth + -50 700 550 255 315 arc %rest of the hook + hooksm1 lt { stroke 105.8 600 translate } if + } for + x y lineto stroke + grestore + end + } def + + + % subsidiary dictionary of character definitions + /CharStrings 128 dict def + CharStrings begin + + /.notdef {} def + + % Here are the definitions of the characters. A stepsize here + % is 300 units (assuming the character is drawn at its default + % size). + + % gclef + /A { + newpath + %start with inner curl, inside boundary + -50 -300 moveto + -450 600 700 700 750 0 curveto + 750 -800 -700 -800 -700 200 curveto + -700 900 500 1400 520 2250 curveto + 520 2900 300 3000 200 3000 curveto + 100 3000 -400 2500 -200 1800 curveto + 350 -600 lineto + 720 -1600 0 -1650 -400 -1400 curveto + + %go back to start, drawing the other boundary + -400 -1480 lineto + 0 -1700 800 -1700 430 -600 curveto + -120 1800 lineto + -300 2400 200 2800 250 2800 curveto + 400 2800 430 2700 430 2450 curveto + 430 1800 -900 1200 -900 300 curveto + -750 -900 800 -900 850 0 curveto + 900 1100 -750 900 -120 -300 curveto fill + + %circle at the bottom + -300 -1250 250 0 360 arc fill + } def + + % fclef + /B { + newpath + %start with outside boundary, at bottom + -1000 -1700 moveto + 100 -1100 500 -600 450 0 curveto + 450 850 -1100 850 -950 0 curveto + + %go back to start, drawing the other boundary + -880 0 lineto + -920 400 -600 560 -300 560 curveto + 0 560 150 400 150 0 curveto + 150 -400 100 -900 -1000 -1620 curveto fill + + %circle at the left + newpath + -700 0 250 0 360 arc fill + + %do the two dots after the main curve + 700 -300 100 0 360 arc fill + 700 300 100 0 360 arc fill + } def + + % cclef + /C { + gsave + %do upper curved part, then scale to do mirror image + 0 1 1 { + pop %we don't need the loop variable + %outer boundary of curve + -170 0 moveto 100 300 lineto + 400 -200 750 300 750 650 curveto + 750 1100 450 1235 250 1235 curveto + 0 1235 -143 1100 -143 950 curveto + + %inner boundary of curve + 0 950 lineto + 0 1100 30 1165 250 1165 curveto + 300 1165 450 1100 450 650 curveto + 450 400 400 -100 100 400 curveto + -270 0 lineto fill + %stroke + %-270 0 moveto 100 400 lineto + %400 -100 450 400 450 650 curveto + %450 1100 300 1165 250 1165 curveto + %30 1165 0 1100 0 950 curveto + %stroke + + %elliptical ball at end of curve + gsave + 1.3 1 scale + 10 950 120 0 360 arc fill + grestore + 1 -1 scale %reflect across X axis + } for + grestore + + % two vertical lines on the left + 300 setlinewidth -600 -1200 halflwid sub moveto + -600 1200 halflwid add lineto stroke + lwid setlinewidth -300 -1200 halflwid sub moveto + -300 1200 halflwid add lineto stroke + } def + + % dblwhole + /D { + do_1n %do a whole note + lwid setlinewidth + -490 -600 moveto -490 600 lineto stroke + 490 -600 moveto 490 600 lineto stroke + } def + + % 1n + /E { + do_1n %do a whole note + } def + + % 2n + /F { + do_2n %do a half note + } def + + % 4n + /G { + do_4n %do a quarter note head + } def + + % upflag + /H { + do_upflag %do an upflag + } def + + % dnflag + /I { + gsave + 1 -1 scale %reflect across X axis + do_upflag %do an upflag + grestore + } def + + % dwhrest + /J { + 300 setlinewidth + 0 0 moveto 0 600 lineto stroke + } def + + % 1rest + /K { + lwid setlinewidth + -750 600 moveto 750 600 lineto stroke + 300 setlinewidth + -400 450 moveto 400 450 lineto stroke + } def + + % 2rest + /L { + lwid setlinewidth + -750 0 moveto 750 0 lineto stroke + 300 setlinewidth + -400 150 moveto 400 150 lineto stroke + } def + + % 4rest + /M { + newpath + cor3x cor3y halflwid add moveto + %-400 -200 -450 -650 50 -950 lwid add curveto + -450 -50 -450 -650 50 -950 lwid add curveto + -150 -650 -100 -250 cor3x cor3y halflwid sub curveto + fill + + cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto + cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto + fill + + lwid setlinewidth + topx topy moveto cor1x cor1y lineto stroke + cor2x cor2y moveto cor3x cor3y lineto stroke + } def + + % 8rest + /N { + 0 0 0 -600 do_shortrest + } def + + % 16rest + /O { + 1 1 100 -1200 do_shortrest + } def + + % 32rest + /P { + 2 1 0 -1800 do_shortrest + } def + + % 64rest + /Q { + 3 2 -80 -2100 do_shortrest + } def + + % 128rest + /R { + 4 2 -150 -2700 do_shortrest + } def + + % 256rest + /S { + 5 3 -280 -3300 do_shortrest + } def + + % dot + /T { + newpath + 0 0 120 0 360 arc fill + } def + + % nat + /U { + % fill crossbars so that we can do parallelograms + -235 -470 moveto -235 -270 lineto + 235 -130 lineto 235 -330 lineto fill + -235 130 moveto -235 330 lineto + 235 470 lineto 235 270 lineto fill + + % vertical strokes + lwid setlinewidth + -200 -380 moveto -200 850 lineto stroke + 200 -850 moveto 200 380 lineto stroke + } def + + % sharp + /V { + % fill crossbars so that we can do parallelograms + -325 -480 moveto -325 -280 lineto + 325 -120 lineto 325 -320 lineto fill + -325 120 moveto -325 320 lineto + 325 480 lineto 325 280 lineto fill + + % vertical strokes + lwid setlinewidth + -150 -930 moveto -150 880 lineto stroke + 150 -880 moveto 150 930 lineto stroke + } def + + % flat + /W { + do_flat %do a flat + } def + + % dblsharp + /X { + gsave + 0 1 3 { %loop once for each of 4 sticks + pop %we don't need the loop variable + 0 off neg moveto + outbendbig outbendsmall lineto + inbendbig inbendsmall lineto + limit limit lineto + inbendsmall inbendbig lineto + outbendsmall outbendbig lineto + off neg 0 lineto + fill + -90 rotate + } for + grestore + } def + + % dblflat + /Y { + -290 580 290 { %loop once for each flat + + gsave + 1 setlinewidth + 0 translate %translate left/right (loop var) + do_flat %do a flat + grestore + + } for + } def + + % xnote + /Z { + gsave + 1.15 1 scale 120 setlinewidth 1 setlinecap %round + -300 -300 moveto 300 300 lineto stroke + -300 300 moveto 300 -300 lineto stroke + grestore + } def + + % dwhdiamond + /a { + do_diamond %do a diamond + lwid setlinewidth + -420 -600 moveto -420 600 lineto stroke + 420 -600 moveto 420 600 lineto stroke + } def + + % diamond + /b { + do_diamond %do a diamond + } def + + % filldiamond + /c { + 420 0 moveto 0 300 lineto + -420 0 lineto 0 -300 lineto fill + } def + + % up2n + /d { + lwid setlinewidth + 380 0 moveto 380 2100 lineto stroke + do_2n %do a half note + } def + + % dn2n + /e { + lwid setlinewidth + -380 0 moveto -380 -2100 lineto stroke + do_2n %do a half note + } def + + % up4n + /f { + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto 370 2100 lineto stroke + } def + + % dn4n + /g { + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto -370 -2100 lineto stroke + } def + + % up8n + /h { + gsave + -330 0 translate % half a flag width + do_4n %do a quarter note head + lwid setlinewidth + 370 0 moveto 370 2100 lineto stroke + 670 2100 translate + 1 -1 scale %reflect across X axis + do_upflag %do an upflag + grestore + } def + + % dn8n + /i { + do_4n %do a quarter note head + lwid setlinewidth + -370 0 moveto -370 -2100 lineto stroke + gsave + -70 -2100 translate + do_upflag %do an upflag + grestore + } def + + % up16n + /j { + 2 do_upshortnote + } def + + % dn16n + /k { + 2 do_dnshortnote + } def + + % up32n + /l { + 3 do_upshortnote + } def + + % dn32n + /m { + 3 do_dnshortnote + } def + + % up64n + /n { + 4 do_upshortnote + } def + + % dn64n + /o { + 4 do_dnshortnote + } def + + % up128n + /p { + 5 do_upshortnote + } def + + % dn128n + /q { + 5 do_dnshortnote + } def + + % up256n + /r { + 6 do_upshortnote + } def + + % dn256n + /s { + 6 do_dnshortnote + } def + + % com + /t { + do_com %do a common time symbol + } def + + % cut + /u { + do_com %do a common time symbol + lwid setlinewidth + 0 -900 moveto 0 900 lineto stroke + } def + + % begped + /v { + lwid setlinewidth + -200 600 moveto -200 0 lineto 200 0 lineto stroke + } def + + % pedal + /w { + lwid setlinewidth + -500 0 moveto -450 0 lineto 0 600 lineto + 450 0 lineto 500 0 lineto stroke + } def + + % endped + /x { + lwid setlinewidth + 200 600 moveto 200 0 lineto -200 0 lineto stroke + } def + + % dnbow + /y { + lwid setlinewidth + -350 0 moveto -350 900 lineto stroke + 350 0 moveto 350 900 lineto stroke + 200 setlinewidth + -350 800 moveto 350 800 lineto stroke + } def + + % upbow + /z { + lwid setlinewidth + -300 900 moveto 0 0 lineto 300 900 lineto stroke + } def + + % wedge + /one { + 0 0 moveto -150 500 lineto 150 500 lineto fill + } def + + % uwedge + /two { + -150 0 moveto 150 0 lineto 0 500 lineto fill + } def + + % ferm + /three { + newpath + do_ferm %do a right side up fermata + } def + + % uferm + /four { + newpath + gsave + 0 270 lwid sub 800 add translate %baseline at bottom + 180 rotate %upside down + do_ferm %do a right side up fermata + grestore + } def + + % sign + /five { + gsave + %do upper left curved part, upper right dot; + %then rotate 180 to do other half + 0 1 1 { + pop %we don't need the loop variable + 0 100 moveto %inner boundary + -1000 300 -400 750 -200 700 curveto + -200 800 lineto %outer boundary + -550 900 -1100 100 0 -100 curveto + fill + %dot at end of curve + -200 700 100 0 360 arc fill + %dot in upper right quadrant + 500 200 70 0 360 arc fill + 180 rotate + } for + grestore + + %slash through middle + lwid setlinewidth + -400 -800 moveto 400 800 lineto stroke + } def + + % coda + /six { + newpath + gsave + 0.6 1 scale + 0 0 550 0 360 arc %outside boundary + 1 0.6 div 1 scale %back to original + 0.9 1 scale + 0 0 650 0 360 arc %inside boundary + eofill + grestore + lwid setlinewidth + 0 -850 moveto 0 850 lineto stroke + -800 0 moveto 800 0 lineto stroke + } def + + % mor + /seven { + do_mor %do a mordent + } def + + % invmor + /eight { + do_mor %do a mordent + lwid setlinewidth + 0 -450 moveto 0 450 lineto stroke + } def + + % turn + /nine { + do_turn %do a turn + } def + + % invturn + /zero { + gsave + 1 -1 scale %reflect across X axis + do_turn %do a turn + grestore + } def + + % acc_gt + /numbersign { + lwid setlinewidth + -500 300 moveto 500 0 lineto -500 -300 lineto stroke + } def + + % acc_hat + /dollar { + newpath + -365 0 moveto 0 860 lineto 365 0 lineto + 150 0 lineto -75 530 lineto -300 0 lineto fill + } def + + % acc_uhat + /quotedbl { + newpath + 365 860 moveto 0 0 lineto -365 860 lineto + -150 860 lineto 75 330 lineto 300 860 lineto fill + } def + + % tr + /asterisk { + %vertical bar of t + -350 1000 moveto -550 200 lineto + -612.5 -50 -212.5 -50 -160 200 curveto + -230 200 lineto + -300 50 -420 50 -400 200 curveto + -200 1000 lineto fill + + %crossbar of t and vertical bar of r + -700 600 moveto -160 600 lineto + 20 600 30 520 60 440 curveto + -50 0 lineto 70 0 lineto 180 440 lineto + 190 480 100 670 -150 670 curveto + -690 670 lineto fill + + %horizontal curve of r + 100 480 moveto + 300 630 450 700 650 550 curveto + 560 480 lineto + 450 630 300 560 100 390 curveto + fill + + %knob at end of r + 600 460 100 0 360 arc fill + } def + + % leg + /comma { + 100 setlinewidth + -400 0 moveto 400 0 lineto stroke + } def + + % rr + /hyphen { + 100 setlinewidth + -400 0 moveto 0 1000 lineto stroke + 0 0 moveto 400 1000 lineto stroke + } def + + % measrpt + /period { + newpath -450 400 150 0 360 arc fill + newpath 450 -400 150 0 360 arc fill + 200 setlinewidth + -550 -600 moveto 550 600 lineto stroke + } def + + % copyright + /slash { + lwid setlinewidth + newpath 0 400 400 0 360 arc stroke + newpath 0 400 200 45 315 arc stroke + } def + + % dim + /quoteleft { + 50 setlinewidth + newpath 0 640 220 0 360 arc stroke + } def + + % halfdim + /quoteright { + 50 setlinewidth + newpath 0 640 220 0 360 arc stroke + newpath -340 300 moveto 340 980 lineto stroke + } def + + % triangle + /asciicircum { + 50 setlinewidth + newpath -340 -10 moveto 0 710 lineto + 340 -10 lineto closepath stroke + } def + + % qwhrest + /ampersand { + 300 setlinewidth + 0 -600 moveto 0 600 lineto stroke + } def + + % ll1rest + /exclam { + 310 setlinewidth + -400 455 moveto 400 450 lineto stroke + } def + + % ll2rest + /at { + 310 setlinewidth + -400 145 moveto 400 150 lineto stroke + } def + end + + /BuildChar { + + exch begin + Encoding exch get + + dup + Mcbbox0 exch get + aload pop setcachedevice + + CharStrings exch get + exec + end + } def +end + + +% Define another music character font, since there are too many to fit in one +% font. It works the same way as the first one. + +/mfont1 100 dict def +mfont1 begin + /FontType 3 def + /FontMatrix [ .001 0 0 0.001 0 0 ] def + /FontBBox [ -2000 -4030 2000 4030 ] def + /FontName (Mfont1) def + + % set up Encoding vector with standard names + /Encoding 256 array def + StandardEncoding Encoding copy + pop + + %%%%% define routines that will be used by multiple characters %%%%% + + /do_dwh_bars { + % the two bars surrounding a double whole note + lwid setlinewidth + -420 -600 moveto -420 600 lineto stroke + 420 -600 moveto 420 600 lineto stroke + } def + /do_righttriangle { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto + 350 150 moveto -140 150 lineto 350 -213 lineto + eofill + } def + /do_fillrighttriangle { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto + fill + } def + /do_rectangle { + newpath + 420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto + 350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto + eofill + } def + /do_isostriangle { + newpath + 0 300 moveto -420 -270 lineto 420 -270 lineto + 0 182 moveto -245 -150 lineto 245 -150 lineto + eofill + } def + /do_piewedge { + newpath + 0 -300 moveto 0 -244 514 35 145 arc + 0 -209 moveto 0 -244 394 43 137 arc + eofill + } def + /do_semicircle { + newpath + gsave + 1 1.357 scale 420 199 moveto 0 199 420 180 360 arc + 1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc + eofill + grestore + } def + /do_slashhead { + newpath + lwid setlinewidth + -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto + closepath stroke + } def + + % subsidiary dictionary of character definitions + /CharStrings 128 dict def + CharStrings begin + + /.notdef {} def + + % Here are the definitions of the characters. A stepsize here + % is 300 units (assuming the character is drawn at its default + % size). + + % dwhrighttriangle + /A { + do_righttriangle + do_dwh_bars + } def + + % righttriangle + /B { + do_righttriangle + } def + + % fillrighttriangle + /C { + newpath + 420 270 moveto -420 270 lineto 350 -300 lineto + 420 -300 lineto + fill + } def + + % udwhrighttriangle + /D { + gsave + 180 rotate + do_righttriangle + do_dwh_bars + grestore + } def + + % urighttriangle + /E { + gsave + 180 rotate + do_righttriangle + grestore + } def + + % ufillrighttriangle + /F { + gsave + 180 rotate + do_fillrighttriangle + grestore + } def + + % dwhrectangle + /G { + do_rectangle + do_dwh_bars + } def + + % rectangle + /H { + do_rectangle + } def + + % fillrectangle + /I { + newpath + 420 270 moveto -420 270 lineto -420 -270 lineto + 420 -270 lineto + fill + } def + + % dwhisostriangle + /J { + do_isostriangle + do_dwh_bars + } def + + % isostriangle + /K { + do_isostriangle + } def + + % fillisostriangle + /L { + newpath + 0 300 moveto -420 -270 lineto 420 -270 lineto + fill + } def + + % dwhpiewedge + /M { + do_piewedge + do_dwh_bars + } def + + % piewedge + /N { + do_piewedge + } def + + % fillpiewedge + /O { + newpath + 0 -300 moveto 0 -244 514 35 145 arc + fill + } def + + % dwhsemicircle + /P { + do_semicircle + do_dwh_bars + } def + + % semicircle + /Q { + do_semicircle + } def + + % fillsemicircle + /R { + newpath + gsave + 1 570 420 div scale + 420 199 moveto 0 199 420 180 360 arc + fill + grestore + } def + + % dwhslashhead + /S { + do_slashhead + lwid setlinewidth + -650 -600 moveto -650 600 lineto stroke + 650 -600 moveto 650 600 lineto stroke + } def + + % slashhead + /T { + do_slashhead + } def + + % fillslashhead + /U { + newpath + 200 setlinewidth + -550 -600 moveto 550 600 lineto stroke + } def + + % blankhead + /V { + %print nothing + } def + end + + /BuildChar { + + exch begin + Encoding exch get + + dup + Mcbbox1 exch get + aload pop setcachedevice + + CharStrings exch get + exec + end + } def +end + + +% General routines for printing any music character, invoked by each music +% character's specific routine below. The scaling factor (default 1) needs +% to be multiplied by 10 to get the actual size. These routines restore the +% preexisting current font when they are done. + +/printmchar0 { + gsave + /musicchar exch def + /Mfont0 findfont exch 10 mul scalefont setfont moveto + musicchar show + grestore +} def +/printmchar1 { + gsave + /musicchar exch def + /Mfont1 findfont exch 10 mul scalefont setfont moveto + musicchar show + grestore +} def + +% Define each music character name to be a routine that prints the character. +% Each character is to be invoked as in this example: +% 100 200 1 gclef % at (100, 200), scale to default size & print + +/gclef { (A) printmchar0 } def +/fclef { (B) printmchar0 } def +/cclef { (C) printmchar0 } def +/dblwhole { (D) printmchar0 } def +/1n { (E) printmchar0 } def +/2n { (F) printmchar0 } def +/4n { (G) printmchar0 } def +/upflag { (H) printmchar0 } def +/dnflag { (I) printmchar0 } def +/dwhrest { (J) printmchar0 } def +/1rest { (K) printmchar0 } def +/2rest { (L) printmchar0 } def +/4rest { (M) printmchar0 } def +/8rest { (N) printmchar0 } def +/16rest { (O) printmchar0 } def +/32rest { (P) printmchar0 } def +/64rest { (Q) printmchar0 } def +/128rest { (R) printmchar0 } def +/256rest { (S) printmchar0 } def +/dot { (T) printmchar0 } def +/nat { (U) printmchar0 } def +/sharp { (V) printmchar0 } def +/flat { (W) printmchar0 } def +/dblsharp { (X) printmchar0 } def +/dblflat { (Y) printmchar0 } def +/xnote { (Z) printmchar0 } def +/dwhdiamond { (a) printmchar0 } def +/diamond { (b) printmchar0 } def +/filldiamond { (c) printmchar0 } def +/up2n { (d) printmchar0 } def +/dn2n { (e) printmchar0 } def +/up4n { (f) printmchar0 } def +/dn4n { (g) printmchar0 } def +/up8n { (h) printmchar0 } def +/dn8n { (i) printmchar0 } def +/up16n { (j) printmchar0 } def +/dn16n { (k) printmchar0 } def +/up32n { (l) printmchar0 } def +/dn32n { (m) printmchar0 } def +/up64n { (n) printmchar0 } def +/dn64n { (o) printmchar0 } def +/up128n { (p) printmchar0 } def +/dn128n { (q) printmchar0 } def +/up256n { (r) printmchar0 } def +/dn256n { (s) printmchar0 } def +/com { (t) printmchar0 } def +/cut { (u) printmchar0 } def +/begped { (v) printmchar0 } def +/pedal { (w) printmchar0 } def +/endped { (x) printmchar0 } def +/dnbow { (y) printmchar0 } def +/upbow { (z) printmchar0 } def +/wedge { (1) printmchar0 } def +/uwedge { (2) printmchar0 } def +/ferm { (3) printmchar0 } def +/uferm { (4) printmchar0 } def +/sign { (5) printmchar0 } def +/coda { (6) printmchar0 } def +/mor { (7) printmchar0 } def +/invmor { (8) printmchar0 } def +/turn { (9) printmchar0 } def +/invturn { (0) printmchar0 } def +/acc_gt { (#) printmchar0 } def +/acc_hat { ($) printmchar0 } def +/acc_uhat { (") printmchar0 } def +/tr { (*) printmchar0 } def +/leg { (,) printmchar0 } def +/rr { (-) printmchar0 } def +/measrpt { (.) printmchar0 } def +/copyright { (/) printmchar0 } def +/dim { (`) printmchar0 } def +/halfdim { (') printmchar0 } def +/triangle { (^) printmchar0 } def +/qwhrest { (&) printmchar0 } def +/ll1rest { (!) printmchar0 } def +/ll2rest { (@) printmchar0 } def +/dwhrighttriangle { (A) printmchar1 } def +/righttriangle { (B) printmchar1 } def +/fillrighttriangle { (C) printmchar1 } def +/udwhrighttriangle { (D) printmchar1 } def +/urighttriangle { (E) printmchar1 } def +/ufillrighttriangle { (F) printmchar1 } def +/dwhrectangle { (G) printmchar1 } def +/rectangle { (H) printmchar1 } def +/fillrectangle { (I) printmchar1 } def +/dwhisostriangle { (J) printmchar1 } def +/isostriangle { (K) printmchar1 } def +/fillisostriangle { (L) printmchar1 } def +/dwhpiewedge { (M) printmchar1 } def +/piewedge { (N) printmchar1 } def +/fillpiewedge { (O) printmchar1 } def +/dwhsemicircle { (P) printmchar1 } def +/semicircle { (Q) printmchar1 } def +/fillsemicircle { (R) printmchar1 } def +/dwhslashhead { (S) printmchar1 } def +/slashhead { (T) printmchar1 } def +/fillslashhead { (U) printmchar1 } def +/blankhead { (V) printmchar1 } def + + +% Define routines for Mup output other than music characters. + +/stepsize 3 def % define a step size as 3 points (at default magnification) + +% x1 y1 x2 lines dist staffscale staff +% draw a staff starting at x1, y1 and extending to x2 with "lines" +% lines, 2*dist*stepsize apart, scaled by staffscale +/staff { + /staffscale exch def + /dist exch def + /lines exch def + /x2 exch def + /y1 exch def + /x1 exch def + 0.7 staffscale mul sb setlinewidth + 1 lines sub 2 lines 1 sub { % loop from bottom line to top line + dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto + stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke + } for +} def + +% x y1 y2 bracket draw a bracket; y1 is the top +/bracket { + /y2 exch def + /y1 exch def + /x exch def + gsave + 3 setlinewidth + x 2 sub y1 1 add moveto + x 2 sub y2 1 sub lineto + stroke + x 2 sub y1 1 add moveto + x 1 sub y1 1 add x 3 add y1 1 add x 5 add y1 6 add curveto + x 6 add y1 5 add lineto + x 5 add y1 2 add x 1 add y1 2 sub x 2 sub y1 2 sub curveto + fill + x 2 sub y2 1 sub moveto + x 1 sub y2 1 sub x 3 add y2 1 sub x 5 add y2 6 sub curveto + x 6 add y2 5 sub lineto + x 5 add y2 2 sub x 1 add y2 2 add x 2 sub y2 2 add curveto + fill + grestore +} def + +% x y1 y2 brace draw a brace; y1 is the top +/brace { + /y2 exch def + /y1 exch def + /x exch def + gsave + x 9 sub y1 y2 add 2 div translate + /topy y1 y2 sub 2 div 1 sub def + 0 1 1 { + pop + %0 topy moveto 0 0 lineto stroke + 0 0 moveto + 16 topy 0.2 mul -11 topy 0.6 mul 8 topy curveto + 8.7 topy lineto + -7 topy 0.7 mul 20 topy 0.3 mul 1 0 curveto + fill + 1 -1 scale % flip to do bottom half + } for + grestore +} def + +% endx endy wavy staffscale draw a wavy line from current point to here, +% scaled by staffscale +/wavy { + /staffscale exch def + /endy exch def % define the end point of the line + /endx exch def + currentpoint % line starts at current point + /begy exch def % define the beginning point of the line + /begx exch def + gsave + /dx endx begx sub def % find delta x and delta y + /dy endy begy sub def + /r dx dx mul dy dy mul add sqrt def % hypotenuse + /theta dy dx atan def % angle with positive x axis + begx begy translate % change axes so that we can draw the line + theta rotate % from (0, 0) to (r, 0) + staffscale staffscale scale % scale everything by staffscale + /scaledr r staffscale div def % but scale r in reverse to keep length + + % Each outer loop draws one cycle of the squiggle. It continues until + % we are at or beyond the desired end point. + 0 0 moveto + 0 6 scaledr { + gsave + % first loop draws left half of squiggle; second draws right + 0 1 1 { + 0.0 0.4 moveto + 2.0 1.9 3.4 2.3 3.9 0.0 curveto + 2.1 0.0 lineto + 1.9 0.8 1.4 0.7 0.0 -0.4 curveto + fill + pop 180 rotate -6 0 translate + } for + grestore + + pop 6 0 translate % shift axes right one squiggle + } for + + grestore +} def + +% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid +% print a guitar grid diagram +/grid { + /grid_positions exch def % 0="o", -1="x", -2=nothing, positive=dot + /curver exch def % right string for curve, 0 if none + /curvel exch def % left string for curve, 0 if none + /numvert exch def % vertical position to print fretno, 0 if none + /fretno exch def % fret no. to print at right, 0 if none + /frets exch def % number of fret lines + /space exch def % points between two neighboring lines + /y exch def % y coord of top fret line + /x exch def % x coord of left strings + + gsave + /strings grid_positions length def % number of strings + /lmarky 0.4 space mul y add def % lowest Y of a "o" or "x" + space 10 div setlinewidth + 2 setlinecap + + % draw the lines of the grid + 0 1 strings 1 sub { % loop from left string to right string + dup space mul x add y moveto + space mul x add frets 1 sub space mul y exch sub lineto stroke + } for + 0 -1 1 frets sub { % loop from top fret (nut) to bottom fret + dup space mul y add x exch moveto + space mul y add strings 1 sub space mul x add exch lineto stroke + } for + + % draw the curved line if there is one + curvel 0 gt { + % within strings curvel to curver, find smallest positive fret + /minfret 1000 def + curvel 1 curver { + /strno exch def + /grid_p grid_positions strno 1 sub get def + grid_p 0 gt grid_p minfret lt and { + /minfret grid_p def + } if + } for + + % if curve goes above top fret, other marks must be higher + minfret 1 eq { + /hmarky 1.2 space mul y add def + } { + /hmarky lmarky def + } ifelse + + /strdiff curver curvel sub def + space 8 div setlinewidth + + % set endpoint coords of curve; higher if curve is short + /curvex1 curvel 1 sub space mul x add def + /curvex2 curver 1 sub space mul x add def + /curvey 1 minfret sub space mul y add def + strdiff 3 lt { + /curvey 0.2 strdiff div space mul curvey add def + } if + + % move to left end, set other points, draw curve + curvex1 curvey moveto + + curvex1 curvex2 curvex1 sub 3 div add + curvey space 0.4 strdiff sqrt mul mul add + + curvex2 curvex2 curvex1 sub 3 div sub + curvey space 0.4 strdiff sqrt mul mul add + + curvex2 curvey curveto stroke + } if + + space 10 div setlinewidth + + % draw dots and x and o marks + 0 1 strings 1 sub { % loop from left string to right string + /strno exch def % first string is 0 + /grid_p grid_positions strno get def + /strx strno space mul x add def + + % set Y of mark higher if curved line covers this string + strno 1 add curvel ge strno 1 add curver le and { + /marky hmarky def + } { + /marky lmarky def + } ifelse + + grid_p -1 eq { % draw an X above the string + /xhwid space 3 div def + strx xhwid sub marky xhwid sub moveto + strx xhwid add marky xhwid add lineto stroke + strx xhwid sub marky xhwid add moveto + strx xhwid add marky xhwid sub lineto stroke + } if + grid_p 0 eq { % draw a circle above the string + strx marky space 0.3 mul 0 360 arc stroke + } if + grid_p 1 ge { % draw a dot by the proper fret + strx y grid_p space mul sub space 3 div add + space 3 div 0 360 arc fill + } if + } for + + % print "X fr" if requested + fretno 0 gt { + /Palatino-Roman findfont space 1.9 mul scalefont setfont + x strings 0.5 sub space mul add + y space numvert 0.3 add mul sub moveto + fretno 2 string cvs show ( fr) show + } if + grestore +} def + +% x1 y1 x2 y2 whitebox draw a white rectangle with opposite +% corners of (x1,y1) and (x2,y2) +/whitebox { + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + 1.0 setgray + newpath + x1 y1 moveto + x1 y2 lineto + x2 y2 lineto + x2 y1 lineto + closepath + fill + stroke + 0.0 setgray +} def + + +/LineNum 0 def +/InputFile (unknown) def + +% n linenum +/linenum { + /LineNum exch def +} def + +% (inputfilename) inputfile +/inputfile { + /InputFile exch def +} def + +% find size of Encoding and make a dictionary +% that size for bounding box information +mfont0 begin +/dictsize Encoding length def +mfont0 /Mcbbox0 dictsize dict put + +% temporarily redefine printmchar0 to get code +5 dict begin +/printmchar0 { {} forall } def + +Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put +Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put +Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put +Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put +Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put +Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put +Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put +Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put +Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put +Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put +Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put +Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put +Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put +Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put +Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put +Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put +Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put +Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put +Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put +Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put +Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put +Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put +Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put +Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put +Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put +Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put +Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put +Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put +Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put +Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put +Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put +Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put +Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put +Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put +Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put +Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put +Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put +Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put +Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put +Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put +Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put +Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put +Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put +Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put +Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put +Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put +Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put +Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put +Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put +Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put +Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put +Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put +Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put +Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put +Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put +Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put +Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put +Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put +Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put +Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put +Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put +Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put +Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put +Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put +Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put +Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put +Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put +Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put +Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put +Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put +Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put +Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put +Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put + +end +end + +/Mfont0 mfont0 definefont + + +% find size of Encoding and make a dictionary +% that size for bounding box information +mfont1 begin +/dictsize Encoding length def +mfont1 /Mcbbox1 dictsize dict put + +% temporarily redefine printmchar1 to get code +5 dict begin +/printmchar1 { {} forall } def + +Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put +Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put +Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put +Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put +Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put +Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put +Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put +Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put + +end +end + +/Mfont1 mfont1 definefont + +/makeExtEncoding { + /extendedencoding 256 array def + StandardEncoding extendedencoding copy + extendedencoding 32 /exclamdown put + extendedencoding 33 /cent put + extendedencoding 34 /sterling put + extendedencoding 35 /yen put + extendedencoding 36 /quotedblleft put + extendedencoding 37 /guillemotleft put + extendedencoding 38 /guillemotright put + extendedencoding 39 /guilsinglleft put + extendedencoding 40 /guilsinglright put + extendedencoding 41 /dagger put + extendedencoding 42 /daggerdbl put + extendedencoding 43 /bullet put + extendedencoding 44 /quotedblbase put + extendedencoding 45 /quotedblright put + extendedencoding 46 /questiondown put + extendedencoding 47 /grave put + extendedencoding 48 /acute put + extendedencoding 49 /macron put + extendedencoding 50 /breve put + extendedencoding 51 /dotaccent put + extendedencoding 52 /dieresis put + extendedencoding 53 /ring put + extendedencoding 54 /cedilla put + extendedencoding 55 /hungarumlaut put + extendedencoding 56 /ogonek put + extendedencoding 57 /caron put + extendedencoding 58 /emdash put + extendedencoding 59 /AE put + extendedencoding 60 /ae put + extendedencoding 61 /ordfeminine put + extendedencoding 62 /ordmasculine put + extendedencoding 63 /Lslash put + extendedencoding 64 /lslash put + extendedencoding 65 /Oslash put + extendedencoding 66 /oslash put + extendedencoding 67 /OE put + extendedencoding 68 /oe put + extendedencoding 69 /dotlessi put + extendedencoding 70 /germandbls put + extendedencoding 71 /Aacute put + extendedencoding 72 /aacute put + extendedencoding 73 /Acircumflex put + extendedencoding 74 /acircumflex put + extendedencoding 75 /Adieresis put + extendedencoding 76 /adieresis put + extendedencoding 77 /Agrave put + extendedencoding 78 /agrave put + extendedencoding 79 /Aring put + extendedencoding 80 /aring put + extendedencoding 81 /Atilde put + extendedencoding 82 /atilde put + extendedencoding 83 /Ccedilla put + extendedencoding 84 /ccedilla put + extendedencoding 85 /Eacute put + extendedencoding 86 /eacute put + extendedencoding 87 /Ecircumflex put + extendedencoding 88 /ecircumflex put + extendedencoding 89 /Edieresis put + extendedencoding 90 /edieresis put + extendedencoding 91 /Egrave put + extendedencoding 92 /egrave put + extendedencoding 93 /Iacute put + extendedencoding 94 /iacute put + extendedencoding 95 /Icircumflex put + extendedencoding 96 /icircumflex put + extendedencoding 97 /Idieresis put + extendedencoding 98 /idieresis put + extendedencoding 99 /Igrave put + extendedencoding 100 /igrave put + extendedencoding 101 /Ntilde put + extendedencoding 102 /ntilde put + extendedencoding 103 /Oacute put + extendedencoding 104 /oacute put + extendedencoding 105 /Ocircumflex put + extendedencoding 106 /ocircumflex put + extendedencoding 107 /Odieresis put + extendedencoding 108 /odieresis put + extendedencoding 109 /Ograve put + extendedencoding 110 /ograve put + extendedencoding 111 /Otilde put + extendedencoding 112 /otilde put + extendedencoding 113 /Scaron put + extendedencoding 114 /scaron put + extendedencoding 115 /Uacute put + extendedencoding 116 /uacute put + extendedencoding 117 /Ucircumflex put + extendedencoding 118 /ucircumflex put + extendedencoding 119 /Udieresis put + extendedencoding 120 /udieresis put + extendedencoding 121 /Ugrave put + extendedencoding 122 /ugrave put + extendedencoding 123 /Ydieresis put + extendedencoding 124 /ydieresis put + extendedencoding 125 /Zcaron put + extendedencoding 126 /zcaron put + extendedencoding 127 /space put +} def + +/makeExtendedFont { + findfont + dup length dict /newdict exch def + { 1 index /FID ne + { newdict 3 1 roll put } + { pop pop } + ifelse + } forall + newdict /Encoding extendedencoding put + newdict /UniqueID newdict /UniqueID get 1 add put + newdict definefont pop +} def +/flagsep 1.60 300 mul def % 1.60 stepsizes +/scv 149508 def /sf 962 string def +/fa {/p 0 def /chr exch -3 bitshift 127 and def {sf exch p add dup /p exch def chr put} forall} def +[ 74 62 70 54 29 55 36 37 19 26 45 40 41 50 45 52 19 73 11 68 ] 1567304784 fa +[ 961 ] 1341740116 fa +[ 12 4 5 4 4 2 4 3 3 7 7 3 5 5 4 5 4 2 5 3 ] 1969419526 fa +[ 96 4 4 3 2 4 11 2 6 23 13 16 8 3 28 13 8 3 6 11 ] 387152134 fa +[ 268 4 13 12 5 4 4 5 4 5 3 2 4 3 4 8 3 3 9 2 ] 305899779 fa +[ 369 3 4 9 3 3 9 2 4 3 4 7 4 4 4 9 5 3 5 4 ] 477458695 fa +[ 498 4 36 4 37 4 42 4 4 37 4 4 35 4 4 5 13 3 4 4 ] 1130513667 fa +[ 759 3 5 33 4 5 9 29 5 4 3 5 4 4 5 4 4 5 4 3 ] 1205319942 fa +[ 902 8 4 2 3 4 3 4 4 3 2 3 9 ] 1708988675 fa +[ 468 6 4 10 3 30 5 3 24 40 4 3 3 3 3 8 23 1 1 1 ] 123455756 fa +[ 664 23 4 2 13 66 4 5 9 ] 2061720845 fa +[ 795 ] 1622189328 fa +[ 463 45 40 41 50 45 84 ] 304180545 fa +[ 494 40 41 49 45 43 84 ] 251711819 fa +[ 149 203 37 144 ] 358262127 fa +[ 456 142 52 ] 95949173 fa +[ 0 13 13 10 65 36 6 26 38 17 13 53 4 13 13 25 36 183 7 140 ] 1751712121 fa +[ 839 5 13 12 13 13 48 ] 1943250302 fa +[ 30 164 254 7 42 4 36 4 18 1 18 4 46 3 1 41 4 39 4 41 ] 499619205 fa +[ 798 1 3 1 ] 1277775234 fa +[ 76 32 135 79 99 8 246 43 30 160 ] 734015880 fa +[ 265 70 36 12 25 87 4 36 4 37 4 46 4 41 43 83 4 83 41 3 ] 1546658194 fa +[ 193 49 180 8 17 134 ] 831070621 fa +[ 353 366 ] 1033403809 fa +[ 266 1 190 39 40 41 50 45 43 45 ] 1758436783 fa +[ 423 8 109 ] 508918194 fa +[ 328 6 30 6 31 6 269 ] 212071871 fa +[ 390 357 2 ] 1671244225 fa +[ 500 ] 347047368 fa +[ 558 ] 1276946910 fa +[ 651 ] 2109048312 fa +[ 644 ] 1914352160 fa +[ 520 ] 471204394 fa +[ 512 5 2 ] 1930983991 fa +[ 665 ] 154021439 fa +[ 513 ] 777103941 fa +[ 514 ] 260959830 fa +[ 530 239 ] 1284535922 fa +[ 510 ] 1982423675 fa +[ 150 ] 1969948305 fa +[ 511 7 134 ] 1407991454 fa +[ 144 371 ] 1896661664 fa +[ 464 52 ] 1444653737 fa +[ 509 81 ] 1712172720 fa +[ 110 11 32 24 22 18 40 12 54 7 17 19 18 19 22 13 377 94 9 11 ] 889612 fa +[ 954 ] 1802916616 fa +[ 80 146 51 78 37 84 8 8 73 5 44 45 33 9 73 9 130 9 11 12 ] 1808121621 fa +[ 19 42 3 22 8 82 63 23 25 13 8 5 176 248 40 73 12 13 13 12 ] 1752602397 fa +[ 22 10 37 42 1 2 19 26 6 38 17 13 38 11 21 13 16 9 27 9 ] 1598682919 fa +[ 405 9 13 46 49 50 50 213 18 12 13 13 12 45 10 ] 160257827 fa +[ 1 8 8 6 10 10 16 11 14 8 23 19 13 19 13 7 15 3 9 8 ] 882894639 fa +[ 234 40 9 15 6 7 6 25 36 37 19 6 47 16 40 41 50 45 43 6 ] 185215791 fa +[ 733 19 37 16 12 13 3 3 12 6 6 6 7 6 7 6 6 6 45 10 ] 1706915629 fa +[ 24 10 37 45 2 17 5 1 15 4 7 5 8 8 17 17 13 11 8 26 ] 1713964852 fa +[ 284 21 13 25 18 18 19 18 28 1 7 28 2 4 106 24 3 2 32 36 ] 1218620208 fa +[ 695 62 1 7 13 1 7 2 37 4 8 5 13 12 13 13 12 45 5 1 ] 1317868340 fa +[ 960 ] 75399990 fa +[ 45 9 155 6 245 68 21 98 60 109 ] 1430691640 fa +[ 20 27 15 25 8 33 173 13 45 37 83 170 5 34 8 115 40 12 13 13 ] 841629509 fa +[ 901 ] 422446918 fa +[ 27 25 37 13 3 40 12 73 49 77 4 33 4 68 89 219 21 27 3 4 ] 560155470 fa +[ 466 6 135 41 7 6 36 6 89 ] 803193686 fa +[ 42 80 1 55 80 1 80 36 37 155 1 263 40 65 ] 189315943 fa +[ 6 31 36 9 43 21 6 185 36 37 210 ] 1031359337 fa +[ 44 9 101 4 4 20 8 80 3 23 30 5 19 17 20 17 15 7 7 36 ] 586694517 fa +[ 552 22 20 16 3 55 42 31 10 33 ] 343336822 fa +[ 7 4 54 54 10 22 10 20 8 8 53 5 226 12 115 38 17 42 26 13 ] 1808462718 fa +[ 780 32 ] 847653755 fa +[ 3 63 31 408 18 4 18 6 22 13 15 3 32 9 17 4 15 5 18 4 ] 1627872128 fa +[ 724 83 7 ] 1643402114 fa +[ 228 296 8 25 39 16 159 14 34 ] 670118796 fa +[ 2 2 47 69 19 34 23 20 35 5 187 10 51 2 38 2 39 2 48 2 ] 888380310 fa +[ 680 2 41 2 2 5 13 11 10 40 2 50 80 ] 1392580498 fa +[ 14 25 10 7 22 49 21 22 1 4 10 23 4 13 15 5 16 15 12 3 ] 2114772893 fa +[ 295 30 24 9 28 9 23 19 13 1 8 24 67 16 3 30 3 3 53 9 ] 453068702 fa +[ 694 6 9 20 11 23 1 23 23 22 8 5 1 24 41 9 11 4 5 1 ] 1393470366 fa +[ 944 8 ] 1770206109 fa +[ 10 5 25 6 4 7 42 39 25 20 4 4 7 2 14 17 126 5 32 5 ] 113705892 fa +[ 442 25 4 6 114 27 38 42 32 25 20 47 19 112 ] 998588323 fa +[ 79 19 131 109 36 37 74 70 1 59 8 34 3 25 5 9 3 80 11 27 ] 1221405612 fa +[ 912 9 11 ] 273962927 fa +[ 8 230 25 23 6 17 130 31 61 64 16 127 32 ] 1881483187 fa +[ 130 683 ] 1406620603 fa +[ 18 10 32 25 5 3 10 3 143 50 13 9 61 93 86 1 1 180 48 58 ] 1980878788 fa +[ 861 13 9 4 12 8 17 3 ] 1447963591 fa +[ 67 143 8 128 115 435 19 2 ] 477757388 fa +[ 490 35 ] 1151262673 fa +[ 5 70 67 32 37 16 14 7 27 18 142 301 17 90 103 ] 1523362782 fa +[ 117 14 33 38 17 13 20 26 3 453 89 3 8 113 10 ] 1908448236 fa +sf cvx exec +%%BeginResource: procset grops 1.17 2 +/setpacking where{ +pop +currentpacking +true setpacking +}if +/grops 120 dict dup begin +/SC 32 def +/A/show load def +/B{0 SC 3 -1 roll widthshow}bind def +/C{0 exch ashow}bind def +/D{0 exch 0 SC 5 2 roll awidthshow}bind def +/E{0 rmoveto show}bind def +/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def +/G{0 rmoveto 0 exch ashow}bind def +/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/I{0 exch rmoveto show}bind def +/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def +/K{0 exch rmoveto 0 exch ashow}bind def +/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/M{rmoveto show}bind def +/N{rmoveto 0 SC 3 -1 roll widthshow}bind def +/O{rmoveto 0 exch ashow}bind def +/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/Q{moveto show}bind def +/R{moveto 0 SC 3 -1 roll widthshow}bind def +/S{moveto 0 exch ashow}bind def +/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def +/SF{ +findfont exch +[exch dup 0 exch 0 exch neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/MF{ +findfont +[5 2 roll +0 3 1 roll +neg 0 0]makefont +dup setfont +[exch/setfont cvx]cvx bind def +}bind def +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def +/MANUAL{ +statusdict begin/manualfeed true store end +}bind def +/PLG{ +gsave newpath clippath pathbbox grestore +exch pop add exch pop +}bind def +/BP{ +/level0 save def +1 setlinecap +1 setlinejoin +72 RES div dup scale +LS{ +90 rotate +}{ +0 PL translate +}ifelse +1 -1 scale +}bind def +/EP{ +level0 restore +showpage +}bind def +/DA{ +newpath arcn stroke +}bind def +/SN{ +transform +.25 sub exch .25 sub exch +round .25 add exch round .25 add exch +itransform +}bind def +/DL{ +SN +moveto +SN +lineto stroke +}bind def +/DC{ +newpath 0 360 arc closepath +}bind def +/TM matrix def +/DE{ +TM currentmatrix pop +translate scale newpath 0 0 .5 0 360 arc closepath +TM setmatrix +}bind def +/RC/rcurveto load def +/RL/rlineto load def +/ST/stroke load def +/MT/moveto load def +/CL/closepath load def +/FL{ +currentgray exch setgray fill setgray +}bind def +/BL/fill load def +/LW/setlinewidth load def +/RE{ +findfont +dup maxlength 1 index/FontName known not{1 add}if dict begin +{ +1 index/FID ne{def}{pop pop}ifelse +}forall +/Encoding exch def +dup/FontName exch def +currentdict end definefont pop +}bind def +/DEFS 0 def +/EBEGIN{ +moveto +DEFS begin +}bind def +/EEND/end load def +/CNT 0 def +/level1 0 def +/PBEGIN{ +/level1 save def +translate +div 3 1 roll div exch scale +neg exch neg exch translate +0 setgray +0 setlinecap +1 setlinewidth +0 setlinejoin +10 setmiterlimit +[]0 setdash +/setstrokeadjust where{ +pop +false setstrokeadjust +}if +/setoverprint where{ +pop +false setoverprint +}if +newpath +/CNT countdictstack def +userdict begin +/showpage{}def +}bind def +/PEND{ +clear +countdictstack CNT sub{end}repeat +level1 restore +}bind def +end def +/setpacking where{ +pop +setpacking +}if +%%EndResource +%%IncludeResource: font Times-BoldItalic +%%IncludeResource: font Times-Roman +%%IncludeResource: font Times-Bold +%%IncludeResource: font Courier +%%IncludeResource: font Times-Italic +%%IncludeResource: font AvantGarde-Book +%%IncludeResource: font AvantGarde-Demi +%%IncludeResource: font AvantGarde-BookOblique +%%IncludeResource: font AvantGarde-DemiOblique +%%IncludeResource: font Bookman-Light +%%IncludeResource: font Bookman-Demi +%%IncludeResource: font Bookman-LightItalic +%%IncludeResource: font Bookman-DemiItalic +%%IncludeResource: font Courier-Bold +%%IncludeResource: font Courier-Oblique +%%IncludeResource: font Courier-BoldOblique +%%IncludeResource: font Helvetica +%%IncludeResource: font Helvetica-Bold +%%IncludeResource: font Helvetica-Oblique +%%IncludeResource: font Helvetica-BoldOblique +%%IncludeResource: font NewCenturySchlbk-Roman +%%IncludeResource: font NewCenturySchlbk-Bold +%%IncludeResource: font NewCenturySchlbk-Italic +%%IncludeResource: font NewCenturySchlbk-BoldItalic +%%IncludeResource: font Palatino-Roman +%%IncludeResource: font Palatino-Bold +%%IncludeResource: font Palatino-Italic +%%IncludeResource: font Palatino-BoldItalic +grops begin/DEFS 52 dict def DEFS begin/u{.001 mul}bind def end/RES 72 +def/PL PLG def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron +/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent +/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen +/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon +/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O +/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex +/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y +/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft +/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl +/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen +/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft +/logicalnot/minus/registered/macron/degree/plusminus/twosuperior +/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior +/ordmasculine/guilsinglright/onequarter/onehalf/threequarters +/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE +/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex +/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn +/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla +/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis +/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash +/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def +/Palatino-BoldItalic@0 ENC0/Palatino-BoldItalic RE/Palatino-Italic@0 +ENC0/Palatino-Italic RE/Palatino-Bold@0 ENC0/Palatino-Bold RE +/Palatino-Roman@0 ENC0/Palatino-Roman RE/NewCenturySchlbk-BoldItalic@0 +ENC0/NewCenturySchlbk-BoldItalic RE/NewCenturySchlbk-Italic@0 ENC0 +/NewCenturySchlbk-Italic RE/NewCenturySchlbk-Bold@0 ENC0 +/NewCenturySchlbk-Bold RE/NewCenturySchlbk-Roman@0 ENC0 +/NewCenturySchlbk-Roman RE/Helvetica-BoldOblique@0 ENC0 +/Helvetica-BoldOblique RE/Helvetica-Oblique@0 ENC0/Helvetica-Oblique RE +/Helvetica-Bold@0 ENC0/Helvetica-Bold RE/Helvetica@0 ENC0/Helvetica RE +/Courier-BoldOblique@0 ENC0/Courier-BoldOblique RE/Courier-Oblique@0 +ENC0/Courier-Oblique RE/Courier-Bold@0 ENC0/Courier-Bold RE +/Bookman-DemiItalic@0 ENC0/Bookman-DemiItalic RE/Bookman-LightItalic@0 +ENC0/Bookman-LightItalic RE/Bookman-Demi@0 ENC0/Bookman-Demi RE +/Bookman-Light@0 ENC0/Bookman-Light RE/AvantGarde-DemiOblique@0 ENC0 +/AvantGarde-DemiOblique RE/AvantGarde-BookOblique@0 ENC0 +/AvantGarde-BookOblique RE/AvantGarde-Demi@0 ENC0/AvantGarde-Demi RE +/AvantGarde-Book@0 ENC0/AvantGarde-Book RE/Times-Italic@0 ENC0 +/Times-Italic RE/Courier@0 ENC0/Courier RE/Times-Bold@0 ENC0/Times-Bold +RE/Times-Roman@0 ENC0/Times-Roman RE/Times-BoldItalic@0 ENC0 +/Times-BoldItalic RE +%%EndProlog +%%Page: T-1 1 +%%BeginPageSetup +BP +%%EndPageSetup +69.336 164 EBEGIN +0 0.15 0.65 setrgbcolor +EEND/F0 24/Times-BoldItalic@0 SF 6(Mup)273.996 196 S -2 4 +(Music Publisher)194.652 228 T -2 4(User's Guide)217.344 260 T 69.336 +364 EBEGIN +0 0 0 setrgbcolor +EEND 232 702 176 176 -61 61 221.336 440.6 PBEGIN +%%BeginDocument: mugex1.ps +%%BoundingBox: 232 702 408 763 +save +1445575900 1445576686 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +1 linenum +% S_FEED +684.29 1163.00 900.00 5 1.000000 1.000000 stf +% S_CLEFSIG +264.08 725.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +292.78 719.00 1.000000 4n +0.70 setlinewidth +296.46 719.75 moveto +296.46 740.00 lineto stroke +320.08 716.00 1.000000 4n +323.76 716.75 moveto +323.76 737.00 lineto stroke +351.62 713.00 1.000000 2n +345.17 713.00 moveto +358.07 713.00 lineto stroke +355.52 713.75 moveto +355.52 734.00 lineto stroke +restore +% S_BAR +5 linenum +0.70 setlinewidth +395.65 743.00 moveto +395.65 719.00 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: +%%Pages: 2 +%%EndDocument +end PEND 69.336 638.6 EBEGIN +0 0.15 0.65 setrgbcolor +EEND/F0 14/Times-Roman@0 SF(Mup V)256.478 670.6 Q(ersion 5.3)-1.554 E +69.336 694.6 EBEGIN +0 0 0 setrgbcolor +EEND EP +%%Page: T-2 2 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF(Mup Music Publisher User')69.336 420 Q 2.5(sG) +-.55 G(uide \212 Mup V)-2.5 E(ersion 5.3)-1.11 E 5.20869.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.2598.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( 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 or 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 or 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 or 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 or or 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; 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+; 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> and 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;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; <> 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; <><><> 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 a c+; 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 "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 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>, , , or .)-.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; e3<\\n>; a2; e'5;)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 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(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 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(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 +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(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(> 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(> 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(> be-)-2.5 E +(fore a note group.)138.476 420 Q F1 -.92(Va)69.336 432 S(lue).92 E F0 +(............... 0 to 500).36 E F1(Default)69.336 444 Q F0 +(............ 20).28 E F1(Context)69.336 456 Q F0 +(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E(It is possible to\ + change this parameter in the middle of a measure, using << >>.)138.476 +468 Q F1(Example)69.336 480 Q F0(......... release = 40)1.66 E F1(Name) +69.336 528 Q F0(.............. restcombine)1.95 E F1(Description)69.336 +540 Q F0(..... If the gi)A -.15(ve)-.25 G 2.5(nn).15 G +(umber of measures of rest occur in a ro)-2.5 E 1.3 -.65(w, t)-.25 H(he) +.65 E 2.5(yw)-.15 G(ill be replaced by a multirest.)-2.5 E(This pa-)5 E +(rameter can be o)138.476 552 Q -.15(ve)-.15 G +(rridden by the -c command line option.).15 E +(See the description of the -c option for)5 E +(more complete information on ho)138.476 564 Q 2.5(wt)-.25 G +(he combining is done.)-2.5 E F1 -.92(Va)69.336 576 S(lue).92 E F0 +(............... 2 to 1000 or nothing).36 E F1(Default)69.336 588 Q F0 +(............ not set).28 E F1(Context)69.336 600 Q F0 +(........... score).56 E F1(Example)69.336 612 Q F0 +(......... restcombine = 5)1.66 E(restcombine =)138.476 624 Q +(// turn of)10 E 2.5(fc)-.25 G(ombining)-2.5 E EP +%%Page: 119 125 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(19 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. restsymmult)1.95 E +F1(Description)69.336 108 Q F0(..... Multi-rests are normally dra)A +(wn as a horizontal line on the middle line of the staf)-.15 E +(f, with tw)-.25 E 2.5(ov)-.1 G(ertical)-2.65 E(lines at the end. But t\ +here is an alternate notation style that uses rest symbols \(whole, dou\ +ble whole,)138.476 120 Q +(and quad whole\) when the number of measures is short.)138.476 132 Q +(If this parameter is set to y)5 E 2.5(,t)-.65 G(hat alternate)-2.5 E +(style will be used for multirests of eight measures or less.)138.476 +144 Q F1 -.92(Va)69.336 156 S(lue).92 E F0(............... y or n).36 E +F1(Default)69.336 168 Q F0(............ n).28 E F1(Context)69.336 180 Q +F0(........... score, staf).56 E(f)-.25 E F1(Example)69.336 192 Q F0 +(......... restsymmult = y)1.66 E F1(See also)69.336 204 Q F0 +(........... printmultnum).83 E F1(Name)69.336 252 Q F0 +(.............. rightmar)1.95 E(gin)-.18 E F1(Description)69.336 264 Q +F0(..... sets the amount of white space mar)A +(gin to put at the right side of each page.)-.18 E +(It is speci\214ed in inches)5 E(if the units parameter is set to inche\ +s, or in centimeters if the units parameter is set to cm.)138.476 276 Q +(This pa-)5 E(rameter can only be speci\214ed before an)138.476 288 Q +2.5(ym)-.15 G(usic or block input.)-2.5 E(Mar)5 E(gins are unaf)-.18 E +(fected by the)-.25 E("scale" parameter)138.476 300 Q(.)-.55 E F1 -.92 +(Va)69.336 312 S(lue).92 E F0(............... 0.0 to page).36 E +(width minus 0.5 inches)-.25 E F1(Default)69.336 324 Q F0 +(............ 0.5 inches).28 E F1(Context)69.336 336 Q F0 +(........... score).56 E F1(Example)69.336 348 Q F0(......... rightmar) +1.66 E(gin = 0.3)-.18 E F1(See also)69.336 360 Q F0 +(........... bottommar).83 E(gin, leftmar)-.18 E(gin, topmar)-.18 E +(gin, page)-.18 E(width, units)-.25 E F1(Name)69.336 408 Q F0 +(.............. scale)1.95 E F1(Description)69.336 420 Q F0 +(..... Scale the printed output by the speci\214ed f)A(actor)-.1 E 2.5 +(.F)-.55 G(or e)-2.65 E(xample, scale=2 prints e)-.15 E -.15(ve)-.25 G +(rything twice as).15 E(lar)138.476 432 Q +(ge as normal, while scale=0.5 prints e)-.18 E -.15(ve)-.25 G +(rything at half size.).15 E(This parameter can only be speci-)5 E +(\214ed before an)138.476 444 Q 2.5(ym)-.15 G(usic or block input.)-2.5 +E F1 -.92(Va)69.336 456 S(lue).92 E F0 +(............... A number between 0.1 and 10.0).36 E F1(Default)69.336 +468 Q F0(............ 1.0).28 E F1(Context)69.336 480 Q F0 +(........... score).56 E F1(Example)69.336 492 Q F0 +(......... scale=0.95)1.66 E F1(See also)69.336 504 Q F0 +(........... packf).83 E(act, pack)-.1 E -.15(ex)-.1 G(p, staf).15 E +(fscale)-.25 E EP +%%Page: 120 126 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(20 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. scorepad)1.95 E F1 +(Description)69.336 108 Q F0 +(..... sets the amount of padding \(white space\) to lea)A .3 -.15(ve b) +-.2 H(etween scores, accounting for all the things that).15 E +(protrude from both scores.)138.476 120 Q(Either a single number)5 E 2.5 +(,g)-.4 G -.25(iv)-2.5 G(ing a minimum amount, or tw).25 E 2.5(on)-.1 G +(umbers,)-2.5 E(gi)138.476 132 Q +(ving a minimum and maximum, can be speci\214ed. The)-.25 E 2.5(ya)-.15 +G(re speci\214ed in stepsizes.)-2.5 E(If only the)5 E +(minimum is speci\214ed, and it is lar)138.476 144 Q(ger than the def) +-.18 E(ault maximum of 2, the maximum will be adjust-)-.1 E +(ed to equal the minimum.)138.476 156 Q +(Depending on the setting of the scoresep parameter)5 E 2.5(,t)-.4 G +(he maximum may)-2.5 E(be e)138.476 168 Q +(xceeded; see the description of scoresep for ho)-.15 E 2.5(wt)-.25 G +(hese parameters interact to determine the)-2.5 E +(placement of the scores.)138.476 180 Q(If a ne)5 E -.05(ga)-.15 G(ti) +.05 E .3 -.15(ve v)-.25 H(alue is speci\214ed for scorepad, some o)-.1 E +-.15(ve)-.15 G(rlap may occur).15 E(,)-.4 E +(\(subject to the interaction with scoresep\).)138.476 192 Q +(Specifying a ne)5 E -.05(ga)-.15 G(ti).05 E .3 -.15(ve v)-.25 H +(alue may be particularly useful)-.1 E(when things protrude do)138.476 +204 Q(wnw)-.25 E(ard from the top score and upw)-.1 E +(ard from the bottom score, b)-.1 E(ut at dif-)-.2 E +(ferent places horizontally)138.476 216 Q 2.5(,s)-.65 G(uch that it is \ +actually safe to put the scores closer together without colli-)-2.5 E +(sion, e)138.476 228 Q -.15(ve)-.25 G 2.5(nt).15 G(hough Mup can')-2.5 E +2.5(tt)-.18 G(ell that it is safe.)-2.5 E(Note, ho)5 E(we)-.25 E -.15 +(ve)-.25 G .8 -.4(r, t).15 H(hat this o).4 E -.15(ve)-.15 G(rrides Mup') +.15 E 2.5(sp)-.55 G(rotection)-2.5 E(ag)138.476 240 Q +(ainst real collisions, so this must be used with care to a)-.05 E -.2 +(vo)-.2 G(id undesired o).2 E -.15(ve)-.15 G(rlaps.).15 E F1 -.92(Va) +69.336 252 S(lue).92 E F0(............... one or tw).36 E 2.5(ow)-.1 G +(hole numbers, in the range from ne)-2.5 E -.05(ga)-.15 G(ti).05 E .3 +-.15(ve t)-.25 H(he height of the page and the height of a).15 E +(page, in stepsizes.)138.476 264 Q(If there are tw)5 E 2.5(on)-.1 G +(umbers, the)-2.5 E 2.5(ya)-.15 G +(re separated by a comma, and the second must)-2.5 E +(be greater than or equal to the \214rst.)138.476 276 Q F1(Default) +69.336 288 Q F0(............ 2,2).28 E F1(Context)69.336 300 Q F0 +(........... score).56 E F1(Example)69.336 312 Q F0 +(......... scorepad = 5)1.66 E(scorepad = -1)138.476 324 Q +(scorepad = 3,10)138.476 336 Q F1(See also)69.336 348 Q F0 +(........... scoresep, staf).83 E(fpad, staf)-.25 E(fsep)-.25 E F1(Name) +69.336 396 Q F0(.............. scoresep)1.95 E F1(Description)69.336 408 +Q F0(..... sets ho)A 2.5(wm)-.25 G(uch space to lea)-2.5 E .3 -.15(ve b) +-.2 H(etween scores; i.e., between the bottom line of the bottom staf) +.15 E 2.5(fo)-.25 G(f)-2.5 E(one score and the top line of the top staf) +138.476 420 Q 2.5(fo)-.25 G 2.5(ft)-2.5 G(he follo)-2.5 E +(wing score. Either a single number)-.25 E 2.5(,g)-.4 G -.25(iv)-2.5 G +(ing a).25 E(minimum amount, or tw)138.476 432 Q 2.5(on)-.1 G +(umbers, gi)-2.5 E(ving a minimum and maximum, can be speci\214ed. The) +-.25 E 2.5(ya)-.15 G(re)-2.5 E(speci\214ed in stepsizes.)138.476 444 Q +(If only the minimum is speci\214ed, and it is lar)5 E(ger than the def) +-.18 E(ault maximum)-.1 E +(of 20, the maximum will be adjusted to equal the minimum.)138.476 456 Q +(Depending on the setting of the)5 E(scorepad parameter)138.476 468 Q +2.5(,t)-.4 G(he maximum may be e)-2.5 E 2.5(xceeded. The)-.15 F +(parameters interact as follo)2.5 E(ws in deter)-.25 E(-)-.2 E +(mining the layout of a page: As man)138.476 480 Q 2.5(ys)-.15 G +(cores are allocated to the page as will \214t \(or until a "ne)-2.5 E +(w-)-.25 E(page" command is encountered\).)138.476 492 Q(Initially)5 E +2.5(,t)-.65 G(he)-2.5 E 2.5(ya)-.15 G(re pack)-2.5 E +(ed together as tightly as the)-.1 E 2.5(yc)-.15 G(an be with-)-2.5 E +(out violating the minimum v)138.476 504 Q +(alues of scorepad and scoresep between an)-.25 E 2.5(yn)-.15 G +(eighboring scores.)-2.5 E(Ne)5 E(xt,)-.15 E(if there is e)138.476 516 Q +(xtra space a)-.15 E -.25(va)-.2 G(ilable at the bottom of the page, th\ +e scores are spread out, increasing the).25 E +(white space between them, b)138.476 528 Q(ut not increasing an)-.2 E +2.5(yb)-.15 G -.15(ey)-2.5 G(ond the maximum scorepad v).15 E 2.5 +(alue. \(Some)-.25 F(may ho)138.476 540 Q(we)-.25 E -.15(ve)-.25 G 2.5 +(ra).15 G(lready be be)-2.5 E(yond the maximum scorepad v)-.15 E +(alue, because the minimum scoresep v)-.25 E(al-)-.25 E +(ue required it.\))138.476 552 Q(This spreading is done without re)5 E +-.05(ga)-.15 G(rd for the maximum scoresep v).05 E 2.5(alue. If)-.25 F +(an)2.5 E 2.5(yo)-.15 G(f)-2.5 E(the inter)138.476 564 Q(-score g)-.2 E +(aps start narro)-.05 E +(wer than others \(because of the minimum scoresep\), the)-.25 E 2.5(ya) +-.15 G(re in-)-2.5 E(creased \214rst, in an attempt to e)138.476 576 Q +-.15(ve)-.25 G 2.5(no).15 G(ut the dif)-2.5 E 2.5(ferences. If)-.25 F +(the maximum scorepad v)2.5 E(alue is reached)-.25 E(or e)138.476 588 Q +(xceeded between all the scores, and there is still e)-.15 E +(xtra space a)-.15 E -.25(va)-.2 G(ilable at the bottom of the page,).25 +E(then the scores are spread out some more, increasing the white space \ +between them, this time ig-)138.476 600 Q(noring the scorepad v)138.476 +612 Q(alues, b)-.25 E(ut not increasing an)-.2 E 2.5(yb)-.15 G -.15(ey) +-2.5 G(ond the maximum scoresep v).15 E 2.5(alue. \(Some)-.25 F(may ho) +138.476 624 Q(we)-.25 E -.15(ve)-.25 G 2.5(ra).15 G(lready be be)-2.5 E +(yond the maximum scoresep v)-.15 E(alue, because of the pre)-.25 E +(vious steps.\))-.25 E(If)5 E +(still not all the space is used up, it remains as e)138.476 636 Q +(xtra space at the bottom of the page.)-.15 E F1 -.92(Va)69.336 648 S +(lue).92 E F0(............... one or tw).36 E 2.5(ow)-.1 G(hole numbers\ +, in the range from 6 to the height of the page in stepsizes.)-2.5 E +(If there are)5 E(tw)138.476 660 Q 2.5(on)-.1 G(umbers, the)-2.5 E 2.5 +(ya)-.15 G(re separated by a comma, and the second must be greater than\ + or equal to the)-2.5 E(\214rst.)138.476 672 Q F1(Default)69.336 684 Q +F0(............ 12,20).28 E F1(Context)69.336 696 Q F0 +(........... score).56 E F1(Examples)69.336 708 Q F0 +(........ scoresep = 25).27 E(scoresep = 9,15)138.476 720 Q F1(See also) +69.336 732 Q F0(........... scorepad, staf).83 E(fpad, staf)-.25 E(fsep) +-.25 E EP +%%Page: 121 127 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(21 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. size)1.95 E F1 +(Description)69.336 108 Q F0 +(..... speci\214es what point size to use for te)A +(xt in print, title, left, right, and center statements, and "with")-.15 +E(lists \(i.e., strings that are associated with a particular chord\).) +138.476 120 Q F1 -.92(Va)69.336 132 S(lue).92 E F0 +(............... a number from 1 to 100 inclusi).36 E -.15(ve)-.25 G F1 +(Default)69.336 144 Q F0(............ 12).28 E F1(Context)69.336 156 Q +F0(........... score, staf).56 E(f, header)-.25 E 2.5(,f)-.4 G(ooter) +-2.5 E 2.5(,h)-.4 G(eader2, footer2, top, bottom, top2, bottom2, block) +-2.5 E F1(Example)69.336 168 Q F0(......... size = 9)1.66 E F1(See also) +69.336 180 Q F0(........... font, fontf).83 E(amily)-.1 E 2.5(,l)-.65 G +(yricssize)-2.5 E F1(Name)69.336 228 Q F0(.............. staf)1.95 E +(\215ines)-.25 E F1(Description)69.336 240 Q F0(..... speci\214es ho)A +2.5(wm)-.25 G(an)-2.5 E 2.5(yl)-.15 G(ines to dra)-2.5 E 2.5(wf)-.15 G +(or the staf)-2.5 E(f. Normally)-.25 E 2.5(,t)-.65 G +(here are 5 lines per staf)-2.5 E(f, b)-.25 E(ut a single line)-.2 E +(staf)138.476 252 Q 2.5(fi)-.25 G 2.5(ss)-2.5 G +(ometimes used for percussion, and tablature staf)-2.5 E(fs for v)-.25 E +(arious instruments may ha)-.25 E .3 -.15(ve d)-.2 H(if).15 E(fer)-.25 E +(-)-.2 E(ent numbers of lines.)138.476 264 Q +(Setting this parameter to 1 will produce a single line staf)5 E 2.5 +(f. The)-.25 F(number of)2.5 E(lines can be follo)138.476 276 Q +(wed by "n" to indicate that clef and k)-.25 E .3 -.15(ey s)-.1 H +(ignature are not to be printed. The "n" al-).15 E +(so implies that accidentals are to be ignored and that notes are ne) +138.476 288 Q -.15(ve)-.25 G 2.5(rt).15 G 2.5(ob)-2.5 G 2.5(et)-2.5 G +2.5(ransposed. If)-2.5 F(the num-)2.5 E +(ber of lines is 1, the clef and k)138.476 300 Q .3 -.15(ey s)-.1 H +(ignature are ne).15 E -.15(ve)-.25 G 2.5(rp).15 G(rinted, re)-2.5 E +-.05(ga)-.15 G(rdless of whether or not you add).05 E(the "n," so the "\ +n" is really only meaningful when used with 5. When staf)138.476 312 Q +(\215ines=1, you can only)-.25 E(ha)138.476 324 Q .3 -.15(ve o)-.2 H +(ne note per chord, and the pitch of that note is irrele).15 E -.25(va) +-.25 G(nt, e).25 E(xcept for MIDI output.)-.15 E(Alternate-)5 E(ly) +138.476 336 Q 2.5(,r)-.65 G(ather than specifying "n" you can specify "\ +drum" which means to use the drum clef \(also some-)-2.5 E +(times called the "neutral" clef\).)138.476 348 Q -.4(Wi)5 G +(th the drum clef, no k).4 E .3 -.15(ey s)-.1 H +(ignature is printed, accidentals are ig-).15 E(nored, and notes are ne) +138.476 360 Q -.15(ve)-.25 G 2.5(rt).15 G(ransposed. The v)-2.5 E +(alue used for the clef parameter is used to determine)-.25 E +(the pitch for placement of notes in this case, b)138.476 372 Q +(ut the drum clef of tw)-.2 E 2.5(ov)-.1 G(ertical lines is printed.) +-2.65 E -.15(Fo)138.476 396 S 2.5(rat).15 G(ablature staf)-2.5 E +(f, rather than specifying a number of staf)-.25 E 2.5(fl)-.25 G +(ines as the v)-2.5 E(alue, the k)-.25 E -.15(ey)-.1 G -.1(wo).15 G +(rd "tab" is).1 E(used, optionally follo)138.476 408 Q(wed by a list of\ + strings in parentheses. The strings are listed in order from the)-.25 E +(top line of the tablature staf)138.476 420 Q 2.5(ft)-.25 G 2.5(ot)-2.5 +G(he bottom.)-2.5 E +(Each item in the list has at least a string pitch, which is)5 E 2.5(al) +138.476 432 S(etter from a to g, optionally follo)-2.5 E +(wed by # or &. If there is more than one string ha)-.25 E +(ving the same)-.2 E(letter/accidental, the)138.476 444 Q 2.5(ya)-.15 G +(re distinguished by adding one or more single quote marks \("ticks"\).\ + An oc-)-2.5 E(ta)138.476 456 Q .3 -.15(ve n)-.2 H +(umber can also be speci\214ed.).15 E +(If the list of strings is omitted, standard guitar strings are used,)5 +E(which is tab\( e5 b4 g4 d4 a3 e'3 \).)138.476 468 Q -.8(Ta)5 G +(blature can only be speci\214ed in staf).8 E 2.5(fc)-.25 G(onte)-2.5 E +(xt, not score or)-.15 E -.2(vo)138.476 480 S +(ice, and when a tablature staf).2 E 2.5(fi)-.25 G 2.5(ss)-2.5 G +(peci\214ed, the staf)-2.5 E 2.5(fa)-.25 G(bo)-2.5 E .3 -.15(ve i)-.15 H +2.5(tb).15 G(ecomes a "tabnote" staf)-2.5 E 2.5(fw)-.25 G(hich is a)-2.5 +E(normal 5-line staf)138.476 492 Q 2.5(fc)-.25 G(ontaining music deri) +-2.5 E -.15(ve)-.25 G 2.5(df).15 G(rom the tablature staf)-2.5 E(f.)-.25 +E F1 -.92(Va)69.336 504 S(lue).92 E F0 +(............... 1 or 5, optionally follo).36 E +(wed by "n" or "drum"; or for tablature staf)-.25 E(f, the k)-.25 E -.15 +(ey)-.1 G -.1(wo).15 G(rd "tab" optionally fol-).1 E(lo)138.476 516 Q +(wed by a list of strings, in parentheses.)-.25 E(Setting the staf)5 E +(\215ines parameter will also reinitialize other)-.25 E(parameters: k) +138.476 528 Q -.15(ey)-.1 G 2.5(,t)-.5 G +(ranspose, addtranspose, clef, beamstyle, and defoct.)-2.5 E F1(Default) +69.336 540 Q F0(............ 5).28 E F1(Context)69.336 552 Q F0 +(........... score, staf).56 E(f)-.25 E F1(Examples)69.336 564 Q F0 +(........ staf).27 E(\215ines=1)-.25 E(staf)138.476 576 Q(\215ines=5n) +-.25 E(staf)138.476 588 Q(\215ines = tab)-.25 E +(// standard guitar tablature staf)3.22 E(f)-.25 E(staf)138.476 600 Q +(\215ines = tab \( g3 d3 a2 e2 \))-.25 E(// standard bass guitar)5 E +(staf)138.476 612 Q(\215ines = tab \(d# g b3 g'3\))-.25 E F1(See also) +69.336 624 Q F0(........... clef, k).83 E -.15(ey)-.1 G 2.5(,t)-.5 G +(ranspose, addtranspose)-2.5 E EP +%%Page: 122 128 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(22 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. staf)1.95 E(fpad) +-.25 E F1(Description)69.336 108 Q F0 +(..... sets the minimum amount of space to lea)A .3 -.15(ve b)-.2 H +(etween staf).15 E(fs, accounting for all the things that protrude)-.25 +E(from both staf)138.476 120 Q 2.5(fs. If)-.25 F 2.5(an)2.5 G -2.25 -.15 +(eg a)-2.5 H(ti).15 E .3 -.15(ve v)-.25 H(alue is speci\214ed, some o) +-.1 E -.15(ve)-.15 G(rlap may occur).15 E 2.5(,a)-.4 G +(lthough it will still be)-2.5 E(limited by the v)138.476 132 Q +(alue of the staf)-.25 E(fsep parameter)-.25 E 5(.S)-.55 G +(pecifying a ne)-5 E -.05(ga)-.15 G(ti).05 E .3 -.15(ve v)-.25 H +(alue may be particularly use-)-.1 E(ful when things protrude do)138.476 +144 Q(wnw)-.25 E(ard from the top staf)-.1 E 2.5(fa)-.25 G(nd upw)-2.5 E +(ard from the bottom staf)-.1 E(f, b)-.25 E(ut at dif-)-.2 E +(ferent places horizontally)138.476 156 Q 2.5(,s)-.65 G +(uch that it is actually safe to put the staf)-2.5 E +(fs closer together without colli-)-.25 E(sion, e)138.476 168 Q -.15(ve) +-.25 G 2.5(nt).15 G(hough Mup can')-2.5 E 2.5(tt)-.18 G +(ell that it is safe.)-2.5 E(Note, ho)5 E(we)-.25 E -.15(ve)-.25 G .8 +-.4(r, t).15 H(hat this o).4 E -.15(ve)-.15 G(rrides Mup').15 E 2.5(sp) +-.55 G(rotection)-2.5 E(ag)138.476 180 Q +(ainst real collisions, so this must be used with care to a)-.05 E -.2 +(vo)-.2 G(id undesired o).2 E -.15(ve)-.15 G(rlaps.).15 E F1 -.92(Va) +69.336 192 S(lue).92 E F0(............... a whole number between ne).36 +E -.05(ga)-.15 G(ti).05 E .3 -.15(ve t)-.25 H +(he height of the page and the height of a page, in stepsizes.).15 E F1 +(Default)69.336 204 Q F0(............ 0).28 E F1(Context)69.336 216 Q F0 +(........... score, staf).56 E(f)-.25 E F1(Example)69.336 228 Q F0 +(......... staf)1.66 E(fpad = -2)-.25 E F1(See also)69.336 240 Q F0 +(........... scorepad, scoresep, staf).83 E(fsep)-.25 E F1(Name)69.336 +288 Q F0(.............. staf)1.95 E(fs)-.25 E F1(Description)69.336 300 +Q F0(..... speci\214es the number of staf)A +(fs. It is possible that not all of these staf)-.25 E +(fs will be printed \(see the "visi-)-.25 E(ble" parameter belo)138.476 +312 Q 2.5(wa)-.25 G(nd the -s command line ar)-2.5 E 2.5 +(gument\). Changing)-.18 F(the number of staf)2.5 E(fs causes)-.25 E +(all parameters that had been set in staf)138.476 324 Q 2.5(fa)-.25 G +(nd v)-2.5 E(oice conte)-.2 E(xt to be set back to their def)-.15 E +(ault v)-.1 E 2.5(alues. It)-.25 F(is)2.5 E +(usually preferable to only set the staf)138.476 336 Q 2.5(fp)-.25 G +(arameter once at the be)-2.5 E(ginning of a song, and use the "visi-) +-.15 E(ble" parameter when you w)138.476 348 Q(ant to change which staf) +-.1 E(fs are actually printed, rather than changing the)-.25 E +(number of staf)138.476 360 Q(fs.)-.25 E F1 -.92(Va)69.336 372 S(lue).92 +E F0(............... a number between 1 and 40 inclusi).36 E -.15(ve) +-.25 G(.).15 E F1(Default)69.336 384 Q F0(............ 1).28 E F1 +(Context)69.336 396 Q F0(........... score).56 E F1(Example)69.336 408 Q +F0(......... staf)1.66 E(fs = 12)-.25 E F1(See also)69.336 420 Q F0 +(........... visible).83 E F1(Name)69.336 468 Q F0(.............. staf) +1.95 E(fscale)-.25 E F1(Description)69.336 480 Q F0 +(..... Speci\214es ho)A 2.5(wt)-.25 G 2.5(os)-2.5 G +(cale the size of a staf)-2.5 E 2.5(fr)-.25 G(elati)-2.5 E .3 -.15(ve t) +-.25 H 2.5(ot).15 G(he size of other staf)-2.5 E(fs. A v)-.25 E +(alue of 1.0 yields the)-.25 E(normal size, whereas 0.5 yields a staf) +138.476 492 Q 2.5(ft)-.25 G +(hat is half as high, and 2.0 one that is twice as high as nor)-2.5 E(-) +-.2 E(mal, and so forth. This might be used, for e)138.476 504 Q +(xample, for a piece written for tw)-.15 E 2.5(oi)-.1 G +(nstruments, say pi-)-2.5 E(ano and violin, where you w)138.476 516 Q +(ant the piano part to be written in normal size, b)-.1 E(ut w)-.2 E +(ant to sho)-.1 E 2.5(wt)-.25 G(he vi-)-2.5 E +(olin part in smaller size, such that while the pianist will ha)138.476 +528 Q .3 -.15(ve t)-.2 H(he violin part a).15 E -.25(va)-.2 G +(ilable for reference,).25 E(it w)138.476 540 Q(on')-.1 E 2.5(tt)-.18 G +(ak)-2.5 E 2.5(eu)-.1 G 2.5(pal)-2.5 G(ot of space.)-2.5 E +(Another possible use is to set staf)5 E(fscale in score conte)-.25 E +(xt, to mak)-.15 E 2.5(ea)-.1 G(ll)-2.5 E(staf)138.476 552 Q +(f-related things a dif)-.25 E(ferent size, b)-.25 E(ut lea)-.2 E .3 +-.15(ve o)-.2 H(ther things, lik).15 E 2.5(eh)-.1 G +(eaders and footers, unaf)-2.5 E(fected.)-.25 E F1 -.92(Va)69.336 564 S +(lue).92 E F0(............... 0.1 to 10.0).36 E F1(Default)69.336 576 Q +F0(............ 1.0).28 E F1(Context)69.336 588 Q F0 +(........... score, staf).56 E(f)-.25 E F1(Example)69.336 600 Q F0 +(......... staf)1.66 E(fscale=0.75)-.25 E F1(See also)69.336 612 Q F0 +(........... scale).83 E EP +%%Page: 123 129 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(23 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. staf)1.95 E(fsep) +-.25 E F1(Description)69.336 108 Q F0 +(..... speci\214es the minimum amount of space to lea)A .3 -.15(ve b)-.2 +H(etween an).15 E 2.5(yt)-.15 G .2 -.1(wo a)-2.5 H(djacent staf).1 E +(fs within the same)-.25 E(score. It is speci\214ed in stepsizes, and i\ +s measured from the bottom line of the staf)138.476 120 Q 2.5(fa)-.25 G +(bo)-2.5 E .3 -.15(ve t)-.15 H 2.5(ot).15 G(he top)-2.5 E +(line of the staf)138.476 132 Q 2.5(fb)-.25 G(elo)-2.5 E 1.3 -.65(w. S) +-.25 H(taf).65 E +(fs will be spread wider than this minimum if necessary to pre)-.25 E +-.15(ve)-.25 G(nt things).15 E(from colliding.)138.476 144 Q F1 -.92(Va) +69.336 156 S(lue).92 E F0 +(............... a number from 6 to the height of the page in stepsizes) +.36 E F1(Default)69.336 168 Q F0(............ 10).28 E F1(Context)69.336 +180 Q F0(........... score, staf).56 E(f)-.25 E F1(Example)69.336 192 Q +F0(......... staf)1.66 E(fsep = 14)-.25 E F1(See also)69.336 204 Q F0 +(........... scorepad, scoresep, staf).83 E(fpad)-.25 E F1(Name)69.336 +252 Q F0(.............. stemlen)1.95 E F1(Description)69.336 264 Q F0 +(..... Speci\214es ho)A 2.5(wl)-.25 G +(ong stems should be, in stepsizes.)-2.5 E +(This is for normal-sized chords; grace or cue size)5 E +(chords will gets stems that are 5/7 of this length.)138.476 276 Q +(This length can be o)5 E -.15(ve)-.15 G(rridden on speci\214c chords) +.15 E(using the len attrib)138.476 288 Q(ute in back)-.2 E +(ets before the chord.)-.1 E F1 -.92(Va)69.336 300 S(lue).92 E F0 +(............... 0.0 to 100.0).36 E F1(Default)69.336 312 Q F0 +(............ 7.0).28 E F1(Context)69.336 324 Q F0 +(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)69.336 +336 Q F0(......... stemlen = 0)1.66 E(// to mak)15.19 E 2.5(ea)-.1 G +(ll notes stemless)-2.5 E F1(Name)69.336 384 Q F0 +(.............. stemshorten)1.95 E F1(Description)69.336 396 Q F0 +(..... On beamed chords, Mup will sometimes shorten stems slightly)A 5 +(.T)-.65 G(his parameter lets you control the)-5 E +(maximum amount of shortening that will e)138.476 408 Q -.15(ve)-.25 G +2.5(rb).15 G 2.5(ed)-2.5 G(one. It is speci\214ed in stepsizes.)-2.5 E +F1 -.92(Va)69.336 420 S(lue).92 E F0(............... 0.0 to 2.0).36 E F1 +(Default)69.336 432 Q F0(............ 1.0).28 E F1(Context)69.336 444 Q +F0(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example) +69.336 456 Q F0(......... stemshorten = 0)1.66 E(// ne)12.5 E -.15(ve) +-.25 G 2.5(rs).15 G(horten an)-2.5 E 2.5(ys)-.15 G(tems)-2.5 E EP +%%Page: 124 130 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(24 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. swingunit)1.95 E F1 +(Description)69.336 108 Q F0(..... This parameter only af)A +(fects MIDI output.)-.25 E +(Some styles of music are often written in "swing time,")5 E +(meaning the players are e)138.476 120 Q(xpected to play pairs of notes\ + with the \214rst twice as long as the second,)-.15 E -2.15 -.25(ev e) +138.476 132 T 2.5(nt).25 G(hough the)-2.5 E 2.5(ya)-.15 G +(re written as if the)-2.5 E 2.5(yw)-.15 G +(ere the same duration, or as if the \214rst w)-2.5 E(as three times as) +-.1 E(long as the second.)138.476 144 Q(The most common e)5 E(xample w) +-.15 E(ould be where the written notation sho)-.1 E(ws tw)-.25 E(o)-.1 E +(eighth notes lik)138.476 156 Q 2.5(e8)-.1 G(;; or a dotted rh)-2.5 E +(ythm lik)-.05 E 2.5(e8)-.1 G(.;16; b)-2.5 E(ut the musician "kno)-.2 E +(ws" that the composer real-)-.25 E(ly intended it to be played as if i\ +t were a triplet {4;8;}3; This parameter adjusts the Mup MIDI out-) +138.476 168 Q(put to follo)138.476 180 Q 2.5(wt)-.25 G +(his performance con)-2.5 E -.15(ve)-.4 G 2.5(ntion. If).15 F +(this parameter is set, each measure is di)2.5 E(vided into)-.25 E(se) +138.476 192 Q(gments of durations of "swingunit," starting at the be) +-.15 E(ginning. \(Usually the time signature di)-.15 E(vided)-.25 E +(by swingunit will be an inte)138.476 204 Q(ger)-.15 E 2.5(,b)-.4 G +(ut if not, the last piece will be shorter)-2.7 E 2.5(.\) Then)-.55 F +(within each se)2.5 E(g-)-.15 E +(ment, the time where one group ends and the ne)138.476 216 Q +(xt group starts will be altered in either of these tw)-.15 E(o)-.1 E +(circumstances: \(1\) The current boundary time is halfw)138.476 228 Q +(ay into a swingunit, and each group is at)-.1 E(least half a swingunit\ + long, or \(2\) The current boundary time is 3/4 of the w)138.476 240 Q +(ay into a swingunit, and)-.1 E(the \214rst group is at least 3/4 of a \ +swingunit long, and the second group is at least 1/4 of a swingunit) +138.476 252 Q 2.5(long. In)138.476 264 R(both of these cases, the durat\ +ions are altered so that the meeting point is 2/3 of the w)2.5 E(ay in-) +-.1 E(to the swingunit.)138.476 276 Q F1 -.92(Va)69.336 288 S(lue).92 E +F0(............... A time v).36 E(alue, lik)-.25 E 2.5(e2)-.1 G 2.5(,4) +-2.5 G 2.5(,o)-2.5 G 2.5(r8)-2.5 G 2.5(,o)-2.5 G 2.5(rn)-2.5 G +(ot set to an)-2.5 E 2.5(ything. It)-.15 F(can be a dotted v)2.5 E +(alue lik)-.25 E 2.5(e2)-.1 G 2.5(.o)-2.5 G 2.5(r1)-2.5 G(6.. although) +-2.5 E(dotted v)138.476 300 Q(alues are rarely lik)-.25 E +(ely to be useful.)-.1 E(It can e)5 E -.15(ve)-.25 G 2.5(nb).15 G 2.5 +(eat)-2.5 G(ime e)-2.5 E(xpression lik)-.15 E 2.5(e2)-.1 G +(.-32 although that)-2.5 E(is e)138.476 312 Q -.15(ve)-.25 G 2.5(nl).15 +G(ess lik)-2.5 E(ely to be useful.)-.1 E F1(Default)69.336 324 Q F0 +(............ not set).28 E F1(Context)69.336 336 Q F0 +(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)69.336 +348 Q F0(......... swingunit = 4)1.66 E(swingunit =)138.476 360 Q +(// turn of)12.5 E 2.5(fs)-.25 G(wing)-2.5 E F1(See also)69.336 372 Q F0 +(........... timeunit).83 E F1(Name)69.336 420 Q F0 +(.............. sylposition)1.95 E F1(Description)69.336 432 Q F0 +(..... A | can be used in lyrics at the be)A +(ginning of a syllable \(after an)-.15 E(ything in angle brack)-.15 E +(ets\) to indicate)-.1 E(syllable alignment.)138.476 444 Q(This will o)5 +E -.15(ve)-.15 G(rride the lyricsalign parameter).15 E 2.5(,a)-.4 G +(nd may be useful for aligning)-2.5 E -.15(ve)138.476 456 S +(rse numbers or to mak).15 E 2.5(es)-.1 G(yllables at the be)-2.5 E +(ginning of poetic lines line up.)-.15 E(If the | is not preceded)5 E +(by a number)138.476 468 Q 2.5(,t)-.4 G +(he sylposition parameter speci\214es the def)-2.5 E(ault alignment v) +-.1 E(alue to use. It is the number)-.25 E(of points \(1 point is 1/72 \ +of an inch\) from the horizontal "middle" of the chord to place the lef\ +t)138.476 480 Q(edge of the syllable. Ne)138.476 492 Q -.05(ga)-.15 G +(ti).05 E .3 -.15(ve v)-.25 H +(alues are to the left of the middle, positi)-.1 E .3 -.15(ve t)-.25 H +2.5(ot).15 G(he right, so this v)-2.5 E(alue)-.25 E(is usually ne) +138.476 504 Q -.05(ga)-.15 G(ti).05 E -.15(ve)-.25 G(.).15 E F1 -.92(Va) +69.336 516 S(lue).92 E F0(............... -100 to 100).36 E F1(Default) +69.336 528 Q F0(............ -5).28 E F1(Context)69.336 540 Q F0 +(........... score, staf).56 E(f)-.25 E F1(Example)69.336 552 Q F0 +(......... sylposition = -4)1.66 E F1(See also)69.336 564 Q F0 +(........... lyricsalign).83 E F1(Name)69.336 612 Q F0 +(.............. tabwhitebox)1.95 E F1(Description)69.336 624 Q F0(.....\ + says whether or not to put a small white box behind each fret number o\ +n tablature staf)A 2.5(fs. This)-.25 F(may)2.5 E(mak)138.476 636 Q 2.5 +(et)-.1 G(he music a little easier to read, since the staf)-2.5 E 2.5 +(fl)-.25 G(ines w)-2.5 E(on')-.1 E 2.5(tb)-.18 G 2.5(eg)-2.5 G +(oing through the middle of the)-2.5 E(fret numbers.)138.476 648 Q F1 +-.92(Va)69.336 660 S(lue).92 E F0(...............).36 E F1(y)2.5 E F0 +(or)2.5 E F1(n)2.5 E(Default)69.336 672 Q F0(............ n).28 E F1 +(Context)69.336 684 Q F0(........... score, staf).56 E(f, v)-.25 E(oice) +-.2 E F1(Examples)69.336 696 Q F0(........ tabwhitebox = y).27 E F1 +(See also)69.336 708 Q F0(........... staf).83 E(\215ines)-.25 E EP +%%Page: 125 131 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(25 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. time)1.95 E F1 +(Description)69.336 108 Q F0 +(..... sets the time signature. Music data for each measure is check)A +(ed to ensure that the total time in the)-.1 E(measure for each v) +138.476 120 Q(oice and v)-.2 E(erse adds up to e)-.15 E +(xactly the time signature. Setting the time parameter)-.15 E(will also\ + reinitialize the timeunit parameter and the beamstyle parameter to the\ +ir most recent v)138.476 132 Q(alues)-.25 E +(for the same time signature \(which w)138.476 144 Q(ould be their def) +-.1 E(ault v)-.1 E(alues if the)-.25 E 2.5(yh)-.15 G(ad ne)-2.5 E -.15 +(ve)-.25 G 2.5(rb).15 G(een e)-2.5 E(xplicitly)-.15 E +(set for this time signature\).)138.476 156 Q F1 -.92(Va)69.336 168 S +(lue).92 E F0(............... either a ratio of the form).36 E/F2 10 +/Times-Italic@0 SF(N/D)2.5 E F0(or the w)2.5 E +(ord "cut" or "common." If the ratio form is used,)-.1 E F2(N)2.5 E F0 +(must be)2.5 E(between 1 and 99 inclusi)138.476 180 Q -.15(ve)-.25 G 2.5 +(,a).15 G(nd)-2.5 E F2(D)2.5 E F0(must be 1, 2, 4, 8, 16, 32, or 64.)2.5 +E(The numerator of the time sig-)5 E(nature can be the sum of se)138.476 +192 Q -.15(ve)-.25 G(ral numbers, as in 3+4/4 or 2+3+2/2. Y).15 E +(ou can also ha)-1.1 E .3 -.15(ve s)-.2 H -2.15 -.25(ev e).15 H +(ral frac-).25 E(tions added together)138.476 204 Q 2.5(,a)-.4 G 2.5(si) +-2.5 G 2.5(n3)-2.5 G(/4 + 4/4. It is also possible to pro)-2.5 E +(vide "alternating" time signatures,)-.15 E(where you list tw)138.476 +216 Q 2.5(o\()-.1 G(or more, although tw)-2.5 E 2.5(oi)-.1 G 2.5(st)-2.5 +G(ypical\) time signatures separated by white space.)-2.5 E +(Each measure then uses the ne)138.476 228 Q +(xt time signature in the list. F)-.15 E(or e)-.15 E +(xample, for 3/4 4/4, the \214rst mea-)-.15 E(sure w)138.476 240 Q(ould\ + be in 3/4 time, the second measure in 4/4, the third back in 3/4, the \ +fourth in 4/4, and so)-.1 E 2.5(forth. It)138.476 252 R +(is possible to combine all the v)2.5 E(arious comple)-.25 E +(xities, with things lik)-.15 E 2.5(e3)-.1 G(+4/8 + 2+3/4 4+3/4)-2.5 E +(although that w)138.476 264 Q(ould be v)-.1 E(ery uncommon.)-.15 E +(The time signature can optionally be follo)5 E(wed by the let-)-.25 E +(ter n to specify that the time signature is not to be printed.)138.476 +276 Q(Or it can be follo)5 E(wed by the letter y)-.25 E(,)-.65 E +(which causes alternating time signatures to be treated dif)138.476 288 +Q(ferently)-.25 E 5(.B)-.65 G 2.5(yd)-5 G(ef)-2.5 E +(ault, the alternating signa-)-.1 E(ture are printed just once, as a li\ +st, and the performer has to remember that each subsequent mea-)138.476 +300 Q(sure has a dif)138.476 312 Q(ferent time signature.)-.25 E +(Using y forces Mup to print the appropriate time signature on)5 E +(each measure.)138.476 324 Q F1(Default)69.336 336 Q F0 +(............ 4/4).28 E F1(Context)69.336 348 Q F0(........... score).56 +E F1(Examples)69.336 360 Q F0(........ time = 6/8).27 E(time = cut) +138.476 372 Q(time = 13/16n)138.476 384 Q(time = 2+3+4 / 8)138.476 396 Q +(// additi)10 E .3 -.15(ve n)-.25 H(umerator).15 E(time = 3/4 + 4/4) +138.476 408 Q(// fractions added together)10 E(time = 4/4 3/4)138.476 +420 Q(// alternating)15 E(time = 3/4 6/8 y)138.476 432 Q +(// alternating, printing time sig on e)10 E -.15(ve)-.25 G(ry measure) +.15 E F1(See also)69.336 444 Q F0(........... timeunit).83 E F1(Name) +69.336 492 Q F0(.............. timeunit)1.95 E F1(Description)69.336 504 +Q F0(..... sets the def)A +(ault time unit. If the \214rst note of a measure has no time v)-.1 E +(alue speci\214ed, the v)-.25 E(alue of the)-.25 E +(timeunit parameter will be used.)138.476 516 Q +(If the time signature is changed, the timeunit parameter re)5 E -.15 +(ve)-.25 G(rts).15 E(back to its pre)138.476 528 Q(vious v)-.25 E +(alue for that time signature, which def)-.25 E(aults to the v)-.1 E +(alue of the denominator)-.25 E(\(bottom number\) of the ne)138.476 540 +Q 2.5(wt)-.25 G(ime signature.)-2.5 E F1 -.92(Va)69.336 552 S(lue).92 E +F0(............... 1/4, 1/2, 1, 2, 4, 8, 16, 32, 64, 128, or 256 repres\ +enting quadruple whole, double whole, whole, half,).36 E(quarter)138.476 +564 Q 2.5(,e)-.4 G +(ighth, sixteenth, thirty-second, sixty-fourth, 128th, or 256th, follo) +-2.5 E(wed by zero or more)-.25 E(dots. Each dot adds 50% of the pre) +138.476 576 Q(vious note or dot to the time.)-.25 E +(It can also be a time e)5 E(xpression,)-.15 E(lik)138.476 588 Q 2.5(e2) +-.1 G(+8 or 1-4+16.)-2.5 E(The time v)5 E +(alue must be less than or equal to the time signature.)-.25 E +(The timeunit)5 E -.25(va)138.476 600 S +(lue can be reinitialized indirectly by setting the time parameter).25 E +5(.S)-.55 G(etting the time parameter will)-5 E +(set the timeunit to the v)138.476 612 Q +(alue used most recently for that time signature.)-.25 E F1(Default) +69.336 624 Q F0 +(............ The denominator \(bottom number\) of the time signature) +.28 E F1(Context)69.336 636 Q F0(........... score, staf).56 E(f, v)-.25 +E(oice)-.2 E F1(Examples)69.336 648 Q F0(........ timeunit = 2).27 E +(timeunit = 4.)138.476 660 Q(timeunit = 2 + 8)138.476 672 Q F1(See also) +69.336 684 Q F0(........... swingunit, time).83 E EP +%%Page: 126 132 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(26 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. topmar)1.95 E(gin) +-.18 E F1(Description)69.336 108 Q F0 +(..... sets the amount of white space mar)A +(gin to put at the top of each page.)-.18 E +(It is speci\214ed in inches if the)5 E(units parameter is set to inche\ +s, or in centimeters if the units parameter is set to cm.)138.476 120 Q +(This parameter)5 E(can only be speci\214ed before an)138.476 132 Q 2.5 +(ym)-.15 G(usic or block input.)-2.5 E(Mar)5 E(gins are unaf)-.18 E +(fected by the "scale" pa-)-.25 E(rameter)138.476 144 Q(.)-.55 E F1 -.92 +(Va)69.336 156 S(lue).92 E F0 +(............... 0.0 to pageheight minus 0.5 inches).36 E F1(Default) +69.336 168 Q F0(............ 0.5 inches).28 E F1(Context)69.336 180 Q F0 +(........... score).56 E F1(Example)69.336 192 Q F0(......... topmar) +1.66 E(gin = 0.8)-.18 E F1(See also)69.336 204 Q F0 +(........... bottommar).83 E(gin, leftmar)-.18 E(gin, rightmar)-.18 E +(gin, pageheight, units)-.18 E F1(Name)69.336 252 Q F0 +(.............. transpose)1.95 E F1(Description)69.336 264 Q F0 +(..... specify by what interv)A(al to transpose the music data.)-.25 E +(The interv)5 E(al can be lar)-.25 E(ger than an octa)-.18 E -.15(ve)-.2 +G 2.5(,b).15 G(ut)-2.7 E(must be a v)138.476 276 Q(alid interv)-.25 E(a\ +l \(e.g., there is no such thing as a perfect 6th\). It is an error to \ +specify a trans-)-.25 E(position v)138.476 288 Q(alue which w)-.25 E +(ould result in a k)-.1 E .3 -.15(ey s)-.1 H +(ignature with more than 7 \215ats or sharps.).15 E(It is also an)5 E +(error if transposition w)138.476 300 Q +(ould result in a note requiring a triple sharp or triple \215at.)-.1 E +F1 -.92(Va)69.336 312 S(lue).92 E F0(............... the w).36 E +(ord "up" or "do)-.1 E(wn," follo)-.25 E(wed by an interv)-.25 E +(al and a whole number greater than 0.)-.25 E(The interv)5 E(al is)-.25 +E(one of major)138.476 324 Q 2.5(,m)-.4 G(inor)-2.5 E 2.5(,a)-.4 G +(ugmented, diminished, or perfect.)-2.5 E(The interv)5 E +(als can be abbre)-.25 E(viated to their)-.25 E +(\214rst 3 letters \(maj, min, aug, dim, or per\).)138.476 336 Q +(The section on transposition lists transposition interv)5 E(als)-.25 E +(and gi)138.476 348 Q -.15(ve)-.25 G 2.5(sf).15 G(urther details.)-2.5 E +(Depending on which k)5 E .3 -.15(ey s)-.1 H +(ignature you are transposing from, some trans-).15 E(position interv) +138.476 360 Q(als may not w)-.25 E(ork because the)-.1 E 2.5(yr)-.15 G +(esult in more than 7 \215ats or sharps.)-2.5 E(There is also an-)5 E +(other parameter called addtranspose.)138.476 372 Q -.8(Ty)5 G +(pically you w).8 E(ould use the transpose parameter to change)-.1 E +(the k)138.476 384 Q .3 -.15(ey o)-.1 H 2.5(fi).15 G(ndi)-2.5 E +(vidual staf)-.25 E(fs \(for transposing instruments\), and then use th\ +e addtranspose parameter)-.25 E(if you w)138.476 396 Q +(ant to change the k)-.1 E .3 -.15(ey o)-.1 H 2.5(ft).15 G +(he entire score.)-2.5 E +(But either of these parameters can be used either)5 E -.1(wa)138.476 +408 S 3.8 -.65(y. I).1 H 2.5(na).65 G .3 -.15(ny c)-2.5 H +(ase, for each staf).15 E(f, and for the score, the v)-.25 E +(alues of transpose and addtranspose are)-.25 E +("added" to \214nd the transposition for that staf)138.476 420 Q 2.5(fo) +-.25 G 2.5(rs)-2.5 G(core.)-2.5 E F1(Default)69.336 432 Q F0 +(............ up perfect 1 \(i.e., no transposition\)).28 E F1(Context) +69.336 444 Q F0(........... score, staf).56 E(f)-.25 E F1(Examples) +69.336 456 Q F0(........ transpose = up minor 3).27 E(transpose = do) +138.476 468 Q(wn perfect 4)-.25 E F1(See also)69.336 480 Q F0 +(........... addtranspose, k).83 E -.15(ey)-.1 G F1(Name)69.336 528 Q F0 +(.............. units)1.95 E F1(Description)69.336 540 Q F0 +(..... Speci\214es whether mar)A(gin and page size parameters are speci\ +\214ed in inches or in centimeters.)-.18 E F1 -.92(Va)69.336 552 S(lue) +.92 E F0(............... inches or cm).36 E F1(Default)69.336 564 Q F0 +(............ inches).28 E F1(Context)69.336 576 Q F0(........... score) +.56 E F1(Example)69.336 588 Q F0(......... units = cm)1.66 E F1 +(See also)69.336 600 Q F0(........... topmar).83 E(gin, bottommar)-.18 E +(gin leftmar)-.18 E(gin, rightmar)-.18 E(gin, pageheight, page)-.18 E +(width)-.25 E EP +%%Page: 127 133 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(27 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. vcombine)1.95 E F1 +(Description)69.336 108 Q F0 +(..... This parameter tells Mup to combine the speci\214ed v)A +(oices onto a single stem whene)-.2 E -.15(ve)-.25 G 2.5(rp).15 G +(ossible.)-2.5 E(One common use w)138.476 120 Q(ould be if you w)-.1 E +(ant multiple v)-.1 E(oices for MIDI purposes, b)-.2 E(ut w)-.2 E +(ant them printed)-.1 E(on the same stems.)138.476 132 Q +(Another typical use w)5 E +(ould be to obtain a printing style common for h)-.1 E(ymns and)-.05 E +(certain other styles of music, where the tw)138.476 144 Q 2.5(ov)-.1 G +(oices on each staf)-2.7 E 2.5(fa)-.25 G(re printed on one common stem) +-2.5 E(whene)138.476 156 Q -.15(ve)-.25 G 2.5(rp).15 G(ossible, b)-2.5 E +(ut when a note is shared between tw)-.2 E 2.5(ov)-.1 G(oices, tw)-2.7 E +2.5(oo)-.1 G(pposing stems are used to)-2.5 E(mak)138.476 168 Q 2.5(ei) +-.1 G 2.5(tc)-2.5 G(lear the note is indeed shared.)-2.5 E(The v)5 E +(alue of this parameter is a list of v)-.25 E(oices plus an op-)-.2 E +(tional quali\214er)138.476 180 Q 5(.T)-.55 G(he list format is lik)-5 E +2.5(ee)-.1 G(lse)-2.5 E(where for v)-.25 E(oices; common e)-.2 E +(xamples w)-.15 E(ould be)-.1 E/F2 10/Courier@0 SF(1,2)2.5 E F0(or)2.5 E +F2(1-3)138.476 192 Q F0(or)2.5 E F2(2-3)2.5 E F0 5(.O)C(rder of v)-5 E +(oices is signi\214cant: sometimes Mup may ha)-.2 E .3 -.15(ve t)-.2 H +2.5(oc).15 G(hoose between tw)-2.5 E 2.5(op)-.1 G(os-)-2.5 E +(sible combinations, so v)138.476 204 Q +(oices listed \214rst get priority)-.2 E 5(.T)-.65 G(he list of v)-5 E +(oices can be follo)-.2 E(wed by a quali-)-.25 E +(\214er to specify what happens when v)138.476 216 Q(oices o)-.2 E -.15 +(ve)-.15 G(rlap. If the quali\214er is "noo).15 E -.15(ve)-.15 G +(rlap," v).15 E(oices will only be)-.2 E +(combined if the bottom note of the higher v)138.476 228 Q +(oice is higher than the top note of the lo)-.2 E(wer v)-.25 E(oice.)-.2 +E(\(That is the typical v)138.476 240 Q(alue for getting the h)-.25 E +(ymn style described abo)-.05 E -.15(ve)-.15 G 2.5(.\) If).15 F +(the quali\214er is "shareone")2.5 E(the bottom note of the top v) +138.476 252 Q(oice must be no lo)-.2 E(wer than than top note of the lo) +-.25 E(wer v)-.25 E(oice for combin-)-.2 E(ing to occur)138.476 264 Q 5 +(.I)-.55 G 2.5(ft)-5 G(he quali\214er is "o)-2.5 E -.15(ve)-.15 G +(rlap," combining will occur without re).15 E -.05(ga)-.15 G(rd for ho) +.05 E 2.5(wt)-.25 G(he v)-2.5 E(oices)-.2 E -.15(ove)138.476 276 S +(rlap. F).15 E(or the purpose of the quali\214er)-.15 E 2.5(,v)-.4 G +(oice 1 is assumed to be the highest v)-2.7 E(oice, v)-.2 E(oice 3 the) +-.2 E(middle v)138.476 288 Q(oice, and v)-.2 E(oice 2 the lo)-.2 E 2.5 +(west. If)-.25 F(no quali\214er is speci\214ed, the def)2.5 E +(ault is noo)-.1 E -.15(ve)-.15 G(rlap. While the).15 E +(vcombine parameter is allo)138.476 300 Q(wed to be used with an)-.25 E +2.5(yv)-.15 G(scheme parameter v)-2.5 E(alue, using it with)-.25 E +(vscheme=1 is pointless, and only vscheme v)138.476 312 Q +(alues of 2f and 3f are really appropriate.)-.25 E(This parame-)5 E +(ters can be used with both v)138.476 324 Q +(oice-at-a-time and chord-at-a-time input styles. It has no ef)-.2 E +(fect on tab-)-.25 E(lature or 1-line staf)138.476 336 Q 2.5(fs. Note) +-.25 F(that there are v)2.5 E +(arious cases where combining will not be done, such as)-.25 E +(when time v)138.476 348 Q(alues or beamings are dif)-.25 E +(ferent in dif)-.25 E(ferent v)-.25 E +(oices, and cases where combining w)-.2 E(ould)-.1 E +(cause information loss, such as when a shared note is tied in one v) +138.476 360 Q(oice b)-.2 E(ut not another)-.2 E 2.5(.I)-.55 G 2.5(ns) +-2.5 G(uch cas-)-2.5 E(es, the usual non-combined format will be used.) +138.476 372 Q F1 -.92(Va)69.336 384 S(lue).92 E F0 +(............... comma-separated list of v).36 E(oices or v)-.2 E +(oice ranges, or nothing, optionally follo)-.2 E(wed by noo)-.25 E -.15 +(ve)-.15 G(rlap, share-).15 E(one, or o)138.476 396 Q -.15(ve)-.15 G +(rlap.).15 E F1(Default)69.336 408 Q F0(............ not set).28 E F1 +(Context)69.336 420 Q F0(........... score, staf).56 E(f)-.25 E F1 +(Example)69.336 432 Q F0(......... vcombine=3,1-2 shareone)1.66 E 5 +(vcombine= //)138.476 444 R(turn of)2.5 E 2.5(fc)-.25 G(ombining)-2.5 E +F1(See also)69.336 456 Q F0(........... vscheme).83 E F1(Name)69.336 504 +Q F0(.............. visible)1.95 E F1(Description)69.336 516 Q F0 +(..... speci\214es whether a staf)A 2.5(fo)-.25 G 2.5(rv)-2.5 G +(oice is actually to be printed.)-2.7 E +(This can be useful for printing a subset of)5 E 2.5(af)138.476 528 S +(ull score. The v)-2.5 E(alue is either y or n, for yes or no, or where\ +used. When whereused is speci\214ed, if)-.25 E 2.5(as)138.476 540 S(taf) +-2.5 E 2.5(fh)-.25 G(as no notes or lyrics or other associated things o\ +n an entire score, that staf)-2.5 E 2.5(fi)-.25 G 2.5(sn)-2.5 G +(ot printed.)-2.5 E(This might be used, for e)138.476 552 Q +(xample, to sa)-.15 E .3 -.15(ve p)-.2 H +(aper on an orchestral score by only printing staf).15 E(fs for in-)-.25 +E(struments when the)138.476 564 Q 2.5(ya)-.15 G(re actually playing.) +-2.5 E(At least one staf)5 E 2.5(fm)-.25 G(ust be visible at all times.) +-2.5 E(When an)5 E(indi)138.476 576 Q(vidual v)-.25 E(oice is made in) +-.2 E(visible, b)-.4 E(ut the other v)-.2 E(oice\(s\) on that staf)-.2 E +2.5(fr)-.25 G(emain visible, all the tempo,)-2.5 E +(dynamics, and similar marks associated with the staf)138.476 588 Q 2.5 +(fw)-.25 G(ill still be printed, since Mup cannot kno)-2.5 E(w)-.25 E +(for sure whether you meant them to be associated with a particular v) +138.476 600 Q(oice or with the staf)-.2 E 2.5(fa)-.25 G 2.5(sa)-2.5 G +2.5(whole. When)138.476 612 R +(MIDI output is generated, this parameter controls whether the staf)2.5 +E 2.5(fo)-.25 G 2.5(rv)-2.5 G(oice is audi-)-2.7 E +(ble, so you can control which v)138.476 624 Q(oices are played.)-.2 E +(The -s command line ar)5 E(gument can also be used)-.18 E +(to control which staf)138.476 636 Q(fs are printed or played.)-.25 E F1 +-.92(Va)69.336 648 S(lue).92 E F0(............... y).36 E 2.5(,n)-.65 G +2.5(,o)-2.5 G 2.5(rw)-2.5 G(hereused)-2.5 E F1(Default)69.336 660 Q F0 +(............ y).28 E F1(Context)69.336 672 Q F0 +(........... score, staf).56 E(f, v)-.25 E(oice)-.2 E F1(Example)69.336 +684 Q F0(......... visible = n)1.66 E F1(See also)69.336 696 Q F0 +(........... brace, brack).83 E(et, endingstyle, staf)-.1 E(fs)-.25 E EP +%%Page: 128 134 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(28 -)-2.5 E/F1 10 +/Times-Bold@0 SF(Name)69.336 96 Q F0(.............. vscheme)1.95 E F1 +(Description)69.336 108 Q F0(..... sets v)A(oice scheme. A v)-.2 E +(alue of 1 means there is only a single v)-.25 E(oice on a staf)-.2 E +(f. The direction of note)-.25 E(stems will be determined based on ho) +138.476 120 Q 2.5(wh)-.25 G(igh or lo)-2.5 E 2.5(wt)-.25 G +(he notes are on the staf)-2.5 E(f. A v)-.25 E(alue of 2o means)-.25 E +(there are tw)138.476 132 Q 2.5(ov)-.1 G +(oices with "opposing" stems. In other w)-2.7 E(ords, the stems of v)-.1 +E(oice 1 will al)-.2 E -.1(wa)-.1 G(ys point).1 E(upw)138.476 144 Q +(ard, and the stems of v)-.1 E(oice 2 will al)-.2 E -.1(wa)-.1 G +(ys point do).1 E(wnw)-.25 E(ard, unless the)-.1 E 2.5(ya)-.15 G(re e) +-2.5 E(xplicitly forced the)-.15 E(other w)138.476 156 Q(ay)-.1 E 2.5 +(.Av)-.65 G(alue of 2f means there are tw)-2.75 E 2.5(ov)-.1 G +(oices with "free" or "\215oating" stems.)-2.7 E(That means in)5 E +(places where there are notes or rests in both v)138.476 168 Q +(oices, stem directions will be as if 2o were set. Ho)-.2 E(w-)-.25 E +-2.15 -.25(ev e)138.476 180 T .8 -.4(r, i).25 H 2.5(fo).4 G(ne of the v) +-2.5 E(oices has "space" where there are no notes or rests, the stem di\ +rections of the)-.2 E(other v)138.476 192 Q +(oice will be determined as if there were only a single v)-.2 E 2.5 +(oice. 2o)-.2 F(is useful if you w)2.5 E(ant to force)-.1 E +(stem directions a certain w)138.476 204 Q(ay)-.1 E 2.5(.2)-.65 G 2.5 +(fi)-2.5 G 2.5(sg)-2.5 G(enerally preferable when there are tw)-2.5 E +2.5(ov)-.1 G(oices only part of the)-2.7 E 2.5(time. The)138.476 216 R +-.25(va)2.5 G(lues 3o and 3f are lik).25 E 2.5(e2)-.1 G 2.5(oa)-2.5 G +(nd 2f e)-2.5 E(xcept that a third v)-.15 E(oice is allo)-.2 E +(wed. The third v)-.25 E(oice')-.2 E(s)-.55 E(stem def)138.476 228 Q +(aults to up, b)-.1 E(ut the direction can be changed at an)-.2 E 2.5 +(yc)-.15 G(hord. The stem direction remains in)-2.5 E(ef)138.476 240 Q +(fect on subsequent chords of v)-.25 E(oice 3 until e)-.2 E +(xplicitly changed.)-.15 E(While there can be v)5 E(oice cross-)-.2 E +(ings, in general v)138.476 252 Q(oice 1 should be the "top" v)-.2 E +(oice, v)-.2 E(oice 2 the "bottom" v)-.2 E(oice, and v)-.2 E +(oice 3 the "mid-)-.2 E(dle" or "e)138.476 264 Q(xtra" v)-.15 E 2.5 +(oice. Mup)-.2 F(does not use v)2.5 E +(oice 3 when associating things lik)-.2 E 2.5(ep)-.1 G(hrase marks and) +-2.5 E(lyrics with chords.)138.476 276 Q(Setting vscheme to a dif)5 E +(ferent number of v)-.25 E(oices will reinitialize all v)-.2 E(oice le) +-.2 E -.15(ve)-.25 G(l).15 E(parameters for the af)138.476 288 Q +(fected staf)-.25 E(fs.)-.25 E F1 -.92(Va)69.336 300 S(lue).92 E F0 +(............... 1, 2o, 2f, 3o, or 3f).36 E F1(Default)69.336 312 Q F0 +(............ 1).28 E F1(Context)69.336 324 Q F0 +(........... score, staf).56 E(f)-.25 E F1(Example)69.336 336 Q F0 +(......... vscheme = 2f)1.66 E F1(See also)69.336 348 Q F0 +(........... vcombine).83 E F1(Name)69.336 396 Q F0(.............. w) +1.95 E(arn)-.1 E F1(Description)69.336 408 Q F0 +(..... speci\214es whether to print w)A(arning messages or not.)-.1 E +(Normally)5 E 2.5(,M)-.65 G(up will print w)-2.5 E(arnings when it en-) +-.1 E(counters input that it considers some)138.476 420 Q +(what dubious. Sometimes, ho)-.25 E(we)-.25 E -.15(ve)-.25 G .8 -.4 +(r, t).15 H(hat input will really be).4 E(what you w)138.476 432 Q +(ant, so this parameter allo)-.1 E(ws you to turn of)-.25 E 2.5(fw)-.25 +G(arning messages.)-2.6 E F1 -.92(Va)69.336 444 S(lue).92 E F0 +(............... y or n).36 E F1(Default)69.336 456 Q F0(............ y) +.28 E F1(Context)69.336 468 Q F0(........... score).56 E F1(Example) +69.336 480 Q F0(......... w)1.66 E(arn = n)-.1 E EP +%%Page: 129 135 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(29 -)-2.5 E 69.336 103 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 15/Times-Bold@0 SF 3.75(13. HINTS)73.086 103 R 69.336 121 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF 1.549(This section contains hints on ho) +73.385 121 R 4.049(wy)-.25 G 1.549(ou can use Mup to accomplish v)-4.049 +F 1.549(arious things that ha)-.25 F 1.848 -.15(ve n)-.2 H 1.548 +(ot been).15 F(co)69.336 133 Q -.15(ve)-.15 G 1.358 +(red up to this point.).15 F 1.358(It doesn')6.358 F 3.858(ti)-.18 G +1.358(ntroduce an)-3.858 F 3.858(yn)-.15 G 1.858 -.25(ew l)-3.858 H +1.358(anguage features, b).25 F 1.358(ut describes some additional)-.2 F +-.1(wa)69.336 145 S(ys to apply what you ha).1 E .3 -.15(ve a)-.2 H +(lready learned, and mentions some other tools you may \214nd useful.) +.15 E 69.336 163 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.1 Deb)72.836 163 R(ugging)-.28 E +69.336 181 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF 1.823(Since Mup requires its input in a f) +73.659 181 R 1.823 +(airly strict format, when a song is put in, it may contain "typos.")-.1 +F(Generally)69.336 193 Q 2.81(,t)-.65 G .31 +(he error messages that Mup prints will gi)-2.81 F .611 -.15(ve y)-.25 H +.311(ou an idea of what is wrong. Ho).15 F(we)-.25 E -.15(ve)-.25 G +1.111 -.4(r, s).15 H(ometimes).4 E .878(Mup is not able to recognize th\ +at something is wrong until some distance be)69.336 205 R .878 +(yond the actual error)-.15 F 3.378(.I)-.55 G 3.378(fy)-3.378 G(ou) +-3.378 E(can')69.336 217 Q 4.263<748c>-.18 G 1.763(nd an)-4.263 F 1.763 +(ything wrong with the line that Mup lists as being in error)-.15 F +4.263(,t)-.4 G 1.763(ry looking at the end of the)-4.263 F(pre)69.336 +229 Q 2.087(vious line, or e)-.25 F -.15(ve)-.25 G 4.587(ne).15 G 2.087 +(arlier lines. Some of the most common problems are missing semicolons \ +and)-4.587 F .936(missing quotes. Missing quote marks tend to be especi\ +ally confusing to Mup, and may cause man)69.336 241 R 3.436(ye)-.15 G +(rror)-3.436 E .679(messages, e)69.336 253 R -.15(ve)-.25 G 3.179(nt).15 +G .679(hough there is only one problem.)-3.179 F .679 +(Another common problem that may cause a v)5.679 F .678(ery lar)-.15 F +(ge)-.18 E(number of error messages is for)69.336 265 Q +(getting to state "music" to enter music conte)-.18 E(xt.)-.15 E 1.492 +(Often listening to MIDI output is much more ef)69.336 283 R(fecti)-.25 +E 1.793 -.15(ve a)-.25 H 3.993(ts).15 G 1.493(potting things lik)-3.993 +F 3.993(ew)-.1 G 1.493(rong notes and missing)-3.993 F +(accidentals than trying to \214nd them by e)69.336 295 Q(ye.)-.15 E +69.336 313 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.2 Adjusting)72.836 313 R(Output)3.5 E +69.336 331 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .42 +(Mup does its best to lay out the music in an aesthetically pleasing w) +72.256 331 R(ay)-.1 E 5.419(.O)-.65 G .419(ften, ho)-5.419 F(we)-.25 E +-.15(ve)-.25 G 1.219 -.4(r, y).15 H .419(ou may w).4 F .419(ant to)-.1 F +(mak)69.336 343 Q 2.584(ea)-.1 G .084 +(djustments. Perhaps the last part of a piece spilled o)-2.584 F -.15 +(ve)-.15 G 2.584(ro).15 G .084(nto a third page and you')-2.584 F 2.584 +(dl)-.5 G(ik)-2.584 E 2.584(et)-.1 G 2.584(os)-2.584 G .084(queeze it) +-2.584 F 1.64(all on tw)69.336 355 R 4.14(op)-.1 G 1.64 +(ages, or a page turn f)-4.14 F 1.64(alls at an a)-.1 F(wkw)-.15 E 1.64 +(ard spot. There are se)-.1 F -.15(ve)-.25 G 1.64(ral mechanisms a).15 F +-.25(va)-.2 G 1.64(ilable for).25 F .896(making adjustments. The)69.336 +367 R 3.396(yh)-.15 G -2.25 -.2(av e)-3.396 H .896 +(already been discussed indi)3.596 F .896(vidually in v)-.25 F .896 +(arious sections of this document,)-.25 F -.2(bu)69.336 379 S 2.5(tt).2 +G(his section tries to pull things together)-2.5 E(.)-.55 E .322 +(The "ne)69.336 397 R .322(wscore" or "ne)-.25 F .322 +(wpage" commands can be used to force where breaks occur)-.25 F 5.322 +(.T)-.55 G .321(his may be useful for)-5.322 F +(ensuring a section ends at the end of a score or page.)69.336 409 Q +1.284(If you w)69.336 427 R 1.285(ant to get a little more or less on e\ +ach page, it is usually best to start with changing the scale,)-.1 F +(staf)69.336 439 Q 3.162(fscale, packf)-.25 F 3.162(act, and/or pack)-.1 +F -.15(ex)-.1 G 5.662(pp).15 G 5.662(arameters. Y)-5.662 F 3.162 +(ou may w)-1.1 F 3.162(ant to e)-.1 F 3.161 +(xperiment with changing these)-.15 F(indi)69.336 451 Q 1.469 +(vidually \214rst, to get a feel for ho)-.25 F 3.969(wt)-.25 G(he)-3.969 +E 3.969(yw)-.15 G 1.47 +(ork, as trying to change all of them at once may lead to)-4.069 F .425 +(interactions that change things more radically than you might e)69.336 +463 R 2.925(xpect. Changing)-.15 F(staf)2.925 E .425 +(fscale in score conte)-.25 F(xt)-.15 E .29 +(lets you adjust the size of the music without af)69.336 475 R .29 +(fecting the size of the te)-.25 F .29(xt in headers and footers.)-.15 F +(Adjusting)5.29 E .712(the mar)69.336 487 R .712(gins is sometimes help\ +ful as well. Other parameters which might be useful in some situations \ +are:)-.18 F(scorepad, scoresep, staf)69.336 499 Q(fpad, and staf)-.25 E +(fsep.)-.25 E 1.196 +(The dist, dyndist, and chorddist parameters are useful if you w)69.336 +517 R 1.197(ant items to line up v)-.1 F(ertically)-.15 E 3.697(.T)-.65 +G 1.197(he "dist")-3.697 F .198 +(option can be used on rom, bold, ital, boldital, octa)69.336 529 R -.15 +(ve)-.2 G 2.698(,m).15 G .198 +(ussym, crescendo and decrescendo statements, and)-2.698 F +(on rehearsal marks, to force something where you w)69.336 541 Q +(ant it.)-.1 E 1.072(The appearance of lyrics can be adjusted using the\ + lyricsfont, lyricsfontf)69.336 559 R(amily)-.1 E 3.573(,l)-.65 G 1.073 +(yricssize, and lyricsalign)-3.573 F(parameters.)69.336 571 Q 69.336 589 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.3 Special)72.836 589 R(uses of in)3.5 +E(visbar)-.56 E 69.336 607 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .01(The "in)71.846 607 R .01(visbar" can be\ + used to force Mup into doing something in the middle of a bar that it \ +normally w)-.4 F(ould)-.1 E(allo)69.336 619 Q 2.762(wt)-.25 G 2.762(oh) +-2.762 G .262(appen only at a bar line.)-2.762 F .262(Suppose, for e) +5.262 F .263(xample, you wish to place a rehearsal letter in the middle) +-.15 F(of a measure. This could be accomplished as follo)69.336 631 Q +(ws:)-.25 E EP +%%Page: 130 136 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(30 -)-2.5 E/F1 10/Courier@0 +SF(// assume we are in 4/4 time, but want)105.336 96 Q +(// a rehearsal letter by count 3)105.336 108 Q(// of the measure) +105.336 120 Q(// do first part of measure and use "space")105.336 144 Q +(// for last part so time values will add up)105.336 156 Q +(// properly to a full measure)105.336 168 Q(1: 4c;d;2s;)105.336 180 Q +(// put in invisible bar with rehearsal letter)105.336 204 Q +(invisbar rehearsal let)105.336 216 Q +(// now do the last half of the measure,)105.336 240 Q +(// this time with space at the beginning)105.336 252 Q(1: 2s;4e;c;) +105.336 264 Q(bar)105.336 276 Q 127.836 285.6 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 69 rlineto 320 0 rlineto 0 69 neg rlineto closepath stroke grestore +EEND 160 693 320 320 -69 69 126.836 354.6 PBEGIN +%%BeginDocument: mugex87.ps +%%BoundingBox: 160 693 480 762 +save +1216322504 1216321786 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +1 linenum +% S_FEED +324.29 1225.78 468.00 5 1.000000 1.000000 stf +% S_CLEFSIG +192.08 715.78 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +226.28 703.78 1.000000 4n +0.70 setlinewidth +220.05 703.78 moveto +232.51 703.78 lineto stroke +229.96 704.53 moveto +229.96 724.78 lineto stroke +287.42 706.78 1.000000 4n +291.10 707.53 moveto +291.10 727.78 lineto stroke +restore +% S_BAR +13 linenum +0.70 setlinewidth +/Times-Bold findfont +12 scalefont +setfont +newpath +332.19 742.78 moveto +332.19 754.00 lineto +345.33 754.00 lineto +345.33 742.78 lineto +closepath +stroke +334.19 744.28 moveto +(A) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +351.92 709.78 1.000000 4n +355.60 710.53 moveto +355.60 730.78 lineto stroke +413.06 703.78 1.000000 4n +406.83 703.78 moveto +419.29 703.78 lineto stroke +416.74 704.53 moveto +416.74 724.78 lineto stroke +restore +% S_BAR +19 linenum +0.70 setlinewidth +467.65 733.78 moveto +467.65 709.78 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Bold +%%Pages: 2 +%%EndDocument +end PEND/F0 10/Times-Roman@0 SF 1.102(As another e)69.336 374.6 R 1.102 +(xample of in)-.15 F 1.102(visbar use, suppose you w)-.4 F 1.102 +(ant to add a "courtesy" k)-.1 F 1.401 -.15(ey s)-.1 H 1.101 +(ignature at the end of a).15 F .82 +(repeated section to remind the player that the be)69.336 386.6 R .821 +(ginning of the repeated section is in a dif)-.15 F .821(ferent k)-.25 F +-.15(ey)-.1 G 3.321(.T)-.5 G(his)-3.321 E(can be done by adding an empt\ +y measure whose sole purpose is to produce this k)69.336 398.6 Q .3 -.15 +(ey s)-.1 H(ignature.).15 E/F1 10/Courier@0 SF(score key=3&)105.336 +416.6 Q(music)105.336 428.6 Q(1: g;f;e;d;)105.336 440.6 Q(repeatstart) +105.336 452.6 Q(1: c;e;f;g;)105.336 464.6 Q(dblbar)105.336 476.6 Q +(score key=0&)105.336 488.6 Q(music)105.336 500.6 Q(1: g;f;e;d;)105.336 +512.6 Q(bar ending "1.")105.336 524.6 Q(1: f;e;2c;)105.336 536.6 Q +(// add a courtesy key signature,)105.336 548.6 Q +(// to remind player the beginning)105.336 560.6 Q +(// of the repeated section is in)105.336 572.6 Q(// a different key) +105.336 584.6 Q(invisbar)105.336 596.6 Q(score key=3&)105.336 608.6 Q +(music)105.336 620.6 Q(1: ms;)105.336 632.6 Q(repeatend ending "2.") +105.336 644.6 Q(1: e;d;2c;)105.336 656.6 Q(endbar)105.336 668.6 Q EP +%%Page: 131 137 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(31 -)-2.5 E 111.836 96 +EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 145 rlineto 352 0 rlineto 0 145 neg rlineto closepath stroke grestore +EEND 128 618 352 352 -145 145 110.836 241 PBEGIN +%%BeginDocument: mugex88.ps +%%BoundingBox: 128 618 480 763 +save +1216322504 1216321786 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +1 linenum +% S_FEED +324.29 1235.00 468.00 5 1.000000 1.000000 stf +% S_CLEFSIG +192.08 725.00 1.000000 gclef +205.62 731.00 1.000000 flat +211.10 740.00 1.000000 flat +216.59 728.00 1.000000 flat +% S_CHHEAD +% S_STAFF +% staff 1 +save +238.42 725.00 1.000000 4n +0.70 setlinewidth +242.10 725.75 moveto +242.10 746.00 lineto stroke +260.81 722.00 1.000000 4n +264.49 722.75 moveto +264.49 743.00 lineto stroke +283.19 719.00 1.000000 4n +286.87 719.75 moveto +286.87 740.00 lineto stroke +306.42 716.00 1.000000 4n +310.10 716.75 moveto +310.10 737.00 lineto stroke +restore +% S_BAR +6 linenum +337.91 734.00 1.000000 dot +337.91 728.00 1.000000 dot +0.70 setlinewidth +334.91 743.00 moveto +334.91 719.00 lineto stroke +3.00 setlinewidth +330.91 743.00 moveto +330.91 719.00 lineto stroke +0.70 setlinewidth +% S_CHHEAD +% S_STAFF +% staff 1 +save +348.99 713.00 1.000000 4n +342.76 713.00 moveto +355.23 713.00 lineto stroke +352.68 713.75 moveto +352.68 734.00 lineto stroke +371.38 719.00 1.000000 4n +375.06 719.75 moveto +375.06 740.00 lineto stroke +393.76 722.00 1.000000 4n +397.45 722.75 moveto +397.45 743.00 lineto stroke +416.99 725.00 1.000000 4n +420.67 725.75 moveto +420.67 746.00 lineto stroke +restore +% S_BAR +8 linenum +0.70 setlinewidth +438.98 743.00 moveto +438.98 719.00 lineto stroke +441.98 743.00 moveto +441.98 719.00 lineto stroke +% S_SSV +9 linenum +% S_CLEFSIG +447.90 731.00 1.000000 nat +453.74 740.00 1.000000 nat +459.58 728.00 1.000000 nat +% S_FEED +288.00 1151.00 468.00 5 1.000000 1.000000 stf +264.93 661.00 moveto +264.93 672.00 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +267.93 662.00 moveto +(1.) show +264.93 672.00 moveto +370.69 672.00 lineto stroke +370.69 672.00 moveto +370.69 661.00 lineto stroke +374.69 661.00 moveto +374.69 672.00 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +377.69 662.00 moveto +(2.) show +374.69 672.00 moveto +462.50 672.00 lineto stroke +462.50 672.00 moveto +462.50 661.00 lineto stroke +% S_CLEFSIG +155.79 641.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +183.18 641.00 1.000000 4n +186.86 641.75 moveto +186.86 662.00 lineto stroke +202.63 638.00 1.000000 4n +206.32 638.75 moveto +206.32 659.00 lineto stroke +222.09 635.00 1.000000 4n +225.77 635.75 moveto +225.77 656.00 lineto stroke +242.38 632.00 1.000000 4n +246.06 632.75 moveto +246.06 653.00 lineto stroke +restore +% S_BAR +12 linenum +0.70 setlinewidth +262.93 659.00 moveto +262.93 635.00 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +273.02 638.00 1.000000 4n +276.70 638.75 moveto +276.70 659.00 lineto stroke +292.44 635.00 1.000000 4n +296.12 635.75 moveto +296.12 656.00 lineto stroke +315.13 629.00 1.000000 2n +308.68 629.00 moveto +321.58 629.00 lineto stroke +319.03 629.75 moveto +319.03 650.00 lineto stroke +restore +% S_BAR +18 linenum +0.70 setlinewidth +% S_SSV +19 linenum +% S_CLEFSIG +345.97 647.00 1.000000 flat +351.46 656.00 1.000000 flat +356.95 644.00 1.000000 flat +% S_CHHEAD +% S_STAFF +% staff 1 +save +restore +% S_BAR +22 linenum +368.69 650.00 1.000000 dot +368.69 644.00 1.000000 dot +0.70 setlinewidth +372.69 659.00 moveto +372.69 635.00 lineto stroke +3.00 setlinewidth +376.69 659.00 moveto +376.69 635.00 lineto stroke +0.70 setlinewidth +% S_CHHEAD +% S_STAFF +% staff 1 +save +387.29 635.00 1.000000 4n +390.97 635.75 moveto +390.97 656.00 lineto stroke +406.71 632.00 1.000000 4n +410.39 632.75 moveto +410.39 653.00 lineto stroke +429.40 629.00 1.000000 2n +422.95 629.00 moveto +435.85 629.00 lineto stroke +433.30 629.75 moveto +433.30 650.00 lineto stroke +restore +% S_BAR +24 linenum +0.70 setlinewidth +462.50 659.00 moveto +462.50 635.00 lineto stroke +3.00 setlinewidth +466.50 659.00 moveto +466.50 635.00 lineto stroke +0.70 setlinewidth +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Roman +%%Pages: 2 +%%EndDocument +end PEND/F0 10/Times-Roman@0 SF -1.1(Yo)69.336 261 S 2.5(uc)1.1 G +(an use a similar technique to insert time signatures, clefs, etc.)-2.5 +E(at unusual places.)5 E 69.336 279 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.4 Chant)72.836 279 R 69.336 297 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF(Here is an e)71.836 297 Q(xample that sho) +-.15 E(ws some techniques you might use when writing chant.)-.25 E EP +%%Page: 132 138 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(32 -)-2.5 E/F1 10/Courier@0 +SF(1: 1a;)105.336 96 Q(lyrics 1: "This<^ is an example of one way>";) +105.336 108 Q(bar)105.336 120 Q(1: d;e;2f;)105.336 144 Q +(lyrics 1: "to do chant.";)105.336 156 Q(bar)105.336 168 Q(1: 1f;) +105.336 192 Q(lyrics 1: "when<^ there are many words for a>";)105.336 +204 Q(bar)105.336 216 Q(1: d;f;2;)105.336 240 Q +(lyrics 1: "sin-gle note.";)105.336 252 Q(dblbar)105.336 264 Q(newscore) +105.336 288 Q(// Note use of 'n' to not print the time signature)105.336 +300 Q(score time=7/4n)105.336 312 Q(music)105.336 324 Q(1: a;;;b;g;2a;) +105.336 336 Q(lyrics 1: "When there are man-y notes,";)105.336 348 Q +(bar)105.336 360 Q(score time=8/4n)105.336 384 Q(music)105.336 396 Q +(1: d;e;f;e;f;8e;;2;)105.336 408 Q +(lyrics 1: "You might change the time sig-na-ture";)105.336 420 Q(bar) +105.336 432 Q(score time=5/4n)105.336 456 Q(music)105.336 468 Q +(1: a;e;;2d;)105.336 480 Q(lyrics 1: "on ev-ery bar,";)105.336 492 Q +(bar)105.336 504 Q(score time=7/4n)105.336 528 Q(music)105.336 540 Q +(1: e;f;e;d;c;2d;)105.336 552 Q(lyrics 1: "to match the syl-la-bles.";) +105.336 564 Q(dblbar)105.336 576 Q(newscore)105.336 600 Q +(score time=8/4n)105.336 624 Q(music)105.336 636 Q +(// Note use of 'n' to not print tuplet number/bracket)105.336 648 Q +(1: {d;e;f;g;e;2d;;}10n,1/2;)105.336 660 Q +(lyrics 1: "You can al-so use tup-lets,";)105.336 672 Q(invisbar)105.336 +684 Q(1: {f;g;e;2d;e;2.d;}9n,1/2;)105.336 708 Q +(lyrics 1: "A-long with in-vis-bars.";)105.336 720 Q(dblbar)105.336 732 +Q EP +%%Page: 133 139 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(33 -)-2.5 E/F1 10/Courier@0 +SF(newscore)105.336 96 Q(score stemlen=0)105.336 120 Q(music)105.336 132 +Q(1: d+;c+;b;g;2a;;)105.336 156 Q(lyrics 1: "Set stem-len to ze-ro,";) +105.336 168 Q(invisbar)105.336 180 Q(1: {f;2e;4d;c;1d;}9n,1/2;)105.336 +204 Q(lyrics 1: "to get stem-less notes.";)105.336 216 Q(endbar)105.336 +228 Q EP +%%Page: 134 140 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(34 -)-2.5 E 87.836 96 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 578 rlineto 400 0 rlineto 0 578 neg rlineto closepath stroke grestore +EEND 104 185 400 400 -578 578 86.836 674 PBEGIN +%%BeginDocument: mugex89.ps +%%BoundingBox: 104 185 504 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_FEED +590.69 803.00 489.60 5 1.000000 1.000000 stf +% S_CLEFSIG +170.48 725.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +5 linenum +/Times-Roman findfont +12 scalefont +setfont +192.16 702.00 moveto +(This is an example of one way) show +197.49 728.00 1.000000 1n +restore +% S_BAR +8 linenum +0.70 setlinewidth +342.18 743.00 moveto +342.18 719.00 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +9 linenum +/Times-Roman findfont +12 scalefont +setfont +351.91 702.00 moveto +(to) show +/Times-Roman findfont +12 scalefont +setfont +386.63 702.00 moveto +(do) show +/Times-Roman findfont +12 scalefont +setfont +422.53 702.00 moveto +(chant.) show +354.23 716.00 1.000000 4n +357.91 716.75 moveto +357.91 737.00 lineto stroke +389.62 719.00 1.000000 4n +393.30 719.75 moveto +393.30 740.00 lineto stroke +429.76 722.00 1.000000 2n +433.66 722.75 moveto +433.66 743.00 lineto stroke +restore +% S_BAR +12 linenum +0.70 setlinewidth +489.25 743.00 moveto +489.25 719.00 lineto stroke +% S_FEED +554.40 719.00 489.60 5 1.000000 1.000000 stf +% S_CLEFSIG +134.19 641.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +13 linenum +/Times-Roman findfont +12 scalefont +setfont +154.98 618.00 moveto +(when there are many words for a) show +161.46 638.00 1.000000 1n +restore +% S_BAR +16 linenum +0.70 setlinewidth +316.16 659.00 moveto +316.16 635.00 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +17 linenum +/Times-Roman findfont +12 scalefont +setfont +350.70 618.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +324.08 618.00 moveto +(sin) show +/Times-Roman findfont +12 scalefont +setfont +366.35 618.00 moveto +(gle) show +/Times-Roman findfont +12 scalefont +setfont +411.28 618.00 moveto +(note.) show +328.56 632.00 1.000000 4n +332.24 632.75 moveto +332.24 653.00 lineto stroke +370.00 638.00 1.000000 4n +373.68 638.75 moveto +373.68 659.00 lineto stroke +417.18 638.00 1.000000 2n +421.08 638.75 moveto +421.08 659.00 lineto stroke +restore +% S_BAR +19 linenum +0.70 setlinewidth +486.25 659.00 moveto +486.25 635.00 lineto stroke +489.25 659.00 moveto +489.25 635.00 lineto stroke +% S_SSV +23 linenum +% S_CLEFSIG +% S_FEED +21 linenum +554.40 635.00 489.60 5 1.000000 1.000000 stf +% S_CLEFSIG +134.19 557.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +25 linenum +/Times-Roman findfont +12 scalefont +setfont +157.83 531.28 moveto +(When) show +/Times-Roman findfont +12 scalefont +setfont +207.29 531.28 moveto +(there) show +/Times-Roman findfont +12 scalefont +setfont +258.12 531.28 moveto +(are) show +/Times-Roman findfont +12 scalefont +setfont +338.28 531.28 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +302.60 531.28 moveto +(man) show +/Times-Roman findfont +12 scalefont +setfont +356.29 531.28 moveto +(y) show +/Times-Roman findfont +12 scalefont +setfont +403.01 531.28 moveto +(notes,) show +164.98 560.00 1.000000 4n +168.66 560.75 moveto +168.66 581.00 lineto stroke +213.26 560.00 1.000000 4n +216.94 560.75 moveto +216.94 581.00 lineto stroke +261.78 560.00 1.000000 4n +265.46 560.75 moveto +265.46 581.00 lineto stroke +308.76 563.00 1.000000 4n +305.07 562.25 moveto +305.07 542.00 lineto stroke +357.78 557.00 1.000000 4n +361.46 557.75 moveto +361.46 578.00 lineto stroke +410.09 560.00 1.000000 2n +413.98 560.75 moveto +413.98 581.00 lineto stroke +restore +% S_BAR +28 linenum +0.70 setlinewidth +489.25 575.00 moveto +489.25 551.00 lineto stroke +% S_SSV +29 linenum +% S_CLEFSIG +% S_FEED +554.40 551.00 489.60 5 1.000000 1.000000 stf +% S_CLEFSIG +134.19 473.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +31 linenum +/Times-Roman findfont +12 scalefont +setfont +157.55 450.00 moveto +(You) show +/Times-Roman findfont +12 scalefont +setfont +195.42 450.00 moveto +(might) show +/Times-Roman findfont +12 scalefont +setfont +234.63 450.00 moveto +(change) show +/Times-Roman findfont +12 scalefont +setfont +282.69 450.00 moveto +(the) show +/Times-Roman findfont +12 scalefont +setfont +321.10 450.00 moveto +(time) show +/Times-Roman findfont +12 scalefont +setfont +378.54 450.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +360.84 450.00 moveto +(sig) show +/Times-Roman findfont +12 scalefont +setfont +404.96 450.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +385.28 450.00 moveto +(na) show +/Times-Roman findfont +12 scalefont +setfont +416.33 450.00 moveto +(ture) show +162.70 464.00 1.000000 4n +166.38 464.75 moveto +166.38 485.00 lineto stroke +202.41 467.00 1.000000 4n +206.09 467.75 moveto +206.09 488.00 lineto stroke +243.11 470.00 1.000000 4n +246.79 470.75 moveto +246.79 491.00 lineto stroke +286.34 467.00 1.000000 4n +290.02 467.75 moveto +290.02 488.00 lineto stroke +326.42 470.00 1.000000 4n +330.11 470.75 moveto +330.11 491.00 lineto stroke +365.32 467.00 1.000000 4n +369.00 467.75 moveto +369.00 488.00 lineto stroke +372.03 488.00 1.000000 dnflag +389.09 467.00 1.000000 4n +392.78 467.75 moveto +392.78 488.00 lineto stroke +395.80 488.00 1.000000 dnflag +420.98 467.00 1.000000 2n +424.87 467.75 moveto +424.87 488.00 lineto stroke +restore +% S_BAR +34 linenum +0.70 setlinewidth +489.25 491.00 moveto +489.25 467.00 lineto stroke +% S_SSV +35 linenum +% S_CLEFSIG +% S_FEED +554.40 467.00 489.60 5 1.000000 1.000000 stf +% S_CLEFSIG +134.19 389.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +37 linenum +/Times-Roman findfont +12 scalefont +setfont +158.59 363.00 moveto +(on) show +/Times-Roman findfont +12 scalefont +setfont +201.30 363.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +184.23 363.00 moveto +(ev) show +/Times-Roman findfont +12 scalefont +setfont +210.07 363.00 moveto +(ery) show +/Times-Roman findfont +12 scalefont +setfont +239.95 363.00 moveto +(bar,) show +161.58 392.00 1.000000 4n +165.26 392.75 moveto +165.26 413.00 lineto stroke +188.05 383.00 1.000000 4n +191.73 383.75 moveto +191.73 404.00 lineto stroke +213.89 383.00 1.000000 4n +217.57 383.75 moveto +217.57 404.00 lineto stroke +244.52 380.00 1.000000 2n +248.42 380.75 moveto +248.42 401.00 lineto stroke +restore +% S_BAR +40 linenum +0.70 setlinewidth +288.59 407.00 moveto +288.59 383.00 lineto stroke +% S_SSV +41 linenum +% S_CLEFSIG +% S_CHHEAD +% S_STAFF +% staff 1 +save +43 linenum +/Times-Roman findfont +12 scalefont +setfont +298.31 363.00 moveto +(to) show +/Times-Roman findfont +12 scalefont +setfont +318.17 363.00 moveto +(match) show +/Times-Roman findfont +12 scalefont +setfont +353.10 363.00 moveto +(the) show +/Times-Roman findfont +12 scalefont +setfont +398.37 363.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +378.75 363.00 moveto +(syl) show +/Times-Roman findfont +12 scalefont +setfont +423.31 363.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +407.03 363.00 moveto +(la) show +/Times-Roman findfont +12 scalefont +setfont +433.96 363.00 moveto +(bles.) show +300.63 383.00 1.000000 4n +304.31 383.75 moveto +304.31 404.00 lineto stroke +325.50 386.00 1.000000 4n +329.18 386.75 moveto +329.18 407.00 lineto stroke +356.76 383.00 1.000000 4n +360.44 383.75 moveto +360.44 404.00 lineto stroke +383.23 380.00 1.000000 4n +386.91 380.75 moveto +386.91 401.00 lineto stroke +410.18 377.00 1.000000 4n +403.95 377.00 moveto +416.41 377.00 lineto stroke +413.86 377.75 moveto +413.86 398.00 lineto stroke +439.54 380.00 1.000000 2n +443.43 380.75 moveto +443.43 401.00 lineto stroke +restore +% S_BAR +45 linenum +0.70 setlinewidth +486.25 407.00 moveto +486.25 383.00 lineto stroke +489.25 407.00 moveto +489.25 383.00 lineto stroke +% S_SSV +49 linenum +% S_CLEFSIG +% S_FEED +47 linenum +554.40 383.00 489.60 5 1.000000 1.000000 stf +% S_CLEFSIG +134.19 305.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +52 linenum +/Times-Roman findfont +12 scalefont +setfont +154.98 281.90 moveto +(You) show +/Times-Roman findfont +12 scalefont +setfont +179.47 281.90 moveto +(can) show +/Times-Roman findfont +12 scalefont +setfont +213.14 281.90 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +201.50 281.90 moveto +(al) show +/Times-Roman findfont +12 scalefont +setfont +219.15 281.90 moveto +(so) show +/Times-Roman findfont +12 scalefont +setfont +235.01 281.90 moveto +(use) show +/Times-Roman findfont +12 scalefont +setfont +277.89 281.90 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +256.23 281.90 moveto +(tup) show +/Times-Roman findfont +12 scalefont +setfont +287.28 281.90 moveto +(lets,) show +160.13 296.00 1.000000 4n +163.81 296.75 moveto +163.81 317.00 lineto stroke +183.63 299.00 1.000000 4n +187.31 299.75 moveto +187.31 320.00 lineto stroke +204.65 302.00 1.000000 4n +208.33 302.75 moveto +208.33 323.00 lineto stroke +221.81 305.00 1.000000 4n +225.49 305.75 moveto +225.49 326.00 lineto stroke +239.00 299.00 1.000000 4n +242.68 299.75 moveto +242.68 320.00 lineto stroke +261.04 296.00 1.000000 2n +264.94 296.75 moveto +264.94 317.00 lineto stroke +292.19 296.00 1.000000 2n +296.09 296.75 moveto +296.09 317.00 lineto stroke +restore +% S_BAR +54 linenum +0.70 setlinewidth +% S_CHHEAD +% S_STAFF +% staff 1 +save +56 linenum +/Times-Roman findfont +12 scalefont +setfont +331.65 281.90 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +322.01 281.90 moveto +(A) show +/Times-Roman findfont +12 scalefont +setfont +335.66 281.90 moveto +(long) show +/Times-Roman findfont +12 scalefont +setfont +359.92 281.90 moveto +(with) show +/Times-Roman findfont +12 scalefont +setfont +404.40 281.90 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +388.24 281.90 moveto +(in) show +/Times-Roman findfont +12 scalefont +setfont +434.12 281.90 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +414.28 281.90 moveto +(vis) show +/Times-Roman findfont +12 scalefont +setfont +443.00 281.90 moveto +(bars.) show +325.16 302.00 1.000000 4n +328.85 302.75 moveto +328.85 323.00 lineto stroke +340.97 305.00 1.000000 4n +344.65 305.75 moveto +344.65 326.00 lineto stroke +365.23 299.00 1.000000 4n +368.91 299.75 moveto +368.91 320.00 lineto stroke +391.55 296.00 1.000000 2n +395.45 296.75 moveto +395.45 317.00 lineto stroke +418.76 299.00 1.000000 2n +422.66 299.75 moveto +422.66 320.00 lineto stroke +448.75 296.00 1.000000 2n +458.23 296.00 1.000000 dot +452.64 296.75 moveto +452.64 317.00 lineto stroke +restore +% S_BAR +58 linenum +0.70 setlinewidth +486.25 323.00 moveto +486.25 299.00 lineto stroke +489.25 323.00 moveto +489.25 299.00 lineto stroke +% S_SSV +62 linenum +% S_FEED +60 linenum +554.40 299.00 489.60 5 1.000000 1.000000 stf +% S_CLEFSIG +134.19 221.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +65 linenum +/Times-Roman findfont +12 scalefont +setfont +156.18 195.00 moveto +(Set) show +/Times-Roman findfont +12 scalefont +setfont +198.52 195.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +174.54 195.00 moveto +(stem) show +/Times-Roman findfont +12 scalefont +setfont +202.81 195.00 moveto +(len) show +/Times-Roman findfont +12 scalefont +setfont +225.29 195.00 moveto +(to) show +/Times-Roman findfont +12 scalefont +setfont +269.28 195.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +246.84 195.00 moveto +(ze) show +/Times-Roman findfont +12 scalefont +setfont +284.06 195.00 moveto +(ro,) show +160.02 233.00 1.000000 4n +181.20 230.00 1.000000 4n +206.46 227.00 1.000000 4n +227.61 221.00 1.000000 4n +250.50 224.00 1.000000 2n +287.30 224.00 1.000000 2n +restore +% S_BAR +67 linenum +0.70 setlinewidth +% S_CHHEAD +% S_STAFF +% staff 1 +save +69 linenum +/Times-Roman findfont +12 scalefont +setfont +321.96 195.00 moveto +(to) show +/Times-Roman findfont +12 scalefont +setfont +340.71 195.00 moveto +(get) show +/Times-Roman findfont +12 scalefont +setfont +391.66 195.00 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +368.23 195.00 moveto +(stem) show +/Times-Roman findfont +12 scalefont +setfont +395.40 195.00 moveto +(less) show +/Times-Roman findfont +12 scalefont +setfont +422.32 195.00 moveto +(notes.) show +324.29 218.00 1.000000 4n +344.36 215.00 1.000000 2n +374.89 212.00 1.000000 4n +399.90 209.00 1.000000 4n +393.67 209.00 moveto +406.14 209.00 lineto stroke +429.40 212.00 1.000000 1n +restore +% S_BAR +71 linenum +0.70 setlinewidth +484.10 239.00 moveto +484.10 215.00 lineto stroke +3.00 setlinewidth +488.10 239.00 moveto +488.10 215.00 lineto stroke +0.70 setlinewidth +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Roman +%%Pages: 2 +%%EndDocument +end PEND 69.336 694 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.5 F)72.836 694 R(or)-.35 E(cing shar) +-.252 E(ed noteheads)-.252 E 69.336 712 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .933(Mup will automatically share note head\ +s when it can \214gure out it is safe and proper to do so. Ho)72.77 712 +R(we)-.25 E -.15(ve)-.25 G -.4(r,).15 G .94 +(there may be some unusual cases where you w)69.336 724 R .94(ould lik) +-.1 F 3.44(et)-.1 G 3.44(of)-3.44 G .94(orce the notes from tw)-3.44 F +3.44(ov)-.1 G .94(oices to share note)-3.64 F .764(heads e)69.336 736 R +-.15(ve)-.25 G 3.264(nw).15 G .764(hen Mup w)-3.264 F .763 +(ould not do that. That can be done by specifying a horizontal of)-.1 F +.763(fset of zero, i.e.,)-.25 F EP +%%Page: 135 141 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(35 -)-2.5 E +([ho 0], on one or both of the v)69.336 96 Q(oices.)-.2 E 69.336 114 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.6 Manually)72.836 114 R +(placed tuplet numbers)3.5 E 69.336 132 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF(Generally)72.168 132 Q 2.832(,M)-.65 G .333 +(up will place tuplet numbers for you.)-2.832 F(Ho)5.333 E(we)-.25 E +-.15(ve)-.25 G 1.133 -.4(r, y).15 H .333 +(ou do need to print them yourself on cross-).4 F(staf)69.336 144 Q +3.089(fb)-.25 G 3.089(eams. And)-3.089 F .589 +(there may be cases where you choose to use 'n' to turn of)3.089 F 3.089 +(fM)-.25 G(up')-3.089 E 3.089(sa)-.55 G .589(utomatic printing of)-3.089 +F .663(tuplet numbers, in order to print them manually in a dif)69.336 +156 R .664(ferent place than Mup w)-.25 F 3.164(ould. Mup)-.1 F .664 +(normally uses)3.164 F(ne)69.336 168 Q .08 +(wcentury boldital font for tuplet numbers, in 11-point size for re)-.25 +F .079(gular notes and 9-point for cue notes.)-.15 F(So)5.079 E 1.237 +(to mak)69.336 180 R 3.737(ey)-.1 G 1.238(our manually placed tuplet nu\ +mbers look the same as automatic ones, you might use a macro)-3.737 F +(something lik)69.336 192 Q 2.5(et)-.1 G(his:)-2.5 E/F1 10/Courier@0 SF +(define TUPNUM\(NUM\) "\\f\(NX\)\\s\(11\)" +`NUM` @)105.336 210 Q +(1: { 8c; d; e; } 3n; 2.us;)105.336 222 Q +(rom above 1 dist0: 1.34 TUPNUM\(3\);)105.336 234 Q(bar)105.336 246 Q F0 +(Or another approach w)69.336 266 Q(ould be something lik)-.1 E 2.5(et) +-.1 G(his:)-2.5 E F1 +(define TN\(NUM,WHERE,D,N\) newcentury boldital WHERE dist D: N `NUM`;@) +105.336 284 Q(1: { 8c; d; e; } 3n; 2.us;)105.336 296 Q +(TN\(3,above 1,0,1.34\))105.336 308 Q(bar)105.336 320 Q 69.336 346 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.7 Manual)72.836 346 R +(placement of notes)3.5 E 69.336 364 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .86(Mup supports up to three v)72.696 364 R +.86(oices per staf)-.2 F .86 +(f. If you need more than that, such as when 4 notes of dif)-.25 F +(ferent)-.25 E .645 +(lengths occur on the same beat, it is possible to position e)69.336 376 +R .645(xtra notes manually)-.15 F 5.645(.M)-.65 G .645 +(anually positioned notes)-5.645 F(will not be included in MIDI output.) +69.336 388 Q .092(First of all, unless the fourth v)69.336 406 R .092 +(oice is v)-.2 F .092(ertically f)-.15 F .092(ar a)-.1 F -.1(wa)-.15 G +2.592(yf).1 G .091(rom the other tw)-2.592 F .091(o, you')-.1 F .091 +(ll probably need to reserv)-.1 F(e)-.15 E .313(some e)69.336 418 R .314 +(xtra space to the left or right of the other chords. This can be done \ +by adding a bit of padding to the)-.15 F 2.975(chord. If)69.336 430 R +.475(you w)2.975 F .475(ant the e)-.1 F .474 +(xtra note on the left of the re)-.15 F .474(gular v)-.15 F .474 +(oices, add padding to whiche)-.2 F -.15(ve)-.25 G 2.974(rr).15 G -.15 +(eg)-2.974 G .474(ular v).15 F(oice)-.2 E .311(is leftmost. If you w) +69.336 442 R .312(ant it on the right, the padding will ha)-.1 F .612 +-.15(ve t)-.2 H 2.812(og).15 G 2.812(oo)-2.812 G 2.812(nt)-2.812 G .312 +(he follo)-2.812 F .312(wing note, or on the bar line)-.25 F .174(if yo\ +u are on the last chord of a measure. The amount of padding to add may \ +ha)69.336 454 R .473 -.15(ve t)-.2 H 2.673(ob).15 G 2.673(ed)-2.673 G +.173(etermined by trial)-2.673 F .308 +(and error; 5 stepsizes is a good \214rst guess. Ne)69.336 466 R .308 +(xt, set a location tag on one of the notes in one of the re)-.15 F +(gular)-.15 E 2.676(groups. The)69.336 478 R .176 +(manually-positioned note will be placed relati)2.676 F .476 -.15(ve t) +-.25 H 2.676(ot).15 G .176 +(hat location tag. The x will be slightly left)-2.676 F .055 +(or right of the west or east of the e)69.336 490 R .056 +(xisting group; something lik)-.15 F 2.556(e3s)-.1 G .056 +(tepsizes might be a good \214rst guess. The)-2.556 F 2.935(yc)69.336 +502 S .435(an be speci\214ed in terms of stepsizes up from the note you\ + used for the location tag. Y)-2.935 F .434(ou can use a print)-1.1 F +.143(statement using one of the special music characters, such as: dbl) +69.336 514 R .144(whole, 1n, up2n, dn2n, up4n, up32n, etc. If)-.1 F .629 +(the note needs ledger lines, dots, or accidentals, these too ha)69.336 +526 R .928 -.15(ve t)-.2 H 3.128(ob).15 G 3.128(em)-3.128 G .628 +(anually positioned, which can be a)-3.128 F(bit trick)69.336 538 Q 1.3 +-.65(y. H)-.15 H(ere is a simple e).65 E(xample:)-.15 E/F1 10/Courier@0 +SF(score)105.336 556 Q(vscheme=3o)105.336 568 Q(beamstyle=4,4,4,4) +105.336 580 Q(music)105.336 604 Q 6(11)105.336 616 S 6(:[)-6 G +(pad 4] 4g =h; a; b; a;)-6 E 6(12)105.336 628 S 6(:4)-6 G(.c;8;2;)-6 E 6 +(13)105.336 640 S 6(:[)-6 G(down] 8e;; [ho 0] 2.f;)-6 E +(print \(h.w - 2.3, h.y + 3\) "\\\(up2n\)")105.336 652 Q(bar)105.336 664 +Q EP +%%Page: 136 142 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(36 -)-2.5 E 95.836 96 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 79 rlineto 384 0 rlineto 0 79 neg rlineto closepath stroke grestore +EEND 128 684 384 384 -79 79 94.836 175 PBEGIN +%%BeginDocument: mugex90.ps +%%BoundingBox: 128 684 512 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_FEED +583.49 803.00 496.80 5 1.000000 1.000000 stf +% S_CLEFSIG +163.28 725.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +202.88 725.00 1.000000 4n +0.70 setlinewidth +206.56 725.75 moveto +206.56 746.00 lineto stroke +282.53 728.00 1.000000 4n +286.21 728.75 moveto +286.21 749.00 lineto stroke +366.77 731.00 1.000000 4n +370.45 731.75 moveto +370.45 752.00 lineto stroke +435.52 728.00 1.000000 4n +439.20 728.75 moveto +439.20 749.00 lineto stroke +202.88 713.00 1.000000 4n +212.14 710.00 1.000000 dot +196.65 713.00 moveto +209.11 713.00 lineto stroke +199.20 712.25 moveto +199.20 692.00 lineto stroke +322.91 713.00 1.000000 4n +316.68 713.00 moveto +329.14 713.00 lineto stroke +319.23 712.25 moveto +319.23 692.00 lineto stroke +322.25 692.00 1.000000 upflag +366.77 713.00 1.000000 2n +360.32 713.00 moveto +373.21 713.00 lineto stroke +362.87 712.25 moveto +362.87 692.00 lineto stroke +221.17 719.00 1.000000 4n +217.49 718.25 moveto +217.49 699.50 lineto stroke +244.90 719.00 1.000000 4n +241.21 718.25 moveto +241.21 699.50 lineto stroke +282.53 722.00 1.000000 2n +292.01 722.00 1.000000 dot +278.63 721.25 moveto +278.63 701.00 lineto stroke +newpath +217.14 701.00 moveto +241.56 701.00 lineto +241.56 698.00 lineto +217.14 698.00 lineto +closepath +fill +restore +% S_PRHEAD +11 linenum +/Times-Roman findfont +12 scalefont +setfont +191.95 734.00 moveto +197.17 734.00 1.000000 up2n +202.39 734.00 moveto +% S_BAR +12 linenum +0.70 setlinewidth +496.45 743.00 moveto +496.45 719.00 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Roman +%%Pages: 2 +%%EndDocument +end PEND/F0 10/Times-Roman@0 SF .252(In this e)69.336 189 R .252 +(xample, 4 stepsizes of padding w)-.15 F .252 +(as added to the quarter note g of v)-.1 F .253(oice 1 on staf)-.2 F +2.753(f1)-.25 G 2.753(.Al)-2.753 G .253(ocation tag)-2.753 F .561("h" w) +69.336 201 R .561 +(as set to this note. After the information about the second v)-.1 F +.561(oice on staf)-.2 F 3.061(f1)-.25 G 3.061(,ah)-3.061 G .561 +(alf note w)-3.061 F .561(as manually)-.1 F +(placed 2.3 stepsizes left of the \214rst v)69.336 213 Q +(oice and at pitch c+ \(3 steps up from the g\).)-.2 E .367(If you also\ + need to place an accidental and/or dots, more padding should be reques\ +ted, and additional print)69.336 231 R(statements used for each item. F) +69.336 243 Q(or e)-.15 E +(xample, you could specify perhaps 5 stepsizes of padding, then add:) +-.15 E/F1 10/Courier@0 SF(print \(h.w - 5, h.y + 3\) "\\\(flat\)") +105.336 261 Q 95.836 270.6 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 79 rlineto 384 0 rlineto 0 79 neg rlineto closepath stroke grestore +EEND 128 684 384 384 -79 79 94.836 349.6 PBEGIN +%%BeginDocument: mugex91.ps +%%BoundingBox: 128 684 512 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_FEED +583.49 803.00 496.80 5 1.000000 1.000000 stf +% S_CLEFSIG +163.28 725.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +205.81 725.00 1.000000 4n +0.70 setlinewidth +209.49 725.75 moveto +209.49 746.00 lineto stroke +284.66 728.00 1.000000 4n +288.34 728.75 moveto +288.34 749.00 lineto stroke +368.05 731.00 1.000000 4n +371.73 731.75 moveto +371.73 752.00 lineto stroke +436.10 728.00 1.000000 4n +439.78 728.75 moveto +439.78 749.00 lineto stroke +205.81 713.00 1.000000 4n +215.08 710.00 1.000000 dot +199.58 713.00 moveto +212.04 713.00 lineto stroke +202.13 712.25 moveto +202.13 692.00 lineto stroke +324.64 713.00 1.000000 4n +318.41 713.00 moveto +330.87 713.00 lineto stroke +320.96 712.25 moveto +320.96 692.00 lineto stroke +323.98 692.00 1.000000 upflag +368.05 713.00 1.000000 2n +361.60 713.00 moveto +374.49 713.00 lineto stroke +364.15 712.25 moveto +364.15 692.00 lineto stroke +224.11 719.00 1.000000 4n +220.43 718.25 moveto +220.43 699.50 lineto stroke +247.43 719.00 1.000000 4n +243.75 718.25 moveto +243.75 699.50 lineto stroke +284.66 722.00 1.000000 2n +294.14 722.00 1.000000 dot +280.76 721.25 moveto +280.76 701.00 lineto stroke +newpath +220.08 701.00 moveto +244.10 701.00 lineto +244.10 698.00 lineto +220.08 698.00 lineto +closepath +fill +restore +% S_PRHEAD +10 linenum +/Times-Roman findfont +12 scalefont +setfont +194.88 734.00 moveto +200.10 734.00 1.000000 up2n +205.32 734.00 moveto +% S_PRHEAD +11 linenum +/Times-Roman findfont +12 scalefont +setfont +186.78 734.00 moveto +190.52 734.00 1.000000 flat +194.27 734.00 moveto +% S_BAR +12 linenum +0.70 setlinewidth +496.45 743.00 moveto +496.45 719.00 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Roman +%%Pages: 2 +%%EndDocument +end PEND/F0 10/Times-Roman@0 SF +(to place a \215at sign in front of the c.)69.336 363.6 Q .361 +(Ledger lines needed by the notes also ha)69.336 381.6 R .661 -.15(ve t) +-.2 H 2.861(ob).15 G 2.861(ep)-2.861 G .36(laced manually)-2.861 F 2.86 +(,u)-.65 G .36(sing the "line" command. If the note is)-2.86 F .177 +(more than three steps abo)69.336 393.6 R .478 -.15(ve o)-.15 H 2.678 +(rb).15 G(elo)-2.678 E 2.678(wt)-.25 G .178(he staf)-2.678 F .178 +(f, more than one ledger line w)-.25 F .178(ould be needed, and each w) +-.1 F(ould)-.1 E 1.905(need to be speci\214ed separately)69.336 405.6 R +4.404(.T)-.65 G 1.904(he y coordinate of the each ledger line w)-4.404 F +1.904(ould be the same as the y)-.1 F .186(coordinate of the note, plus\ + or minus some number of step sizes. The length of the line depends on \ +the note)69.336 417.6 R .051 +(head. About 4.5 stepsizes is a good estimate for most notes, b)69.336 +429.6 R .05(ut a double whole needs more lik)-.2 F 2.55(e6s)-.1 G +(tepsizes.)-2.55 E 69.336 447.6 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.8 Brack)72.836 447.6 R +(eting notes acr)-.14 E(oss staffs)-.252 E 69.336 465.6 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .914(In k)72.75 465.6 R -.15(ey)-.1 G .914 +(board music, sometimes a brack).15 F .914(et is dra)-.1 F .914 +(wn to indicate that notes from tw)-.15 F 3.414(os)-.1 G(taf)-3.414 E +.915(fs are to be played)-.25 F .56(with the same hand. The brack)69.336 +477.6 R .56(et is really just a v)-.1 F .56 +(ertical line with short horizontal lines at each end. But if)-.15 F +(you need to mak)69.336 489.6 Q 2.5(el)-.1 G(ots of brack)-2.5 E +(ets, a macro with parameters can be v)-.1 E(ery helpful.)-.15 E EP +%%Page: 137 143 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(37 -)-2.5 E/F1 10/Courier@0 +SF(score)105.336 96 Q(staffs=2)117.336 108 Q(staff 2)105.336 132 Q +(clef=bass)117.336 144 Q(vscheme=2f)117.336 156 Q +(// Define a macro to draw a bracket to show that notes on two)105.336 +180 Q(// different staffs are to be played with the same hand.)105.336 +192 Q(// The parameters are location tags for the top and bottom notes) +105.336 204 Q(// to be included in the bracket.)105.336 216 Q +(define BRACK\(TOP, BOT\))105.336 228 Q +(// Draw a short horizontal line 0.5 stepsizes above the top note) +105.336 240 Q +(line \(TOP.w - 2, TOP.n + 0.5\) to \(TOP.w - 1, TOP.n + 0.5\))105.336 +252 Q(// Draw a vertical line from 0.5 stepsizes above the top note) +105.336 264 Q(// to 0.5 stepsizes below the bottom note.)105.336 276 Q +(// Do all the 'x' coordinates relative to the same note \(in)105.336 +288 Q +(// this case the top\), so that if the top and bottom chord happen) +105.336 300 Q +(// to be different widths, the line will still be vertical.)105.336 312 +Q(line \(TOP.w - 2, TOP.n + 0.5\) to \(TOP.w - 2, BOT.s - 0.5\))105.336 +324 Q +(// Draw short horizontal line just below and left of the bottom note.) +105.336 336 Q +(line \(TOP.w - 2, BOT.s - 0.5\) to \(TOP.w - 1, BOT.s - 0.5\))105.336 +348 Q(@)105.336 360 Q(music)105.336 384 Q +(// For each chord that is to get a bracket, add some padding to)105.336 +408 Q(// make sure there is enough room, and set a location tag)105.336 +420 Q(// on the top and bottom notes.)105.336 432 Q +(1: [pad 2] ce =a;[] df =b; [] d =c; [] ce =d;)105.336 444 Q +(2: [pad 2] g =e; [] a =f; [] af =g; [] g =h;)105.336 456 Q 6(22)105.336 +468 S 6(:2)-6 G(cc-; 4g-; cc-;)-6 E +(// Now draw the brackets, using the tags as parameters)105.336 480 Q +(BRACK \(a, e\))105.336 492 Q(BRACK \(b, f\))105.336 504 Q +(BRACK \(c, g\))105.336 516 Q(BRACK \(d, h\))105.336 528 Q(bar)105.336 +540 Q 127.836 549.6 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 141 rlineto 320 0 rlineto 0 141 neg rlineto closepath stroke grestore +EEND 160 622 320 320 -141 141 126.836 690.6 PBEGIN +%%BeginDocument: mugex92.ps +%%BoundingBox: 160 622 480 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_SSV +7 linenum +% S_FEED +612.29 803.00 468.00 5 1.000000 1.000000 stf +612.29 746.72 468.00 5 1.000000 1.000000 stf +0.70 setlinewidth +180.29 743.00 moveto +180.29 662.72 lineto stroke +% S_CLEFSIG +192.08 725.00 1.000000 gclef +192.33 680.72 1.000000 fclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +231.72 719.00 1.000000 4n +231.72 713.00 1.000000 4n +225.49 713.00 moveto +237.95 713.00 lineto stroke +235.40 713.75 moveto +235.40 740.00 lineto stroke +291.66 722.00 1.000000 4n +291.66 716.00 1.000000 4n +295.34 716.75 moveto +295.34 743.00 lineto stroke +351.59 716.00 1.000000 4n +355.27 716.75 moveto +355.27 737.00 lineto stroke +413.37 719.00 1.000000 4n +413.37 713.00 1.000000 4n +407.13 713.00 moveto +419.60 713.00 lineto stroke +417.05 713.75 moveto +417.05 740.00 lineto stroke +restore +% S_STAFF +% staff 2 +save +231.72 683.72 1.000000 4n +0.70 setlinewidth +235.40 684.47 moveto +235.40 704.72 lineto stroke +291.66 686.72 1.000000 4n +295.34 687.47 moveto +295.34 707.72 lineto stroke +351.59 686.72 1.000000 4n +351.59 680.72 1.000000 4n +355.27 681.47 moveto +355.27 707.72 lineto stroke +413.37 683.72 1.000000 4n +417.05 684.47 moveto +417.05 704.72 lineto stroke +231.72 671.72 1.000000 2n +231.72 650.72 1.000000 2n +225.27 650.72 moveto +238.17 650.72 lineto stroke +225.27 656.72 moveto +238.17 656.72 lineto stroke +227.82 670.97 moveto +227.82 629.72 lineto stroke +351.59 662.72 1.000000 4n +347.91 661.97 moveto +347.91 641.72 lineto stroke +413.37 671.72 1.000000 4n +413.37 650.72 1.000000 4n +407.13 650.72 moveto +419.60 650.72 lineto stroke +407.13 656.72 moveto +419.60 656.72 lineto stroke +409.68 670.97 moveto +409.68 629.72 lineto stroke +restore +% S_LINE +36 linenum +0.70 setlinewidth +221.69 723.78 moveto +224.69 723.78 lineto stroke +% S_LINE +36 linenum +221.69 723.78 moveto +221.69 678.95 lineto stroke +% S_LINE +36 linenum +221.69 678.95 moveto +224.69 678.95 lineto stroke +% S_LINE +37 linenum +281.62 726.78 moveto +284.62 726.78 lineto stroke +% S_LINE +37 linenum +281.62 726.78 moveto +281.62 681.95 lineto stroke +% S_LINE +37 linenum +281.62 681.95 moveto +284.62 681.95 lineto stroke +% S_LINE +38 linenum +341.56 720.78 moveto +344.56 720.78 lineto stroke +% S_LINE +38 linenum +341.56 720.78 moveto +341.56 675.95 lineto stroke +% S_LINE +38 linenum +341.56 675.95 moveto +344.56 675.95 lineto stroke +% S_LINE +39 linenum +403.33 723.78 moveto +406.33 723.78 lineto stroke +% S_LINE +39 linenum +403.33 723.78 moveto +403.33 678.95 lineto stroke +% S_LINE +39 linenum +403.33 678.95 moveto +406.33 678.95 lineto stroke +% S_BAR +41 linenum +467.65 743.00 moveto +467.65 719.00 lineto stroke +467.65 686.72 moveto +467.65 662.72 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: +%%Pages: 2 +%%EndDocument +end PEND/F0 10/Times-Roman@0 SF .956(Note that Mup supports cross-staf) +69.336 710.6 R 3.456(fs)-.25 G .957(tems, which is another w)-3.456 F +.957(ay to notate a chord that is split across tw)-.1 F(o)-.1 E(staf) +69.336 722.6 Q(fs, and may often be a better choice.)-.25 E EP +%%Page: 138 144 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(38 -)-2.5 E 69.336 102 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.9 Cr)72.836 102 R(oss-bar beaming) +-.252 E 69.336 120 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF(Generally)71.945 120 Q 2.609(,b)-.65 G .109 +(eams do not cross bar lines, and Mup follo)-2.609 F .109(ws that rule.) +-.25 F(Ho)5.109 E(we)-.25 E -.15(ve)-.25 G .909 -.4(r, i).15 H 2.609(fy) +.4 G .109(ou w)-2.609 F .109(ant beams to cross a)-.1 F 1.192 +(bar line, there are at least tw)69.336 132 R 3.692(op)-.1 G 1.192 +(ossible approaches to getting the desired ef)-3.692 F 1.193 +(fect. The \214rst is to e)-.25 F(xplicitly)-.15 E .115 +(specify stem lengths such that all the beams in the v)69.336 144 R .114 +(arious measures will lie on the same line.)-.25 F -1.1(Yo)5.114 G 2.614 +(uc)1.1 G .114(an then)-2.614 F(use the line command to \214ll in the g) +69.336 156 Q(aps in the beams across the bar lines.)-.05 E .32 +(The other approach is to dra)69.336 174 R 2.82(wi)-.15 G 2.82(nt)-2.82 +G .32(he bar line using the "line" construct.)-2.82 F 1.921 -.8(To d) +5.321 H 2.821(ot).8 G .321(his you \214rst tell Mup that a)-2.821 F .136 +(measure is twice as long as is really is, so that you can put tw)69.336 +186 R 2.635(oa)-.1 G .135(ctual measures inside what Mup thinks is a) +-2.635 F(single measure. Here is an e)69.336 198 Q(xample.)-.15 E/F1 10 +/Courier@0 SF(// First make an empty measure ending with an)105.336 216 +Q(// invisible bar. This is for the sole purpose)105.336 228 Q +(// of allowing the real time signature to be)105.336 240 Q +(// printed and would not be necessary if we)105.336 252 Q +(// wanted to cross a bar line other than)105.336 264 Q +(// the very first bar line of the piece.)105.336 276 Q(1: ms;)105.336 +288 Q(invisbar)105.336 300 Q +(// Now, make the effective time signature twice)105.336 324 Q +(// as long as the real time signature, but use 'n' so this fake)105.336 +336 Q(// time signature is not actually printed.)105.336 348 Q +(// Set up for beaming across the entire double-length measure.)105.336 +360 Q(// \(You could could use other beamstyles if you wish, or custom \ +beaming.\))105.336 372 Q(score time=8/4n)105.336 384 Q(beamstyle=1/2) +105.336 396 Q(music)105.336 408 Q +(// Now do the double-length measure. On the chord)105.336 432 Q +(// just after where we want a bar line, add some extra)105.336 444 Q +(// padding and set a location tag so that we can draw)105.336 456 Q +(// a bar line relative to the tag.)105.336 468 Q +(1: 8c;e;f;d;g;e;f;a; [pad 3; =a]g;e;f;a;g;d+;4c+;)105.336 480 Q +(// Also set a location tag on the next bar line,)105.336 492 Q +(// so that we can get the vertical endpoints of the)105.336 504 Q +(// bar line that we draw from the endpoints of the)105.336 516 Q +(// normal Mup-supplied bar line.)105.336 528 Q(bar =b)105.336 540 Q +(// Now draw the bar line that goes through the beam.)105.336 564 Q +(// Use the horizontal position relative to the "a")105.336 576 Q +(// location tag on the chord in the second actual measure,)105.336 588 +Q(// and get the vertical endpoints from the "b" tag)105.336 600 Q +(// associated with the next bar line.)105.336 612 Q +(line \(a.w + 1, b.y + 4\) to \(a.w + 1, b.y - 4\))105.336 624 Q 91.836 +633.6 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 392 0 rlineto 0 61 neg rlineto closepath stroke grestore +EEND 128 702 392 392 -61 61 90.836 694.6 PBEGIN +%%BeginDocument: mugex93.ps +%%BoundingBox: 128 702 520 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +1 linenum +% S_FEED +576.29 802.79 504.00 5 1.000000 1.000000 stf +% S_CLEFSIG +156.08 724.79 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +restore +% S_BAR +10 linenum +0.70 setlinewidth +% S_SSV +17 linenum +% S_CLEFSIG +% S_CHHEAD +% S_STAFF +% staff 1 +save +185.58 712.79 1.000000 4n +179.34 712.79 moveto +191.81 712.79 lineto stroke +189.26 713.54 moveto +189.26 740.15 lineto stroke +205.67 718.79 1.000000 4n +209.35 719.54 moveto +209.35 741.17 lineto stroke +225.76 721.79 1.000000 4n +229.44 722.54 moveto +229.44 742.20 lineto stroke +245.85 715.79 1.000000 4n +249.53 716.54 moveto +249.53 743.23 lineto stroke +265.94 724.79 1.000000 4n +269.62 725.54 moveto +269.62 744.26 lineto stroke +286.03 718.79 1.000000 4n +289.71 719.54 moveto +289.71 745.28 lineto stroke +306.12 721.79 1.000000 4n +309.80 722.54 moveto +309.80 746.31 lineto stroke +324.71 727.79 1.000000 4n +328.39 728.54 moveto +328.39 747.26 lineto stroke +346.30 724.79 1.000000 4n +349.98 725.54 moveto +349.98 748.36 lineto stroke +366.39 718.79 1.000000 4n +370.07 719.54 moveto +370.07 749.39 lineto stroke +386.48 721.79 1.000000 4n +390.16 722.54 moveto +390.16 750.42 lineto stroke +406.57 727.79 1.000000 4n +410.25 728.54 moveto +410.25 751.45 lineto stroke +426.66 724.79 1.000000 4n +430.34 725.54 moveto +430.34 752.47 lineto stroke +446.75 736.79 1.000000 4n +450.43 737.54 moveto +450.43 753.50 lineto stroke +470.16 733.79 1.000000 4n +466.48 733.04 moveto +466.48 712.79 lineto stroke +newpath +188.91 741.65 moveto +450.78 755.00 lineto +450.78 752.00 lineto +188.91 738.65 lineto +closepath +fill +restore +% S_BAR +30 linenum +0.70 setlinewidth +503.65 742.79 moveto +503.65 718.79 lineto stroke +% S_LINE +37 linenum +335.27 742.79 moveto +335.27 718.79 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: +%%Pages: 2 +%%EndDocument +end PEND 69.336 714.6 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.10 Mixed)72.836 714.6 R(time signatur) +3.5 E(es)-.252 E 69.336 732.6 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .649 +(Once in a while, music is written with dif)72.485 732.6 R .65 +(ferent time signatures on dif)-.25 F .65(ferent staf)-.25 F .65 +(fs. Mup does not support)-.25 F EP +%%Page: 139 145 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(39 -)-2.5 E .158 +(this directly)69.336 96 R 2.658(,b)-.65 G .157(ut it is possible to si\ +mulate it for the case where the time signatures reduce to the same v) +-2.858 F(alue,)-.25 E .85(for e)69.336 108 R .85 +(xample, 3/4 and 6/8 time \(since 6/8 tak)-.15 F .851 +(en as a fraction and reduced to lo)-.1 F .851(west terms is 3/4\). Y) +-.25 F .851(ou can)-1.1 F(mak)69.336 120 Q 4.815(et)-.1 G 2.314(he outp\ +ut use both 3/4 and 6/8 by using a non-printing time signature, then pl\ +acing the time)-4.815 F(signatures manually)69.336 132 Q 5(.H)-.65 G +(ere is an e)-5 E(xample of ho)-.15 E 2.5(wt)-.25 G 2.5(od)-2.5 G 2.5 +(ot)-2.5 G(hat:)-2.5 E/F1 10/Courier@0 SF(score)105.336 150 Q +(// set time signature to 3/4 but don't print it)130.336 162 Q +(time=3/4n)130.336 174 Q(staffs=2)130.336 186 Q(staff 1)105.336 210 Q +(// We want this staff to be in 3/4 time,)130.336 222 Q +(// so beam things in groups of)130.336 234 Q(// quarter note times.) +130.336 246 Q(beamstyle=4,4,4)130.336 258 Q(staff 2)105.336 282 Q +(// We want this staff to effectively be)130.336 294 Q +(// in 6/8 time, so we'll beam things)130.336 306 Q +(// in groups of dotted quarters.)130.336 318 Q(beamstyle=4., 4.)130.336 +330 Q(// In real 6/8 time, the time unit would)130.336 342 Q +(// be eighth note, so make that the default)130.336 354 Q(timeunit=8) +130.336 366 Q(music)105.336 390 Q +(// Add padding to the first chord on at least one)105.336 414 Q +(// of the staffs, to make room for the manually placed)105.336 426 Q +(// time signatures, and set location tags)105.336 438 Q +(1: [pad 5; =t] c; 8d; e; f; g;)105.336 450 Q(2: [=s] g; f; g; 4.c;) +105.336 462 Q(// Manually place the time signatures)105.336 486 Q +(// They are printed in 16-point newcentury bold font,)105.336 498 Q +(// relative to the location tags that were set.)105.336 510 Q +(// First print the 3/4)105.336 522 Q +(print \(t.w - 4, t.y\) "\\f\(newcentury bold\)\\s\(16\)3";)105.336 534 +Q(print \(t.w - 4, t.y - 4\) "\\f\(newcentury bold\)\\s\(16\)4";)105.336 +546 Q(// Then print the 6/8)105.336 570 Q +(print \(t.w - 4, s.y\) "\\f\(newcentury bold\)\\s\(16\)6";)105.336 582 +Q(print \(t.w - 4, s.y - 4\) "\\f\(newcentury bold\)\\s\(16\)8";)105.336 +594 Q(bar)105.336 606 Q 127.836 615.6 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 115 rlineto 320 0 rlineto 0 115 neg rlineto closepath stroke grestore +EEND 160 648 320 320 -115 115 126.836 730.6 PBEGIN +%%BeginDocument: mugex94.ps +%%BoundingBox: 160 648 480 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_SSV +9 linenum +% S_SSV +15 linenum +% S_FEED +612.29 803.00 468.00 5 1.000000 1.000000 stf +612.29 749.00 468.00 5 1.000000 1.000000 stf +0.70 setlinewidth +180.29 743.00 moveto +180.29 665.00 lineto stroke +% S_CLEFSIG +192.08 725.00 1.000000 gclef +192.08 671.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +237.65 713.00 1.000000 4n +231.42 713.00 moveto +243.88 713.00 lineto stroke +241.33 713.75 moveto +241.33 734.00 lineto stroke +314.73 716.00 1.000000 4n +318.41 716.75 moveto +318.41 735.81 lineto stroke +353.27 719.00 1.000000 4n +356.96 719.75 moveto +356.96 738.81 lineto stroke +391.81 722.00 1.000000 4n +395.50 722.75 moveto +395.50 741.81 lineto stroke +431.19 725.00 1.000000 4n +434.88 725.75 moveto +434.88 744.81 lineto stroke +newpath +318.06 737.31 moveto +357.31 740.31 lineto +357.31 737.31 lineto +318.06 734.31 lineto +closepath +fill +newpath +395.15 743.31 moveto +435.23 746.31 lineto +435.23 743.31 lineto +395.15 740.31 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +237.65 671.00 1.000000 4n +0.70 setlinewidth +241.33 671.75 moveto +241.33 690.50 lineto stroke +276.19 668.00 1.000000 4n +279.87 668.75 moveto +279.87 690.50 lineto stroke +314.73 671.00 1.000000 4n +318.41 671.75 moveto +318.41 690.50 lineto stroke +353.27 659.00 1.000000 4n +362.54 662.00 1.000000 dot +347.04 659.00 moveto +359.51 659.00 lineto stroke +356.96 659.75 moveto +356.96 680.00 lineto stroke +newpath +240.98 692.00 moveto +318.76 692.00 lineto +318.76 689.00 lineto +240.98 689.00 lineto +closepath +fill +restore +% S_PRHEAD +35 linenum +/Times-Roman findfont +12 scalefont +setfont +205.62 731.00 moveto +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +(3) show +% S_PRHEAD +36 linenum +/Times-Roman findfont +12 scalefont +setfont +205.62 719.00 moveto +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +(4) show +% S_PRHEAD +39 linenum +/Times-Roman findfont +12 scalefont +setfont +205.62 677.00 moveto +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +(6) show +% S_PRHEAD +40 linenum +/Times-Roman findfont +12 scalefont +setfont +205.62 665.00 moveto +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +(8) show +% S_BAR +42 linenum +0.70 setlinewidth +467.65 743.00 moveto +467.65 719.00 lineto stroke +467.65 689.00 moveto +467.65 665.00 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Roman /NewCenturySchlbk-Bold +%%Pages: 2 +%%EndDocument +end PEND EP +%%Page: 140 146 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(40 -)-2.5 E 69.336 102 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.11 Differ)72.836 102 R(ent mar)-.252 E +(gins f)-.14 E(or odd/e)-.35 E -.14(ve)-.21 G 3.5(np).14 G(ages)-3.5 E +69.336 120 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .629(Sometimes you may w)72.465 120 R .629 +(ant to mak)-.1 F 3.129(em)-.1 G(ar)-3.129 E .629(gins dif)-.18 F .629 +(ferent for odd and e)-.25 F -.15(ve)-.25 G 3.13(np).15 G .63 +(ages, for e)-3.13 F .63(xample, if you w)-.15 F .63(ant to)-.1 F 1.184 +(put music in a ringed binder)69.336 132 R 3.684(,a)-.4 G 1.184 +(nd thus w)-3.684 F 1.183(ant to of)-.1 F 1.183 +(fset the printing on the pages to a)-.25 F -.2(vo)-.2 G 1.183 +(id the holes in the).2 F(paper)69.336 144 Q 6.117(.W)-.55 G 1.117 +(hile you can')-6.117 F 3.617(td)-.18 G 3.617(ot)-3.617 G 1.117 +(his directly)-3.617 F 3.618(,y)-.65 G 1.118(ou can get the desired ef) +-3.618 F 1.118(fect by using appropriate macros, and)-.25 F +(then printing the odd and e)69.336 156 Q -.15(ve)-.25 G 2.5(np).15 G +(ages in tw)-2.5 E 2.5(op)-.1 G(asses.)-2.5 E +(In the Mup input \214le, put something lik)69.336 174 Q 2.5(et)-.1 G +(his:)-2.5 E/F1 10/Courier@0 SF(score)105.336 192 Q +(// if the WIDELEFT macro is set,)130.336 204 Q +(// make the left margin extra wide,)130.336 216 Q +(// otherwise if WIDERIGHT is set,)130.336 228 Q +(// make the right margin extra wide,)130.336 240 Q +(// otherwise make them equal.)130.336 252 Q(ifdef WIDELEFT)130.336 264 +Q(leftmargin=1)155.336 276 Q(rightmargin=0.5)155.336 288 Q +(else ifdef WIDERIGHT)130.336 300 Q(leftmargin=0.5)155.336 312 Q +(rightmargin=1)155.336 324 Q(else)130.336 336 Q(leftmargin=0.75)155.336 +348 Q(rightmargin=0.75)155.336 360 Q(endif endif)130.336 372 Q F0 +(Then when printing, print in tw)69.336 398 Q 2.5(op)-.1 G +(asses. First print the odd pages:)-2.5 E F1 +(mupprnt -oodd -DWIDELEFT file.mup)105.336 416 Q F0 +(Then turn the paper o)69.336 436 Q -.15(ve)-.15 G 2.5(ra).15 G +(nd print the e)-2.5 E -.15(ve)-.25 G 2.5(np).15 G(ages:)-2.5 E F1 +(mupprnt -oeven -DWIDERIGHT file.mup)105.336 454 Q F0 .577 +(This idea should w)69.336 480 R .577 +(ork as long as the sum of the left and right mar)-.1 F .576 +(gins are equal between the WIDELEFT)-.18 F 1.073 +(and WIDERIGHT parts. Otherwise you may get dif)69.336 492 R 1.073 +(ferent numbers of measures on each page in the tw)-.25 F(o)-.1 E +(runs, and you')69.336 504 Q(ll end up missing or repeating measures.) +-.1 E 69.336 522 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.12 Marking)72.836 522 R +(complicated tempo changes)3.5 E 69.336 540 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .049 +(Sometimes you may wish to indicate tempo changes by sho)71.885 540 R +.048(wing 2 note v)-.25 F .048(alues with an equals sign between)-.25 F +.273(them. F)69.336 552 R .273(or simple cases, this is f)-.15 F .274 +(airly straightforw)-.1 F .274(ard, b)-.1 F .274(ut if you w)-.2 F .274 +(ant to include beamed notes or a triplet, a)-.1 F .157(little more w) +69.336 564 R .157 +(ork is required. Another use of this notation is to sho)-.1 F 2.657(wt) +-.25 G .156(hat the music is to be played in "swing)-2.657 F .73 +(time," as in this e)69.336 576 R .73(xample, which has tw)-.15 F 3.23 +(oo)-.1 G .73 +(rdinary eight notes on one side of the equals sign, and a triplet)-3.23 +F(made up of a quarter and eighth note on the other:)69.336 588 Q EP +%%Page: 141 147 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(41 -)-2.5 E/F1 10/Courier@0 +SF(score)105.336 96 Q(// This example assumes "size" is set to 15) +130.336 108 Q(size=15)130.336 120 Q(beamstyle=4,4)130.336 132 Q(music) +105.336 156 Q(// set a location tag)105.336 180 Q(1: [=c] 8c+;a;g;f;) +105.336 192 Q(// set X and Y to where the first note will be placed) +105.336 216 Q(define X c.x - 3 @)105.336 228 Q(define Y c.y + 5 @) +105.336 240 Q(// print "straight 8ths = triplet quarter plus 8th") +105.336 264 Q(// print the basic notes and equal sign)105.336 288 Q +(print \(X, Y\) "\\\(smup4n\))105.336 300 Q 6(\\\(smup4n\) =)12 F 6 +(\\\(smup4n\) \\\(smup8n\)")6 F +(// print the beam between the straight 8th notes)105.336 324 Q +(wide line \(X + 2.1, Y + 5.5\) to \(X + 7.2, Y + 5.5\))105.336 336 Q +(// now do the triplet bracket)105.336 360 Q(line \(X + 14.7, Y + 7.0\)) +105.336 372 Q(to \(X + 17.6, Y + 7.0\) // horz left top segment)12 E +(line \(X + 19.4, Y + 7.0\))105.336 384 Q +(to \(X + 22.5, Y + 7.0\) // horz right top segment)12 E(line \(X + 14.\ +7, Y + 7.05\) to \(X + 14.7, Y + 5.3\) // vert left side segment)105.336 +396 Q(line \(X + 22.5, Y + 7.05\) to \(X + 22.5, Y + 5.3\) // vert righ\ +t side segment)105.336 408 Q +(// print the 3 in the middle of the bracket)105.336 432 Q +(print \(X + 17.9, Y + 6.1\) "\\s\(8\)\\f\(TI\)3")105.336 444 Q +(// the 3 for the triplet)10 E(bar)105.336 468 Q 151.836 477.6 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 77 rlineto 272 0 rlineto 0 77 neg rlineto closepath stroke grestore +EEND 184 701 272 272 -77 77 150.836 554.6 PBEGIN +%%BeginDocument: mugex95.ps +%%BoundingBox: 184 701 456 778 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +1 linenum +% S_FEED +633.89 803.00 446.40 5 1.000000 1.000000 stf +% S_CLEFSIG +213.68 725.00 1.000000 gclef +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +225.47 731.00 moveto +(2) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +225.47 718.98 moveto +(4) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +257.04 734.00 1.000000 4n +0.70 setlinewidth +253.35 733.25 moveto +253.35 715.00 lineto stroke +304.99 728.00 1.000000 4n +301.31 727.25 moveto +301.31 709.00 lineto stroke +352.95 725.00 1.000000 4n +356.63 725.75 moveto +356.63 744.25 lineto stroke +401.75 722.00 1.000000 4n +405.43 722.75 moveto +405.43 741.25 lineto stroke +newpath +253.00 716.50 moveto +301.66 710.50 lineto +301.66 707.50 lineto +253.00 713.50 lineto +closepath +fill +newpath +356.28 745.75 moveto +405.78 742.75 lineto +405.78 739.75 lineto +356.28 742.75 lineto +closepath +fill +restore +% S_PRHEAD +22 linenum +/Times-Roman findfont +15 scalefont +setfont +248.04 746.00 moveto +251.84 748.24 0.750000 up4n +255.65 746.00 moveto +( ) show +267.02 748.24 0.750000 up4n +270.82 746.00 moveto +( = ) show +294.43 748.24 0.750000 up4n +298.24 746.00 moveto +( ) show +311.63 748.24 0.750000 up8n +317.46 746.00 moveto +% S_LINE +24 linenum +3.00 setlinewidth +254.34 762.50 moveto +269.64 762.50 lineto stroke +% S_LINE +27 linenum +0.70 setlinewidth +292.14 767.00 moveto +300.84 767.00 lineto stroke +% S_LINE +28 linenum +306.24 767.00 moveto +315.54 767.00 lineto stroke +% S_LINE +29 linenum +292.14 767.15 moveto +292.14 761.90 lineto stroke +% S_LINE +30 linenum +315.54 767.15 moveto +315.54 761.90 lineto stroke +% S_PRHEAD +34 linenum +/Times-Roman findfont +15 scalefont +setfont +301.74 764.30 moveto +/Times-Italic findfont +8 scalefont +setfont +(3) show +% S_BAR +36 linenum +446.05 743.00 moveto +446.05 719.00 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Roman /Times-Italic /NewCenturySchlbk-Bold +%%Pages: 2 +%%EndDocument +end PEND/F0 10/Times-Roman@0 SF .14(Note that if you w)69.336 574.6 R +.14(ant a piece to be played in swing time, you may also w)-.1 F .139 +(ant to set the swingunit parameter)-.1 F(,)-.4 E(which will mak)69.336 +586.6 Q 2.5(et)-.1 G(he MIDI output use swing time.)-2.5 E 69.336 604.6 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.13 Placing)72.836 604.6 R(se)3.5 E +-.14(ve)-.21 G(ral songs on one page).14 E 69.336 622.6 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .657 +(Sometimes you may wish to print more than one song on the same page.) +72.493 622.6 R .657(While Mup considers all of its)5.657 F .188 +(input to be a single song, it is possible to get the ef)69.336 634.6 R +.188(fect of separate songs.)-.25 F .188 +(First of all, on the last bar line of)5.188 F 1.135 +(\214rst song, use "hidechanges.")69.336 646.6 R 1.135(That w)6.135 F +(ay)-.1 E 3.635(,i)-.65 G 3.635(ft)-3.635 G 1.135(he k)-3.635 F 1.436 +-.15(ey o)-.1 H 3.636(ra).15 G -.15(ny)-3.636 G 1.136(thing is dif).15 F +1.136(ferent in the ne)-.25 F 1.136(xt song, Mup w)-.15 F(on')-.1 E(t) +-.18 E .384(print the changes at the end of the \214rst song. Then use \ +a "block" for printing the titles for the second song.)69.336 658.6 R +(Here is an e)69.336 670.6 Q(xample:)-.15 E EP +%%Page: 142 148 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(42 -)-2.5 E/F1 10/Courier@0 +SF(score)105.336 96 Q(scoresep=10,14)130.336 108 Q(label="")130.336 120 +Q(header)105.336 132 Q(title \(18\) "Title for first song")130.336 144 Q +(music)105.336 156 Q(1: c;d;e;f;)105.336 168 Q(bar)105.336 180 Q +(1: f;e;d;c;)105.336 192 Q(bar)105.336 204 Q(1: c;d;e;f;)105.336 216 Q +(bar)105.336 228 Q(1: f;d;2c;)105.336 240 Q(endbar)105.336 252 Q +(// force time signature to be printed on next score)105.336 276 Q +(// by changing the time, but only for an invisible measure)105.336 288 +Q(score time=5/4n)105.336 300 Q(music)105.336 312 Q(1: ms;)105.336 324 Q +(invisbar hidechanges)105.336 336 Q +(// Force the block closer to next score,)105.336 360 Q +(// so it will better match the spacing of)105.336 372 Q +(// the title of the first song.)105.336 384 Q(score scoresep=6,6) +105.336 396 Q(// print title for second song)105.336 408 Q(block)105.336 +420 Q(title \(30\) " ")105.336 432 Q +(// Allow some extra room above title)18 E +(title \(18\) "Title for second song")105.336 444 Q(score)105.336 468 Q +(// Set up for second song)130.336 480 Q(time=4/4)130.336 492 Q(key=1&) +130.336 504 Q(music)105.336 528 Q(1: d;e;2f;)105.336 540 Q(bar)105.336 +552 Q(// Put score spacing back to original)105.336 564 Q +(score scoresep=10,14)105.336 576 Q(music)105.336 588 Q(1: a;2g;4f;) +105.336 600 Q(bar)105.336 612 Q(1: 2e;4c;d;)105.336 624 Q(bar)105.336 +636 Q(1: 2g;f;)105.336 648 Q(endbar)105.336 660 Q EP +%%Page: 143 149 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(43 -)-2.5 E 111.836 96 +EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 327 rlineto 352 0 rlineto 0 327 neg rlineto closepath stroke grestore +EEND 128 435 352 352 -327 327 110.836 423 PBEGIN +%%BeginDocument: mugex96.ps +%%BoundingBox: 128 435 480 762 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_FEED +579.00 777.13 468.00 5 1.000000 1.000000 stf +/Times-Roman findfont +12 scalefont +setfont +144.00 705.13 moveto +% S_CLEFSIG +158.79 699.13 1.000000 gclef +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +170.58 705.13 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +170.58 693.11 moveto +(4) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +188.51 687.13 1.000000 4n +0.70 setlinewidth +182.28 687.13 moveto +194.74 687.13 lineto stroke +192.19 687.88 moveto +192.19 708.13 lineto stroke +221.95 690.13 1.000000 4n +225.63 690.88 moveto +225.63 711.13 lineto stroke +255.39 693.13 1.000000 4n +259.07 693.88 moveto +259.07 714.13 lineto stroke +289.66 696.13 1.000000 4n +293.35 696.88 moveto +293.35 717.13 lineto stroke +restore +% S_BAR +12 linenum +0.70 setlinewidth +321.87 717.13 moveto +321.87 693.13 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +334.29 696.13 1.000000 4n +337.98 696.88 moveto +337.98 717.13 lineto stroke +367.73 693.13 1.000000 4n +371.41 693.88 moveto +371.41 714.13 lineto stroke +401.17 690.13 1.000000 4n +404.85 690.88 moveto +404.85 711.13 lineto stroke +435.45 687.13 1.000000 4n +429.21 687.13 moveto +441.68 687.13 lineto stroke +439.13 687.88 moveto +439.13 708.13 lineto stroke +restore +% S_BAR +14 linenum +0.70 setlinewidth +467.65 717.13 moveto +467.65 693.13 lineto stroke +% S_FEED +576.00 711.13 468.00 5 1.000000 1.000000 stf +% S_CLEFSIG +155.79 633.13 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +185.54 621.13 1.000000 4n +179.31 621.13 moveto +191.78 621.13 lineto stroke +189.23 621.88 moveto +189.23 642.13 lineto stroke +219.18 624.13 1.000000 4n +222.86 624.88 moveto +222.86 645.13 lineto stroke +252.81 627.13 1.000000 4n +256.49 627.88 moveto +256.49 648.13 lineto stroke +287.28 630.13 1.000000 4n +290.96 630.88 moveto +290.96 651.13 lineto stroke +restore +% S_BAR +16 linenum +0.70 setlinewidth +319.65 651.13 moveto +319.65 627.13 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +332.11 630.13 1.000000 4n +335.79 630.88 moveto +335.79 651.13 lineto stroke +365.70 624.13 1.000000 4n +369.38 624.88 moveto +369.38 645.13 lineto stroke +404.33 621.13 1.000000 2n +397.88 621.13 moveto +410.78 621.13 lineto stroke +408.23 621.88 moveto +408.23 642.13 lineto stroke +restore +% S_BAR +17 linenum +0.70 setlinewidth +462.50 651.13 moveto +462.50 627.13 lineto stroke +3.00 setlinewidth +466.50 651.13 moveto +466.50 627.13 lineto stroke +0.70 setlinewidth +% S_SSV +21 linenum +% S_CLEFSIG +% S_CHHEAD +% S_STAFF +% staff 1 +save +restore +% S_BAR +24 linenum +0.70 setlinewidth +% S_SSV +29 linenum +% S_CLEFSIG +% S_FEED +31 linenum +% S_BLOCKHEAD +31 linenum +/Times-Roman findfont +30 scalefont +setfont +302.22 584.83 moveto +( ) show +/Times-Roman findfont +18 scalefont +setfont +229.91 565.60 moveto +(Title for second song) show +% S_SSV +36 linenum +% S_FEED +576.00 601.95 468.00 5 1.000000 1.000000 stf +% S_CLEFSIG +155.79 523.95 1.000000 gclef +169.33 529.95 1.000000 flat +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +175.07 529.95 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +175.07 517.94 moveto +(4) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +204.25 514.95 1.000000 4n +207.93 515.70 moveto +207.93 535.95 lineto stroke +237.87 517.95 1.000000 4n +241.55 518.70 moveto +241.55 538.95 lineto stroke +276.52 520.95 1.000000 2n +280.41 521.70 moveto +280.41 541.95 lineto stroke +restore +% S_BAR +43 linenum +0.70 setlinewidth +329.72 541.95 moveto +329.72 517.95 lineto stroke +% S_SSV +44 linenum +% S_CHHEAD +% S_STAFF +% staff 1 +save +342.15 526.95 1.000000 4n +345.83 527.70 moveto +345.83 547.95 lineto stroke +379.96 523.95 1.000000 2n +383.85 524.70 moveto +383.85 544.95 lineto stroke +435.27 520.95 1.000000 4n +438.95 521.70 moveto +438.95 541.95 lineto stroke +restore +% S_BAR +48 linenum +0.70 setlinewidth +467.65 541.95 moveto +467.65 517.95 lineto stroke +% S_FEED +576.00 535.95 468.00 5 1.000000 1.000000 stf +% S_CLEFSIG +155.79 457.95 1.000000 gclef +169.33 463.95 1.000000 flat +% S_CHHEAD +% S_STAFF +% staff 1 +save +197.93 451.95 1.000000 2n +201.83 452.70 moveto +201.83 472.95 lineto stroke +255.50 445.95 1.000000 4n +249.27 445.95 moveto +261.73 445.95 lineto stroke +259.18 446.70 moveto +259.18 466.95 lineto stroke +291.91 448.95 1.000000 4n +295.59 449.70 moveto +295.59 469.95 lineto stroke +restore +% S_BAR +50 linenum +0.70 setlinewidth +325.89 475.95 moveto +325.89 451.95 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +343.21 457.95 1.000000 2n +347.11 458.70 moveto +347.11 478.95 lineto stroke +406.02 454.95 1.000000 2n +409.91 455.70 moveto +409.91 475.95 lineto stroke +restore +% S_BAR +51 linenum +0.70 setlinewidth +462.50 475.95 moveto +462.50 451.95 lineto stroke +3.00 setlinewidth +466.50 475.95 moveto +466.50 451.95 lineto stroke +0.70 setlinewidth +% Printing header/footer +/Times-Roman findfont +18 scalefont +setfont +240.44 741.42 moveto +(Title for first song) show +showpage +restore +%%DocumentFonts: /Times-Roman /NewCenturySchlbk-Bold +%%Pages: 2 +%%EndDocument +end PEND 69.336 443 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.14 Cadenzas)72.836 443 R 69.336 461 +EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .59(Cadenzas or cadenza-lik)72.426 461 R +3.09(ep)-.1 G .591(assages are often written with an arbitrary number o\ +f notes per measure.)-3.09 F(One)5.591 E -.1(wa)69.336 473 S 2.5(yt).1 G +2.5(oa)-2.5 G(ccomplish this is to use a tuplet with the appropriate nu\ +mber of notes.)-2.5 E/F1 10/Courier@0 SF(score)105.336 491 Q(time = 3/4) +130.336 503 Q(music)105.336 527 Q +(1: { [cue]... 16g- bm;b-;c;d;e;f;g;a;b;a;g;f;e;d;c;b-;g- ebm;} 17n,2.;) +105.336 551 Q(bar)105.336 563 Q 127.836 572.6 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 68 rlineto 320 0 rlineto 0 68 neg rlineto closepath stroke grestore +EEND 160 695 320 320 -68 68 126.836 640.6 PBEGIN +%%BeginDocument: mugex97.ps +%%BoundingBox: 160 695 480 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_FEED +612.29 803.00 468.00 5 1.000000 1.000000 stf +% S_CLEFSIG +192.08 725.00 1.000000 gclef +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +203.87 731.00 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +203.87 718.98 moveto +(4) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +228.64 704.00 0.583333 4n +0.70 setlinewidth +224.09 707.00 moveto +233.20 707.00 lineto stroke +224.09 713.00 moveto +233.20 713.00 lineto stroke +230.65 704.49 moveto +230.65 742.02 lineto stroke +242.57 710.00 0.583333 4n +238.02 713.00 moveto +247.12 713.00 lineto stroke +244.57 710.49 moveto +244.57 742.02 lineto stroke +256.49 713.00 0.583333 4n +251.94 713.00 moveto +261.04 713.00 lineto stroke +258.49 713.49 moveto +258.49 742.02 lineto stroke +270.42 716.00 0.583333 4n +272.42 716.49 moveto +272.42 742.03 lineto stroke +284.34 719.00 0.583333 4n +286.34 719.49 moveto +286.34 742.02 lineto stroke +298.26 722.00 0.583333 4n +300.27 722.49 moveto +300.27 742.02 lineto stroke +312.19 725.00 0.583333 4n +314.19 725.49 moveto +314.19 742.03 lineto stroke +326.11 728.00 0.583333 4n +328.11 728.49 moveto +328.11 742.02 lineto stroke +340.04 731.00 0.583333 4n +342.04 731.49 moveto +342.04 742.02 lineto stroke +353.96 728.00 0.583333 4n +355.96 728.49 moveto +355.96 742.02 lineto stroke +367.88 725.00 0.583333 4n +369.89 725.49 moveto +369.89 742.03 lineto stroke +381.81 722.00 0.583333 4n +383.81 722.49 moveto +383.81 742.02 lineto stroke +395.73 719.00 0.583333 4n +397.73 719.49 moveto +397.73 742.02 lineto stroke +409.66 716.00 0.583333 4n +411.66 716.49 moveto +411.66 742.03 lineto stroke +423.58 713.00 0.583333 4n +419.03 713.00 moveto +428.13 713.00 lineto stroke +425.58 713.49 moveto +425.58 742.02 lineto stroke +437.51 710.00 0.583333 4n +432.95 713.00 moveto +442.06 713.00 lineto stroke +439.51 710.49 moveto +439.51 742.02 lineto stroke +451.99 704.00 0.583333 4n +447.44 707.00 moveto +456.54 707.00 lineto stroke +447.44 713.00 moveto +456.54 713.00 lineto stroke +453.99 704.49 moveto +453.99 742.02 lineto stroke +newpath +230.42 743.00 moveto +454.22 743.00 lineto +454.22 741.05 lineto +230.42 741.05 lineto +closepath +fill +newpath +230.42 739.00 moveto +454.22 739.00 lineto +454.22 737.05 lineto +230.42 737.05 lineto +closepath +fill +restore +% S_BAR +10 linenum +0.70 setlinewidth +467.65 743.00 moveto +467.65 719.00 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /NewCenturySchlbk-Bold +%%Pages: 2 +%%EndDocument +end PEND 69.336 660.6 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.15 T)72.836 660.6 R(ransposition) +-1.036 E 69.336 678.6 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .933(The transpose and addtranspose paramet\ +ers can be used to transpose the pitches for a staf)72.77 678.6 R 3.433 +(fo)-.25 G 3.433(rt)-3.433 G .933(he whole)-3.433 F 2.5(score. The) +69.336 690.6 R(follo)2.5 E(wing table sho)-.25 E +(ws what transposition v)-.25 E(alues to use for dif)-.25 E +(ferent interv)-.25 E(als.)-.25 E EP +%%Page: 144 150 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(44 -)-2.5 E .4 LW 398.736 +88.5 171.936 88.5 DL/F1 10/Times-Bold@0 SF 12.5 +(halfsteps tranposition alter)176.936 98 R(nate transposition)-.15 E +398.736 102.5 171.936 102.5 DL F0 47.78(0p)176.936 112 S(erfect 1)-47.78 +E(diminished 2)31.97 E 47.78(1a)176.936 124 S(ugmented 1)-47.78 E +(minor 2)15.85 E 47.78(2m)176.936 136 S(ajor 2)-47.78 E(diminished 3) +36.4 E 47.78(3a)176.936 148 S(ugmented 2)-47.78 E(minor 3)15.85 E 47.78 +(4m)176.936 160 S(ajor 3)-47.78 E(diminished 4)36.4 E 47.78(5a)176.936 +172 S(ugmented 3)-47.78 E(perfect 4)15.85 E 47.78(6a)176.936 184 S +(ugmented 4)-47.78 E(diminished 5)15.85 E 47.78(7p)176.936 196 S +(erfect 5)-47.78 E(diminished 6)31.97 E 47.78(8a)176.936 208 S +(ugmented 5)-47.78 E(minor 6)15.85 E 47.78(9m)176.936 220 S(ajor 6) +-47.78 E(diminished 7)36.4 E 40.28(10 augmented)176.936 232 R 15.85(6m) +2.5 G(inor 7)-15.85 E 40.28(11 major)176.936 244 R 36.4(7d)2.5 G +(iminished 8)-36.4 E 398.736 248.5 171.936 248.5 DL 289.446 88.5 289.446 +248.5 DL 222.216 88.5 222.216 248.5 DL 398.736 88.5 398.736 248.5 DL +171.936 88.5 171.936 248.5 DL 1.21(This table continues in a similar w) +69.336 262 R 1.21(ay for interv)-.1 F 1.21(als be)-.25 F 1.21 +(yond an octa)-.15 F -.15(ve)-.2 G 6.21(.F).15 G 1.21 +(or each number of halfsteps you)-6.36 F -.1(wa)69.336 274 S .457 +(nt to transpose, there is more than one w).1 F .456 +(ay the transpose and addtranspose parameters can be speci\214ed,)-.1 F +.579(as sho)69.336 286 R .579(wn by this table.)-.25 F .579(This allo) +5.579 F .579(ws to you control whether a sharp k)-.25 F .88 -.15(ey o) +-.1 H 3.08(ra\215).15 G .58(at k)-3.08 F .88 -.15(ey i)-.1 H 3.08(st).15 +G 3.08(ob)-3.08 G 3.08(eu)-3.08 G .58(sed in cases)-3.08 F .686 +(where there is a choice.)69.336 298 R -.15(Fo)5.686 G 3.185(re).15 G +.685(xample, if the k)-3.335 F .985 -.15(ey s)-.1 H .685 +(ignature has three sharps, and you w).15 F .685(ant to transpose up)-.1 +F(tw)69.336 310 Q 2.5(oh)-.1 G(alfsteps, you could say either)-2.5 E/F2 +10/Courier@0 SF(transpose = up maj 2)130.336 328 Q F0(or)69.336 348 Q F2 +(transpose = up dim 3)130.336 366 Q F0 .709 +(The \214rst will result in a k)69.336 386 R 1.009 -.15(ey o)-.1 H 3.209 +<668c>.15 G 1.009 -.15(ve s)-3.209 H .71 +(harps, and the second will result in se).15 F -.15(ve)-.25 G 3.21<6e8d> +.15 G 3.21(ats. These)-3.21 F .71(are equi)3.21 F -.25(va)-.25 G(lent) +.25 E -.1(ke)69.336 398 S .754(ys; in major for e)-.05 F .754 +(xample, the)-.15 F 3.254(ya)-.15 G .754 +(re B and C \215at, which are the same note.)-3.254 F .753 +(It is up to you to choose the)5.753 F -.1(wa)69.336 410 S 3.256(yy).1 G +.756(ou w)-3.256 F .756(ould lik)-.1 F 3.256(ei)-.1 G 3.256(tt)-3.256 G +3.256(ob)-3.256 G 3.256(ep)-3.256 G 3.256(rinted. But)-3.256 F .756 +(no k)3.256 F 1.056 -.15(ey i)-.1 H 3.256(sa).15 G(llo)-3.256 E .756 +(wed to ha)-.25 F 1.057 -.15(ve m)-.2 H .757(ore than se).15 F -.15(ve) +-.25 G 3.257(ns).15 G .757(harps or \215ats, so in)-3.257 F .13 +(most cases only one of the w)69.336 422 R .13(ays will result in a v) +-.1 F .13(alid k)-.25 F -.15(ey)-.1 G 2.63(,a)-.5 G .13(nd the other w) +-2.63 F .13(ay will result in an error message.)-.1 F 1.02 +(The transpose and addtranspose parameters are allo)69.336 440 R 1.021 +(wed in score and staf)-.25 F 3.521(fc)-.25 G(onte)-3.521 E 1.021 +(xts, so the)-.15 F 3.521(yc)-.15 G 1.021(an be set to)-3.521 F(dif) +69.336 452 Q .99(ferent v)-.25 F .99(alues on dif)-.25 F .99 +(ferent staf)-.25 F .99(fs, and on the score as a whole.)-.25 F .99 +(This is useful for printing scores where)5.99 F 2.375 +(some of the instruments are transposing instruments \(lik)69.336 464 R +4.875(eB)-.1 G 2.375(-\215at clarinet\).)-4.875 F -1.1(Yo)7.375 G 4.875 +(uc)1.1 G 2.375(an set the transpose)-4.875 F .802 +(parameter on speci\214c staf)69.336 476 R .802(fs to appropriate v)-.25 +F .801(alues for the transposing instruments. Then if you decide you) +-.25 F -.1(wa)69.336 488 S .579(nt to mo).1 F .879 -.15(ve t)-.15 H .579 +(he entire score to a ne).15 F 3.079(wk)-.25 G -.15(ey)-3.179 G 3.079 +(,y)-.5 G .58(ou can set the addtranspose parameter in score conte) +-3.079 F 3.08(xt. Y)-.15 F(ou)-1.1 E 2.316 +(can enter all the music at true pitch, b)69.336 500 R 2.315 +(ut print the score and/or the indi)-.2 F 2.315 +(vidual parts with the correct)-.25 F(transposition.)69.336 512 Q 1.964 +(Another use for setting dif)69.336 530 R 1.964(ferent transposition v) +-.25 F 1.964(alues is the follo)-.25 F 1.964 +(wing trick, useful in guitar music for)-.25 F .665 +(printing both the real chords and chords for capo.)69.336 542 R(Say) +5.665 E 3.165(,f)-.65 G .665(or e)-3.165 F .665(xample, you ha)-.15 F +.965 -.15(ve a s)-.2 H .664(ong that is in B \215at, b).15 F(ut)-.2 E +.232(the guitar is to use a capo on the third fret, and play in the k) +69.336 554 R .532 -.15(ey o)-.1 H 2.732(fG).15 G 5.232(.Y)-2.732 G .232 +(ou could de\214ne the follo)-6.332 F .232(wing macro)-.25 F +(to print both v)69.336 566 Q(ersions of a chord, the capo v)-.15 E +(ersion abo)-.15 E .3 -.15(ve t)-.15 H(he real v).15 E(ersion:)-.15 E F2 +(define CHORD\(COUNT, NAME\))105.336 584 Q +(bold chord all: COUNT \222NAME\222;)130.336 608 Q(// chord for capo)30 +E(ital\(8\) chord 1: COUNT \222NAME\222;)130.336 620 Q(// real chord)24 +E(@)105.336 632 Q F0(Then, set these transpositions:)69.336 652 Q F2 12 +(score transpose)105.336 670 R 6(=d)6 G(own minor 3)-6 E +(// transpose score for capo)8 E(staff 1 transpose = up perfect 1) +105.336 682 Q(// override score transposition)8 E F0 +(and similarly for an)69.336 702 Q 2.5(yo)-.15 G(ther staf)-2.5 E 2.5 +(fs. Then,)-.25 F(where)2.5 E -.15(ve)-.25 G 2.5(ry).15 G(ou w)-2.5 E +(ant to print a chord, say \(for e)-.1 E(xample\))-.15 E F2 +(CHORD\(3,Dm\))105.336 720 Q EP +%%Page: 145 151 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(45 -)-2.5 E .271 +(This will print both v)69.336 96 R .271(ersions of the chord abo)-.15 F +.571 -.15(ve c)-.15 H .271(ount 3 of the measure.).15 F -.15(Fo)5.271 G +2.771(rt).15 G .271(he top chord it will transpose)-2.771 F +(this to Bm, the capo chord.)69.336 108 Q -.15(Fo)5 G 2.5(rt).15 G +(he bottom chord it will lea)-2.5 E .3 -.15(ve i)-.2 H 2.5(ta).15 G 2.5 +(sD)-2.5 G(m, the real chord.)-2.5 E 69.336 126 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.16 Placing)72.836 126 R -.14(ve)3.5 G +(rses belo).14 E 3.5(wt)-.14 G(he scor)-3.5 E(es)-.252 E 69.336 144 +EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .362 +(Sometimes, particularly with songs that ha)72.198 144 R .662 -.15 +(ve a l)-.2 H .362(ot of v).15 F .362(erses, you may w)-.15 F .362 +(ant to put some v)-.1 F .362(erses of lyrics as)-.15 F 2.458 +(blocks of te)69.336 156 R 2.457(xt belo)-.15 F 4.957(wt)-.25 G 2.457 +(he music. Probably the easiest w)-4.957 F 2.457 +(ay to do this is using "print" or "paragraph")-.1 F +(statements inside a "block.")69.336 168 Q/F1 10/Courier@0 SF(block) +105.336 186 Q(print \(_win.w + 30, _win.n - 15\) "2.)105.336 198 Q(")18 +E(print "\\)105.336 210 Q(Here is the first line)105.336 222 Q +(and the second line)105.336 234 Q(and the third line.)105.336 246 Q(") +105.336 258 Q(print \(_win.w + 90, _win.n - 15\) "3.)105.336 270 Q(")18 +E(print "\\)105.336 282 Q(Here is another verse's first line)105.336 294 +Q(and its second line)105.336 306 Q(and its third line.)105.336 318 Q(") +105.336 330 Q F0 -1.1(Yo)69.336 356 S 2.98(um)1.1 G .48(ay need to use \ +a little trial-and-error to determine the coordinates to use on the pri\ +nt statements, b)-2.98 F(ut)-.2 E .044(you only ha)69.336 368 R .344 +-.15(ve t)-.2 H 2.544(od).15 G .044(etermine one coordinate per v)-2.544 +F .043 +(erse, and with a bit of practice it gets easier to \214nd the right) +-.15 F -.25(va)69.336 380 S 2.561(lues. Since).25 F .061(the "print" st\ +atement is being used, the font and size will be determined by the size\ + parameter)2.561 F(and font parameter)69.336 392 Q 2.5(,r)-.4 G +(ather than by lyricssize and lyricsfont.)-2.5 E .216(If you also w) +69.336 410 R .215(ant chords symbols with these v)-.1 F .215 +(erses, you can do that too. It is easiest if you use Courier font,)-.15 +F .05(as sho)69.336 422 R .05(wn in the e)-.25 F .05(xample belo)-.15 F +1.35 -.65(w, s)-.25 H .05(ince its constant-width characters mak).65 F +2.551(ei)-.1 G 2.551(te)-2.551 G .051(asy to line things up. If you use) +-2.551 F 2.5(ap)69.336 434 S(roportional-width font, you will ha)-2.5 E +.3 -.15(ve t)-.2 H 2.5(od).15 G(etermine ho)-2.5 E 2.5(wt)-.25 G 2.5(op) +-2.5 G(lace the chords by trial and error)-2.5 E(.)-.55 E F1 +(print \(_win.w + 50, _win.n - 35\) "3.)105.336 452 Q(")18 E +(print "\\f\(CR\)\\)105.336 464 Q 72(CD)105.336 476 S 24(7G)-72 G(7)-24 +E(This is the first line)105.336 488 Q 42(CF)105.336 500 S +(of the next verse)105.336 512 Q(B\\\(smflat\))105.336 524 Q +(of the song.)105.336 536 Q(")105.336 548 Q 69.336 574 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.17 A)72.836 574 R(utomatic piano r)-.7 +E(eduction)-.252 E 69.336 592 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .926(Perhaps you')72.762 592 R 3.426(dl)-.5 +G(ik)-3.426 E 3.426(ea4)-.1 G .926(-part v)-3.426 F .926 +(ocal piece written on 4 separate staf)-.2 F .926 +(fs, as well as a piano reduction on tw)-.25 F(o)-.1 E(staf)69.336 604 Q +(fs with 2 v)-.25 E 2.5(oices. This)-.2 F(could be done using:)2.5 E EP +%%Page: 146 152 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(46 -)-2.5 E/F1 10/Courier@0 +SF(score)105.336 96 Q(staffs=6)123.336 108 Q(bracket=1-4)123.336 120 Q +(brace=5-6)123.336 132 Q(staff 3)105.336 144 Q(clef=treble8)123.336 156 +Q(staff 4)105.336 168 Q(clef=bass)123.336 180 Q(staff 5)105.336 192 Q +(vscheme=2o)123.336 204 Q 12(staffscale=0.75 //)123.336 216 R +(make piano staffs a little smaller)6 E(staff 6)105.336 228 Q(clef=bass) +123.336 240 Q(vscheme=2o)123.336 252 Q(staffscale=0.75)123.336 264 Q +(// Define macros to put each voice on its own staff)105.336 288 Q +(// plus the appropriate staff/voice of the piano staffs.)105.336 300 Q +(define S 1 1 & 5 1: @)105.336 312 Q(// soprano)12 E +(define A 2 1 & 5 2: @)105.336 324 Q(// alto)12 E(define T 3 1 & 6 1: @) +105.336 336 Q(// tenor)12 E(define B 4 1 & 6 2: @)105.336 348 Q(// bass) +18 E(music)105.336 372 Q 6(S2)105.336 384 S(c+;;)-6 E 6(A2)105.336 396 S +(f;e;)-6 E 6(T2)105.336 408 S(a;g;)-6 E 6(B2)105.336 420 S(c;;)-6 E(bar) +105.336 432 Q EP +%%Page: 147 153 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(47 -)-2.5 E 127.836 96 +EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 322 rlineto 320 0 rlineto 0 322 neg rlineto closepath stroke grestore +EEND 160 441 320 320 -322 322 126.836 418 PBEGIN +%%BeginDocument: mugex98.ps +%%BoundingBox: 160 441 480 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_SSV +8 linenum +% S_SSV +10 linenum +% S_SSV +12 linenum +% S_SSV +15 linenum +% S_FEED +622.29 803.00 468.00 5 1.000000 1.000000 stf +622.29 749.00 468.00 5 1.000000 1.000000 stf +622.29 695.00 468.00 5 1.000000 1.000000 stf +622.29 641.00 468.00 5 1.000000 1.000000 stf +622.29 590.00 468.00 5 1.000000 0.750000 stf +622.29 539.00 468.00 5 1.000000 0.750000 stf +188.29 746.00 554.00 bracket +189.79 527.00 458.00 brace +0.52 setlinewidth +190.29 743.00 moveto +190.29 458.00 lineto stroke +% S_CLEFSIG +202.08 725.00 1.000000 gclef +202.08 671.00 1.000000 gclef +202.08 595.26 moveto +/Times-Italic findfont +9 scalefont +setfont +(8) show +202.08 617.00 1.000000 gclef +202.33 575.00 1.000000 fclef +199.13 513.50 0.750000 gclef +199.32 471.50 0.750000 fclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +243.02 734.00 1.000000 2n +0.70 setlinewidth +239.13 733.25 moveto +239.13 713.00 lineto stroke +360.79 734.00 1.000000 2n +356.89 733.25 moveto +356.89 713.00 lineto stroke +restore +% S_STAFF +% staff 2 +save +243.02 668.00 1.000000 2n +0.70 setlinewidth +246.92 668.75 moveto +246.92 689.00 lineto stroke +360.79 665.00 1.000000 2n +364.68 665.75 moveto +364.68 686.00 lineto stroke +restore +% S_STAFF +% staff 3 +save +243.02 620.00 1.000000 2n +0.70 setlinewidth +246.92 620.75 moveto +246.92 641.00 lineto stroke +360.79 617.00 1.000000 2n +364.68 617.75 moveto +364.68 638.00 lineto stroke +restore +% S_STAFF +% staff 4 +save +243.02 566.00 1.000000 2n +0.70 setlinewidth +246.92 566.75 moveto +246.92 587.00 lineto stroke +360.79 566.00 1.000000 2n +364.68 566.75 moveto +364.68 587.00 lineto stroke +restore +% S_STAFF +% staff 5 +save +243.02 520.25 0.750000 2n +0.52 setlinewidth +245.95 520.81 moveto +245.95 536.00 lineto stroke +360.79 520.25 0.750000 2n +363.71 520.81 moveto +363.71 536.00 lineto stroke +243.02 511.25 0.750000 2n +240.10 510.69 moveto +240.10 495.50 lineto stroke +360.79 509.00 0.750000 2n +357.86 508.44 moveto +357.86 493.25 lineto stroke +restore +% S_STAFF +% staff 6 +save +243.02 476.00 0.750000 2n +0.52 setlinewidth +245.95 476.56 moveto +245.95 491.75 lineto stroke +360.79 473.75 0.750000 2n +363.71 474.31 moveto +363.71 489.50 lineto stroke +243.02 464.75 0.750000 2n +240.10 464.19 moveto +240.10 449.00 lineto stroke +360.79 464.75 0.750000 2n +357.86 464.19 moveto +357.86 449.00 lineto stroke +restore +% S_BAR +32 linenum +0.70 setlinewidth +467.65 743.00 moveto +467.65 719.00 lineto stroke +467.65 689.00 moveto +467.65 665.00 lineto stroke +467.65 635.00 moveto +467.65 611.00 lineto stroke +467.65 581.00 moveto +467.65 557.00 lineto stroke +467.65 527.00 moveto +467.65 509.00 lineto stroke +467.65 476.00 moveto +467.65 458.00 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Italic +%%Pages: 2 +%%EndDocument +end PEND/F0 10/Times-Roman@0 SF +(This can also be done using chord-at-a-time input style:)69.336 438 Q +/F1 10/Courier@0 SF +(// Define a macro to put each voice on its own staff)105.336 456 Q +(// plus the appropriate staff/voice of the piano staffs.)105.336 468 Q +(// This example assumes inputting notes from bottom to top.)105.336 480 +Q(define M [ 4 1 & 6 2; \\)105.336 492 Q 6(31&61)171.336 504 S 6(;\\)-6 +G 6(21&52)171.336 516 S 6(;\\)-6 G 6(11&51]: @)171.336 528 S(music) +105.336 552 Q 6(M2)105.336 576 S(cafc+;cgec+;)-6 E(bar)105.336 588 Q +69.336 614 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.18 Diagonal)72.836 614 R(slash marks) +3.5 E 69.336 632 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .346(Sometimes, instead of a note or notes,\ + a diagonal slash mark is printed on a staf)72.182 632 R 2.846(f. This) +-.25 F .347(is used for v)2.847 F(arious)-.25 E .166(purposes, such as \ +strumming a chord \(in a guitar part\), or to mean that the pre)69.336 +644 R .166(vious beat should be repeated)-.25 F 2.096 +(or that a note should be impro)69.336 656 R 4.597(vised. Y)-.15 F 2.097 +(ou can get slash marks for all notes by setting the noteheads)-1.1 F +(parameter)69.336 668 Q(.)-.55 E/F1 10/Courier@0 SF +(noteheads = "allslash")105.336 686 Q F0(or if you w)69.336 706 Q +(ant to use hollo)-.1 E 2.5(ws)-.25 G(lashes for half notes and longer) +-2.5 E F1(noteheads = "slash")105.336 724 Q EP +%%Page: 148 154 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(48 -)-2.5 E(Usually such sl\ +ash marks do not include a stem, so you may wish to also set)69.336 96 Q +/F1 10/Courier@0 SF(stemlen=0)105.336 114 Q F0(If you just w)69.336 140 +Q(ant speci\214c chords to be slashes, you can use the chord head shape\ + o)-.1 E -.15(ve)-.15 G(rride:).15 E F1 +(1: b;[ hs "allslash"; len 0 ]... ;;;)105.336 158 Q(bar)105.336 170 Q +127.836 179.6 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 320 0 rlineto 0 61 neg rlineto closepath stroke grestore +EEND 160 702 320 320 -61 61 126.836 240.6 PBEGIN +%%BeginDocument: mugex99.ps +%%BoundingBox: 160 702 480 763 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +1 linenum +% S_FEED +612.29 803.00 468.00 5 1.000000 1.000000 stf +% S_CLEFSIG +192.08 725.00 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +226.10 731.00 1.000000 4n +0.70 setlinewidth +222.42 730.25 moveto +222.42 710.00 lineto stroke +287.28 731.00 1.000000 fillslashhead +348.84 731.00 1.000000 fillslashhead +411.63 731.00 1.000000 fillslashhead +restore +% S_BAR +6 linenum +0.70 setlinewidth +467.65 743.00 moveto +467.65 719.00 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: +%%Pages: 2 +%%EndDocument +end PEND 69.336 260.6 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.19 Br)72.836 260.6 R(eath marks)-.252 +E 69.336 278.6 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF 2.924(Ac)72.26 278.6 S .424(omma in a lar) +-2.924 F .424(ge font can be used as a breath mark.)-.18 F .423 +(Something in the range of 20 to 30 points usually)5.423 F +(looks good; you can adjust to your preference.)69.336 290.6 Q/F1 10 +/Courier@0 SF(1: c;d;2e;)105.336 308.6 Q +(rom \(24\) above all dist 0: 4.5 ",";)105.336 320.6 Q(bar)105.336 332.6 +Q(1: e;d;2c;)105.336 356.6 Q(bar)105.336 368.6 Q 91.836 378.2 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 61 rlineto 392 0 rlineto 0 61 neg rlineto closepath stroke grestore +EEND 128 692 392 392 -61 61 90.836 439.2 PBEGIN +%%BeginDocument: mugex100.ps +%%BoundingBox: 128 692 520 753 +save +1039846316 1039845534 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_FEED +576.29 792.97 504.00 5 1.000000 1.000000 stf +% S_CLEFSIG +156.08 714.97 1.000000 gclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +187.05 702.97 1.000000 4n +0.70 setlinewidth +180.82 702.97 moveto +193.28 702.97 lineto stroke +190.73 703.72 moveto +190.73 723.97 lineto stroke +227.94 705.97 1.000000 4n +231.62 706.72 moveto +231.62 726.97 lineto stroke +274.76 708.97 1.000000 2n +278.65 709.72 moveto +278.65 729.97 lineto stroke +/Times-Roman findfont +24 scalefont +setfont +319.55 740.45 moveto +(, ) show +restore +% S_BAR +9 linenum +0.70 setlinewidth +338.51 732.97 moveto +338.51 708.97 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +352.19 708.97 1.000000 4n +355.87 709.72 moveto +355.87 729.97 lineto stroke +393.08 705.97 1.000000 4n +396.76 706.72 moveto +396.76 726.97 lineto stroke +439.90 702.97 1.000000 2n +433.45 702.97 moveto +446.34 702.97 lineto stroke +443.79 703.72 moveto +443.79 723.97 lineto stroke +restore +% S_BAR +12 linenum +0.70 setlinewidth +503.65 732.97 moveto +503.65 708.97 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Roman +%%Pages: 2 +%%EndDocument +end PEND 69.336 459.2 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.20 Or)72.836 459.2 R +(gan pedal heel and toe marks)-.14 E 69.336 477.2 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .278 +(Mup does not include characters specially for the standard or)72.114 +477.2 R -.05(ga)-.18 G 2.778(np).05 G .279 +(edal heel and toe indications, b)-2.778 F .279(ut a U in)-.2 F(helv) +69.336 489.2 Q .741 +(etica font and the acc_hat music symbol can be used. Y)-.15 F .74 +(ou may w)-1.1 F .74(ant to mak)-.1 F 3.24(et)-.1 G .74 +(hem a bit smaller than)-3.24 F(the def)69.336 501.2 Q +(ault size, so de\214ning macros for them may be useful.)-.1 E/F1 10 +/Courier@0 SF(score)105.336 519.2 Q(clef = bass)130.336 531.2 Q +(// define strings for the organ pedal heel and toe marks)105.336 555.2 +Q(define HEEL "\\s\(-3\)\\f\(HB\)U" @)105.336 567.2 Q +(define TOE "\\s\(-1\)\\\(acc_hat\)" @)105.336 579.2 Q(music)105.336 +603.2 Q(1: a-;b-;e;f;)105.336 627.2 Q(rom below 1: 1 HEEL; 2 TOE;) +105.336 639.2 Q(rom above 1: 3 TOE; 4 HEEL;)105.336 651.2 Q(bar)105.336 +663.2 Q 127.836 672.8 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 71 rlineto 320 0 rlineto 0 71 neg rlineto closepath stroke grestore +EEND 160 691 320 320 -71 71 126.836 743.8 PBEGIN +%%BeginDocument: mugex101.ps +%%BoundingBox: 160 691 480 762 +save +1930114009 1930113259 sv +1.000000 1.000000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +2 linenum +% S_FEED +396.29 1157.33 468.00 5 1.000000 1.000000 stf +% S_CLEFSIG +192.33 731.33 1.000000 fclef +% S_CHHEAD +% S_STAFF +% staff 1 +save +226.97 716.33 1.000000 4n +0.70 setlinewidth +230.65 717.08 moveto +230.65 737.33 lineto stroke +288.41 719.33 1.000000 4n +292.09 720.08 moveto +292.09 740.33 lineto stroke +349.84 728.33 1.000000 4n +346.16 727.58 moveto +346.16 707.33 lineto stroke +412.12 731.33 1.000000 4n +408.43 730.58 moveto +408.43 710.33 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +408.88 745.76 moveto +/Helvetica-Bold findfont +9 scalefont +setfont +(U ) show +/Times-Roman findfont +12 scalefont +setfont +345.52 746.30 moveto +349.84 746.22 0.916667 acc_hat +354.16 746.30 moveto +/Times-Roman findfont +11 scalefont +setfont +( ) show +/Times-Roman findfont +12 scalefont +setfont +223.73 700.04 moveto +/Helvetica-Bold findfont +9 scalefont +setfont +(U ) show +/Times-Roman findfont +12 scalefont +setfont +284.08 697.63 moveto +288.41 697.55 0.916667 acc_hat +292.73 697.63 moveto +/Times-Roman findfont +11 scalefont +setfont +( ) show +restore +% S_BAR +15 linenum +0.70 setlinewidth +467.65 737.33 moveto +467.65 713.33 lineto stroke +% Printing header/footer +showpage +restore +%%DocumentFonts: /Times-Roman /Helvetica-Bold +%%Pages: 2 +%%EndDocument +end PEND EP +%%Page: 149 155 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(49 -)-2.5 E 69.336 104 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.21 Generating)72.836 104 R +(blank staff paper)3.5 E 69.336 122 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .835 +(It is possible to use Mup to generate blank music staf)72.671 122 R +3.336(fp)-.25 G(aper)-3.336 E 5.836(.Y)-.55 G .836 +(ou simply use an input \214le that contains)-6.936 F 1.098 +(measure spaces, each ending with an in)69.336 134 R(visbar)-.4 E 6.097 +(.Y)-.55 G 1.097(ou can control whether you w)-7.197 F 1.097 +(ant clefs, time signatures,)-.1 F .423 +(braces, etc., and can control the spacing of staf)69.336 146 R .423 +(fs using the scoresep parameter)-.25 F 5.424(.H)-.55 G .424 +(ere is a simple input that)-5.424 F +(will generate a page with 8 completely blank staf)69.336 158 Q(fs.)-.25 +E/F1 10/Courier@0 SF(score)105.336 176 Q 35(scoresep=9,100 //)130.336 +188 R(spread staffs out nicely)6 E 41(stafflines=5n //)130.336 200 R +(don't print any clefs)6 E 21(label="" //)130.336 212 R +(make sure left edges line up both on first)6 E 40(label2="" //)130.336 +224 R(and on subsequent lines)24 E 28(topmargin=1 //)130.336 236 R +(allow extra margin to write in header/footer)6 E(bottommargin=1)130.336 +248 Q 40(time=4/4n //)130.336 260 R(don't print any time signature)6 E +(music)105.336 272 Q(define SCORE)105.336 296 Q(1: ms;)130.336 308 Q 21 +(invisbar //)130.336 320 R(no bar line at the end of the staff)6 E(@) +105.336 332 Q(define SCORE_NEWSCORE)105.336 356 Q(SCORE)130.336 368 Q +(newscore)130.336 380 Q(@)105.336 392 Q +(// print 8 staffs, with newscore between each)105.336 416 Q +(SCORE_NEWSCORE)105.336 428 Q(SCORE_NEWSCORE)105.336 440 Q +(SCORE_NEWSCORE)105.336 452 Q(SCORE_NEWSCORE)105.336 464 Q +(SCORE_NEWSCORE)105.336 476 Q(SCORE_NEWSCORE)105.336 488 Q +(SCORE_NEWSCORE)105.336 500 Q(SCORE)105.336 512 Q 69.336 538 EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 14/Times-Bold@0 SF 3.5(13.22 Con)72.836 538 R -.14(ve)-.56 G +(rting Mup \214les to other f).14 E(ormats)-.35 E 69.336 556 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF 1.132 +(Since Mup generates PostScript, almost an)72.968 556 R 3.632(yP)-.15 G +1.132(ostScript tool can be used on its output. In particular)-3.632 F +3.631(,t)-.4 G(he)-3.631 E .668 +("ps2pdf" tool that comes with Ghostscript can con)69.336 568 R -.15(ve) +-.4 G .668(rt Mup output to PDF format, and the "ps2epsi" tool,).15 F +1.572(which also comes with Ghostscript, con)69.336 580 R -.15(ve)-.4 G +1.572 +(rts a PostScript \214le to an Encapsulated PostScript \(EPS\) \214le.) +.15 F(Man)69.336 592 Q 3.23(yt)-.15 G -.15(ex)-3.23 G 3.23(tp).15 G .731 +(rocessing and graphics programs will let you import EPS \214les, so th\ +is can let you insert Mup)-3.23 F(output into some other document.) +69.336 604 Q .388(There is a package called "psutils" a)69.336 622 R +-.25(va)-.2 G .388(ilable on most Linux archi).25 F -.15(ve)-.25 G .388 +(s, that contains v).15 F .388(arious Postscript tools.)-.25 F .351(The\ +se include "psnup" which lets you print multiple pages on one sheet of \ +paper with more \215e)69.336 634 R .352(xibility than)-.15 F(Mup')69.336 +646 Q 2.5(sp)-.55 G(anelsperpage parameter)-2.5 E 2.5(,a)-.4 G +(nd "psselect" which prints a subset of pages.)-2.5 E -1.1(Yo)69.336 664 +S 2.509(uc)1.1 G .009 +(an check the user donated programs page on Arkkra')-2.509 F 2.509(sw) +-.55 G .009(eb site for other programs for processing Mup)-2.509 F +(input or output.)69.336 676 Q EP +%%Page: 150 156 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(50 -)-2.5 E 69.336 103 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 15/Times-Bold@0 SF 3.75(14. MIDI)73.086 103 R(OUTPUT)3.75 E +69.336 121 EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF 2.012 +(Mup will optionally produce MIDI output \(using the -m command line ar) +73.848 121 R 4.513(gument\). Mup)-.18 F 2.013(is \214rst and)4.513 F +.266(foremost a music publication program, so its MIDI capabilities ha) +69.336 133 R .566 -.15(ve a f)-.2 H .766 -.25(ew l).15 H 2.766 +(imitations. Ho).25 F(we)-.25 E -.15(ve)-.25 G 1.066 -.4(r, t).15 H .266 +(he MIDI).4 F .567(output is quite useful for "proofreading" \(or perha\ +ps we should say "proof-listening"\).)69.336 145 R .568 +(It is often easier to)5.568 F .182(spot a typo in Mup input by listeni\ +ng to it than to look at the output. Mup pro)69.336 157 R .181 +(vides enough MIDI control to)-.15 F .911 +(do virtually all of what MIDI supports, and will be adequate for man) +69.336 169 R 3.411(yp)-.15 G .911(eople. Others ho)-3.411 F(we)-.25 E +-.15(ve)-.25 G 1.712 -.4(r, m).15 H .912(ay \214nd).4 F(the)69.336 181 Q +2.5(yw)-.15 G(ant a separate MIDI editor for really serious MIDI w)-2.6 +E(ork.)-.1 E .535(The follo)69.336 199 R .535 +(wing section assumes a general kno)-.25 F .535 +(wledge of MIDI. If you are not f)-.25 F .534 +(amiliar with MIDI, there are)-.1 F(man)69.336 211 Q 2.5(yb)-.15 G +(ooks a)-2.5 E -.25(va)-.2 G +(ilable on the subject at most music stores or computer book stores.).25 +E .959(Each v)69.336 229 R .959(oice is put on a separate MIDI track. T\ +he \214rst track contains general information such as k)-.2 F 1.26 -.15 +(ey a)-.1 H(nd).15 E .276(time signature. The ne)69.336 241 R .276 +(xt track will be for staf)-.15 F 2.776(f1)-.25 G 2.776(,v)-2.776 G .276 +(oice 1. If staf)-2.976 F 2.776(f1h)-.25 G .275(as a second v)-2.776 F +.275(oice, that will be the ne)-.2 F(xt)-.15 E +(track, otherwise it will be v)69.336 253 Q(oice 1 of staf)-.2 E 2.5(f2) +-.25 G 2.5(,i)-2.5 G 2.5(fa)-2.5 G -.15(ny)-2.5 G 2.5(,a)-.5 G +(nd so forth, one track for each v)-2.5 E(oice, top to bottom.)-.2 E +.483(Output is in MIDI \214le format 1, with a def)69.336 271 R .483 +(ault of 120 quarter notes per minute, 192 ticks per quarter note.)-.1 F +.04(MIDI channel 1 is used by def)69.336 283 R .04(ault for all v)-.1 F +.04(oices. If you w)-.2 F .04(ant to use dif)-.1 F .04 +(ferent instrument sounds for dif)-.25 F(ferent)-.25 E -.2(vo)69.336 295 +S 1.006(ices, you will need to specify a dif).2 F 1.006 +(ferent channel for each v)-.25 F 1.006 +(oice, then specify the MIDI "program" for)-.2 F(that v)69.336 307 Q +(oice. This is demonstrated in some of the e)-.2 E +(xamples later in this section.)-.15 E 1.037 +(Mup MIDI output will handle repeats and \214rst and second endings, b) +69.336 325 R 1.037(ut it does not kno)-.2 F 3.537(wa)-.25 G -.15(ny) +-3.537 G 1.037(thing about).15 F .852("D.S. al coda" or an)69.336 337 R +.852(ything of that sort.)-.15 F .852(It is possible to w)5.852 F .852 +(ork around this limitation to some e)-.1 F .853(xtent using)-.15 F +2.702(macros. F)69.336 349 R .201(or e)-.15 F .201(xample, a section be\ +tween a "sign" and a "jump to coda" symbol could be put inside a macro) +-.15 F .294(de\214nition, then the macro can be called. Then later in t\ +he piece, where the "D. S." occurs the macro can be)69.336 361 R +(called ag)69.336 373 Q(ain if MIDI is de\214ned. F)-.05 E(or e)-.15 E +(xample:)-.15 E EP +%%Page: 151 157 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(51 -)-2.5 E/F1 10/Courier@0 +SF(// an introductory section, ends with a sign)105.336 96 Q +(1: c;d;e;f;)105.336 108 Q(mussym above all: 5 "sign";)105.336 120 Q +(bar)105.336 132 Q(// define macro for section between sign and)105.336 +156 Q(// symbol to "jump to coda")105.336 168 Q(define SECTION)105.336 +180 Q(1: g;a;g;;)105.336 192 Q(mussym above all: 5 "coda";)105.336 204 Q +(bar)105.336 216 Q(@)105.336 228 Q +(// print/play the section just defined by)105.336 252 Q(// the macro) +105.336 264 Q(SECTION)105.336 276 Q(// now do the music up to the D.S.) +105.336 300 Q(1: e;f;2g;)105.336 312 Q(ital above 1: 1 "D. S. al Coda";) +105.336 324 Q(dblbar)105.336 336 Q +(// human player would now flip back to)105.336 360 Q +(// the sign, so do the MIDI equivalent:)105.336 372 Q +(// play that section again.)105.336 384 Q(ifdef MIDI)105.336 396 Q +(SECTION)130.336 408 Q(endif)105.336 420 Q(// now do the coda)105.336 +444 Q(1: e;d;2c;)105.336 456 Q(rom above 1: 0 "Coda";)105.336 468 Q +(endbar)105.336 480 Q F0 1.123 +(Mup mainly just outputs the note information.)69.336 506 R 1.122 +(Mup will recognize octa)6.123 F 1.422 -.15(ve m)-.2 H 1.122 +(arks, and mo).15 F 1.422 -.15(ve n)-.15 H 1.122(otes up or).15 F(do) +69.336 518 Q .808(wn appropriately)-.25 F 5.808(.I)-.65 G 3.308(tr) +-5.808 G .808(ecognizes piano pedal marks.)-3.308 F .809 +(It does not attempt to interpret tempo or dynamics)5.809 F .561(marks \ +speci\214ed by "rom," "boldital," etc. or ornaments in "mussym" stateme\ +nt.)69.336 530 R .56(It does interpret rehearsal)5.56 F 1.133 +(marks as cue points.)69.336 542 R 1.134 +(It handles grace notes, rolls, slashes, and alternation groups.)6.133 F +-1.1(Yo)6.134 G 3.634(uc)1.1 G 1.134(an control ho)-3.634 F(w)-.25 E(le) +69.336 554 Q -.05(ga)-.15 G +(to the music is by using the Mup "release" parameter).05 E(.)-.55 E +.673(Some styles of music are often written in "swing time," meaning th\ +e players are e)69.336 572 R .672(xpected to play pairs of)-.15 F 1.458 +(notes with the \214rst twice as long as the second, e)69.336 584 R -.15 +(ve)-.25 G 3.958(nt).15 G 1.458(hough the)-3.958 F 3.958(ya)-.15 G 1.458 +(re written as if the)-3.958 F 3.958(yw)-.15 G 1.458(ere the same)-3.958 +F 1.028 +(duration, or as if the \214rst were three times as long as the second.) +69.336 596 R 1.028(The most common e)6.028 F 1.027(xample w)-.15 F 1.027 +(ould be)-.1 F .696(where the written notation sho)69.336 608 R .696 +(ws tw)-.25 F 3.196(oe)-.1 G .697(ighth notes lik)-3.196 F 3.197(e8)-.1 +G .697(;; or a dotted rh)-3.197 F .697(ythm lik)-.05 F 3.197(e8)-.1 G +.697(.;16; b)-3.197 F .697(ut the musician)-.2 F("kno)69.336 620 Q 1.363 +(ws" that the composer really intended it to be played as if it were a \ +triplet {4;8;}3; The swingunit)-.25 F +(parameter can be used to get Mup MIDI output to automatically follo) +69.336 632 Q 2.5(wt)-.25 G(hat performance con)-2.5 E -.15(ve)-.4 G +(ntion.).15 E 2.731(AM)69.336 650 S .231 +(IDI editing program will probably be necessary to add some ef)-2.731 F +2.731(fects. Ho)-.25 F(we)-.25 E -.15(ve)-.25 G 1.031 -.4(r, i).15 H +2.731(ti).4 G 2.732(sp)-2.731 G .232(ossible to specify)-2.732 F +(certain directi)69.336 662 Q -.15(ve)-.25 G 2.5(sf).15 G(or MIDI.)-2.5 +E(The)5 E 2.5(ya)-.15 G(re of the form:)-2.5 E/F2 10/Times-Bold@0 SF +(midi)105.336 680 Q/F3 10/Times-Italic@0 SF 2.5(SV)6 G F2(:)-2.5 E F3 +(be)6 E(gintime "k)-.4 E -.3(ey)-.1 G(wor).3 E(d=value";)-.37 E F0(The) +69.336 700 Q F3(S)2.617 E F0(and)2.617 E F3(V)2.617 E F0 .116 +(specify the staf)2.617 F 2.616(fa)-.25 G .116(nd v)-2.616 F .116 +(oice for which the directi)-.2 F .416 -.15(ve i)-.25 H 2.616(st).15 G +2.616(oa)-2.616 G(pply)-2.616 E 2.616(.A)-.65 G 2.616(se)-2.616 G(lse) +-2.616 E .116(where in Mup, an omitted)-.25 F -.2(vo)69.336 712 S .338 +(ice will def).2 F .338(ault to v)-.1 F .338(oice 1, and both staf)-.2 F +2.838(fa)-.25 G .338(nd v)-2.838 F .338(oice can be gi)-.2 F -.15(ve) +-.25 G 2.838(na).15 G 2.838(sal)-2.838 G 2.838(ist. Certain)-2.838 F -.1 +(ke)2.838 G(yw)-.05 E .339(ords apply to the)-.1 F +(entire score. In that case the form)69.336 724 Q EP +%%Page: 152 158 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(52 -)-2.5 E/F1 10 +/Times-Bold@0 SF(midi all:)105.336 96 Q/F2 10/Times-Italic@0 SF(be)6 E +(gintime "k)-.4 E -.3(ey)-.1 G(wor).3 E(d=value";)-.37 E F0 .1 +(is used instead.)69.336 116 R .099(The items speci\214ed using "all" a\ +re placed on the \214rst track, the track containing score-wide)5.1 F +(information. The)69.336 128 Q 2.5(ya)-.15 G(re not applied to the v) +-2.5 E(oices on the other tracks.)-.2 E(The)69.336 146 Q F2(be)2.606 E +(gintime)-.4 E F0 2.606(,a)C 2.606(se)-2.606 G(lse)-2.606 E .106 +(where in Mup, gi)-.25 F -.15(ve)-.25 G 2.606(st).15 G .106 +(he beat into the measure where the MIDI output is to be placed.)-2.606 +F .206(If notes are to be turned on or of)69.336 158 R 2.706(fa)-.25 G +2.706(tt)-2.706 G .205(he same instant in time as the)-2.706 F F2(be) +2.705 E(gintime)-.4 E F0 2.705<2c8c>C .205(rst all "note of)-2.705 F +.205(f" commands)-.25 F(are generated, then the "midi" command e)69.336 +170 Q -.15(ve)-.25 G(nts, then "note on" commands.).15 E(The)69.336 188 +Q F2 -.1(ke)3.344 G(ywor)-.2 E(d=value)-.37 E F0(gi)3.344 E -.15(ve)-.25 +G 3.344(ss).15 G .845 +(peci\214c information of what MIDI output to generate. The follo)-3.344 +F .845(wing k)-.25 F -.15(ey)-.1 G -.1(wo).15 G(rds).1 E +(are currently supported:)69.336 200 Q F1 -.1(ke)76.926 218 S(yw).1 E +31.385(ord v)-.1 F 73.235(alues meaning)-.1 F(midi S V)64.44 E(midi all) +15 E .4 LW 435.986 222.5 69.336 222.5 DL F0 30.82(program 0-127)69.336 +232 R(program change \(ne)40.83 E 2.5(wi)-.25 G 24.45(nstrument\) yes) +-2.5 F(no)38.205 E 24.72(parameter 0-127,0-127)69.336 244 R 120.02 +(parameter yes)15 F(yes)36.54 E 33.6(channel 1-16)69.336 256 R 128.9 +(channel yes)45.83 F(no)38.205 E 12.5(chanpressure 0-127)69.336 268 R +(channel pressure \(after touch\))40.83 E 34.04(yes yes)43.38 F 39.7 +(tempo 10-1000)69.336 280 R(tempo, quarter notes per minute)30.83 E +35.705(no yes)36.685 F 33.59(seqnum 0-65535)69.336 292 R +(sequence number)30.83 E 34.04(yes yes)92.8 F(te)69.336 304 Q 49.85 +(xt te)-.15 F 46.81(xt te)-.15 F(xt meta e)-.15 E -.15(ve)-.25 G 99.45 +(nt yes).15 F(yes)36.54 E(cop)69.336 316 Q 26.47(yright te)-.1 F 46.81 +(xt cop)-.15 F(yright notice)-.1 E 34.04(yes yes)97.33 F 43.04(name te) +69.336 328 R 46.81(xt sequence/track)-.15 F 76.42(name yes)2.5 F(yes) +36.54 E 21.92(instrument te)69.336 340 R 46.81(xt instrument)-.15 F +93.06(name yes)2.5 F(yes)36.54 E(mark)69.336 352 Q 36.48(er te)-.1 F +46.81(xt mark)-.15 F(er meta e)-.1 E -.15(ve)-.25 G 86.08(nt yes).15 F +(yes)36.54 E 50.82(cue te)69.336 364 R 46.81(xt cue)-.15 F 123.06 +(point yes)2.5 F(yes)36.54 E 48.59(port 0-127)69.336 376 R(MIDI port) +40.83 E 34.04(yes yes)121.12 F(on)69.336 388 Q -.15(ve)-.4 G 23.03 +(locity 1-127).15 F(note on v)40.83 E 95.71(elocity yes)-.15 F(no)38.205 +E(of)69.336 400 Q(fv)-.25 E 21.22(elocity 0-127)-.15 F(note of)40.83 E +2.5(fv)-.25 G 94.3(elocity yes)-2.65 F(no)38.205 E(he)69.336 412 Q 52.91 +(xh)-.15 G .3 -.15(ex d)-52.91 H 28.21(ata arbitrary).15 F(MIDI data)2.5 +E 34.04(yes yes)83.64 F .034(The k)69.336 430 R -.15(ey)-.1 G -.1(wo).15 +G .034(rds can be abbre).1 F .034 +(viated to their \214rst three or more letters, e)-.25 F .033 +(xcept "chanpressure" which requires at)-.15 F .389(least \214v)69.336 +442 R 2.889(el)-.15 G .389(etters to dif)-2.889 F .389(ferentiate it fr\ +om "channel" \("cha" or "chan" will be interpreted as channel\).)-.25 F +.39(In most)5.39 F .342(cases, the "=" is follo)69.336 454 R .342 +(wed by either a number or some te)-.25 F .342 +(xt. Exceptions to this are discussed in the ne)-.15 F .342(xt fe)-.15 F +(w)-.25 E(paragraphs.)69.336 466 Q 1.446(The "parameter" k)69.336 484 R +-.15(ey)-.1 G -.1(wo).15 G 1.446(rd is follo).1 F 1.446 +(wed by 2 numbers, separated by a comma.)-.25 F 1.447 +(The \214rst is the parameter)6.446 F(number)69.336 496 Q 2.926(,t)-.4 G +.426(he second is the parameter v)-2.926 F 2.926(alue. Thus)-.25 F .425 +(to set parameter 7 \(which is the v)2.926 F .425 +(olume parameter\) to 90)-.2 F(for v)69.336 508 Q(oice 2 of staf)-.2 E +2.5(f3)-.25 G 2.5(,s)-2.5 G(tarting at the be)-2.5 E +(ginning of the measure, you can use:)-.15 E/F3 10/Courier@0 SF +(midi 3 2: 0 "parameter=7,90";)105.336 526 Q F0 .098(The "on)69.336 552 +R -.15(ve)-.4 G .098(locity" and "of).15 F(fv)-.25 E .098(elocity" k) +-.15 F -.15(ey)-.1 G -.1(wo).15 G .098(rds can ha).1 F .398 -.15(ve o) +-.2 H .098(ne or more v).15 F .098 +(alues, separated by commas. If there is)-.25 F .09(only one v)69.336 +564 R .09(alue, it applies to all notes in each chord. If there is more\ + than one v)-.25 F .09(alue, the \214rst v)-.25 F .09(alue applies to) +-.25 F .445(the top note of the chord, the second v)69.336 576 R .445 +(alue to the second-from-the-top note, and so forth. If there are more) +-.25 F .092(notes in a chord than there are v)69.336 588 R .092 +(alues speci\214ed, the last v)-.25 F .091 +(alue speci\214ed applies to all of the remaining notes.)-.25 F 1.107 +(So, for e)69.336 600 R 1.107(xample, if you w)-.15 F 1.107 +(ant to emphasize the top note of each chord because it is the melody) +-.1 F 3.607(,y)-.65 G 1.107(ou can)-3.607 F(specify tw)69.336 612 Q 2.5 +(ov)-.1 G(alues, as in)-2.75 E F3(midi 1: 1 "onvelocity=76, 60";)105.336 +630 Q F0(which w)69.336 650 Q(ould cause the top note to ha)-.1 E .3 +-.15(ve a ve)-.2 H(locity of 76 and all other notes to ha).15 E .3 -.15 +(ve a ve)-.2 H(locity of 60.).15 E .384(The "he)69.336 668 R .384 +(x" form can be used to insert an)-.15 F 2.884(ya)-.15 G .384 +(rbitrary MIDI data into the MIDI \214le. The v)-2.884 F .384 +(alue consists of an)-.25 F(y)-.15 E -2.15 -.25(ev e)69.336 680 T 2.5 +(nn).25 G(umber of he)-2.5 E(xadecimal digits.)-.15 E +(Spaces and tabs can be included in the v)5 E +(alue \214eld for readability)-.25 E(.)-.65 E .939(Note that Mup uses t\ +he MIDI standard, which numbers instruments from 0 through 127, b)69.336 +698 R .939(ut some MIDI)-.2 F(playback programs follo)69.336 710 Q 2.5 +(wac)-.25 G(on)-2.5 E -.15(ve)-.4 G +(ntion of numbering them from 1 through 128.).15 E(Here are some e) +69.336 728 Q(xamples:)-.15 E EP +%%Page: 153 159 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(53 -)-2.5 E/F1 10/Courier@0 +SF(midi all: 0 "tempo=72";)105.336 96 Q +(midi 1-2 1-2: 0 "channel=2"; 0 "program=14"; 3.5 "program=76";)105.336 +108 Q(midi all: 3 "hex= ff 00 02 00 01";)105.336 120 Q +(// sequence number 1)18 E +(midi 3,6: 0 "channel=5"; 0 "prog=15"; 0 "instr=dulcimer";)105.336 132 Q +(// set parameter 7 \(usually volume\) to 100)105.336 144 Q +(midi 2: "par = 7, 100";)105.336 156 Q F0(Here is a more e)69.336 182 Q +(xtensi)-.15 E .3 -.15(ve ex)-.25 H(ample of ho).15 E 2.5(wm)-.25 G +(idi commands might be used in a song:)-2.5 E EP +%%Page: 154 160 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(54 -)-2.5 E/F1 10/Courier@0 +SF(score)105.336 96 Q(staffs=2)130.336 108 Q(vscheme=2o)130.336 120 Q +(staff 2)105.336 144 Q(clef=bass)130.336 156 Q(voice 2 2)105.336 180 Q +(// Make the bottom voice more staccato)130.336 192 Q(release=50)130.336 +204 Q(music)105.336 228 Q(// Set the tempo.)105.336 252 Q +(// Start out at 108 quarter notes per minute,)105.336 264 Q +(// but on count 4, slow down to 96 per minute.)105.336 276 Q +(midi all: 0 "tempo=108"; 4 "tempo=96";)105.336 288 Q +(// Put each voice on a different channel)105.336 312 Q +(// using a different instrument sound.)105.336 324 Q +(// The program numbers correspond to the)105.336 336 Q +(// General MIDI sounds as noted.)105.336 348 Q +(midi 1 1: 0 "channel=1"; 0 "program=68";)105.336 360 Q(//oboe)12 E +(midi 1 2: 0 "channel=2"; 0 "program=11";)105.336 372 Q(//vibraphone)12 +E(midi 2 1: 0 "channel=6"; 0 "program=60";)105.336 384 Q(//french horn) +12 E(midi 2 2: 0 "channel=4"; 0 "program=35";)105.336 396 Q +(//fretless bass)12 E(// Make the top voice louder, and put an)105.336 +420 Q(// accent on the third beat)105.336 432 Q +(midi 1 1: 0 "onvelocity=86"; 3 "onvelocity=100"; 4 "onvel=86";)105.336 +444 Q(// Set maximum reverb on french horn part,)105.336 468 Q +(// starting at the second beat.)105.336 480 Q +(// \(Reverb is parameter 91\))105.336 492 Q +(midi 2 1: 2 "parameter=91, 127";)105.336 504 Q +(// Set chorus on oboe to 75, from the beginning.)105.336 528 Q +(// \(Chorus is parameter 93\))105.336 540 Q +(midi 1 1: 0 "param=93, 75";)105.336 552 Q +(// Pan the bass part to middle of left side.)105.336 576 Q +(// \(Pan is parameter 10, with a value of 0 being hard left,)105.336 +588 Q(// 64 in the center, and 127 being hard right, so 32 is)105.336 +600 Q(// half way to the left.\))105.336 612 Q +(midi 2 2: 0 "parameter=10, 32";)105.336 624 Q +(// Now the music to be played...)105.336 648 Q 6(11)105.336 660 S 6(:e) +-6 G(;d;2c;)-6 E 6(12)105.336 672 S 6(:c)-6 G(;b-;2g-;)-6 E 6(21)105.336 +684 S 6(:g)-6 G(;f;2e;)-6 E 6(22)105.336 696 S 6(:c)-6 G(;g-;2c;)-6 E +(bar)105.336 708 Q EP +%%Page: 155 161 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(55 -)-2.5 E 69.336 103 +EBEGIN +0 0.1 0.5 setrgbcolor +EEND/F0 15/Times-Bold@0 SF 3.75(15. CONCLUSION)73.086 103 R 69.336 121 +EBEGIN +0 0 0 setrgbcolor +EEND/F0 10/Times-Roman@0 SF .497(The Mup program pro)72.333 121 R .496 +(vides a con)-.15 F -.15(ve)-.4 G .496(nient w).15 F .496 +(ay to produce high-quality musical scores. W)-.1 F 2.996(eh)-.8 G .496 +(ope you enjo)-2.996 F(y)-.1 E 1.769(using it.)69.336 133 R 1.769 +(Appendix A gi)6.769 F -.15(ve)-.25 G 4.269(sas).15 G 1.769 +(ample input \214le, demonstrating man)-4.269 F 4.27(yo)-.15 G 4.27(ft) +-4.27 G 1.77(he features of Mup. Y)-4.27 F 1.77(ou can)-1.1 F(do)69.336 +145 Q 1.084(wnload additional sample songs from the Arkkra Enterprises \ +web site listed belo)-.25 F 4.884 -.65(w. T)-.25 H 1.084 +(he web site also).65 F 1.644(includes se)69.336 157 R -.15(ve)-.25 G +1.644(ral programs written by Mup users that may mak).15 F 4.144(eM)-.1 +G 1.645(up e)-4.144 F -.15(ve)-.25 G 4.145(nm).15 G 1.645 +(ore useful for you.)-4.145 F(Once)6.645 E(you')69.336 169 Q 1.442 -.15 +(ve u)-.5 H 1.141(sed Mup for a while, you may \214nd the Quick Referen\ +ce helpful for remembering details of the).15 F(Mup language.)69.336 181 +Q(If you ha)69.336 199 Q .3 -.15(ve c)-.2 H +(omments or questions, please contact:).15 E(Arkkra Enterprises)141.336 +211 Q 2.22 -1.11(P. O)141.336 223 T 2.5(.B)1.11 G(ox 315)-2.5 E -.8(Wa) +141.336 235 S(rren).8 E(ville, IL 60555)-.4 E(support@arkkra.com)141.336 +259 Q(http://www)141.336 283 Q(.arkkra.com)-.65 E EP +%%Page: 156 162 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(56 -)-2.5 E/F1 16 +/Times-Bold@0 SF -.4(Ap)244.416 324 S(pendix A).4 E +(Example of a Mup input \214le)189.544 372 Q EP +%%Page: 157 163 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(57 -)-2.5 E/F1 10/Courier@0 +SF(//!Mup-Arkkra)105.336 96 Q(// sample of a Mup input file)105.336 120 +Q(header)105.336 144 Q(title \(18\) "The Star Spangled Banner")130.336 +156 Q(title ital \(12\) "\(The United States National Anthem\)")130.336 +168 Q(title \(9\) "Text: Francis Scott Key" "Tune: J. S. Smith")130.336 +180 Q(title \(9\) "")130.336 192 Q("arr: William J. Krauss")12 E(score) +105.336 216 Q(topmargin = 0.5)130.336 228 Q(bottommargin = 0.5)130.336 +240 Q(leftmargin = 0.65)130.336 252 Q(rightmargin = 0.65)130.336 264 Q +(scale = 0.65)130.336 276 Q(packfact = 1.3)130.336 288 Q(key = 3#) +130.336 300 Q(time = 3/4)130.336 312 Q(staffs = 2)130.336 324 Q +(brace = 1-2)130.336 336 Q(barstyle = 1-2)130.336 348 Q(measnum = y) +130.336 360 Q(vscheme = 2o)130.336 372 Q(beamstyle = 4,4,4)130.336 384 Q +(endingstyle = top)130.336 396 Q(staff 2)105.336 420 Q(clef = bass) +130.336 432 Q(define LYRICS lyrics between 1&2: @)105.336 456 Q(music) +105.336 480 Q(// Starts on a pickup, so use space)130.336 492 Q +(// at beginning of measure.)130.336 504 Q +(// Voices are in unison for the first)130.336 516 Q +(// few notes, so specify two voices)130.336 528 Q(// at once.)130.336 +540 Q 6(11)130.336 552 S(-2: 2s; 8.e<>; 16c;)-6 E 6(21)130.336 564 S +(-2: 2s; 8.e<>; 16c;)-6 E(LYRICS 2s; 4;)130.336 576 Q([1] "Oh_";)22 E +(// Since the first two sections are)130.336 588 Q +(// almost the same, use a repeat)130.336 600 Q(repeatstart)130.336 612 +Q 6(11)130.336 636 S 6(:a)-6 G(-; c; e;)-6 E 6(12)130.336 648 S 6(:a)-6 +G(-; c; b-;)-6 E 6(21)130.336 660 S 6(:a)-6 G(-; a; b;)-6 E 6(22)130.336 +672 S 6(:a)-6 G(-; a; g;)-6 E 33(LYRICS [1])130.336 684 R +("say. can you";)6 E(\\)12 E([2] "stripes and bright";)180.336 696 Q +(bar)130.336 708 Q 6(11)130.336 732 S 6(:2)-6 G(a; 8.c+; 16b;)-6 E EP +%%Page: 158 164 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(58 -)-2.5 E/F1 10/Courier@0 +SF 6(12)130.336 96 S 6(:2)-6 G(c; 8.; 16;)-6 E 6(21)130.336 108 S 6(:2) +-6 G(a; 8.g; 16;)-6 E 6(22)130.336 120 S 6(:2)-6 G(f; 8.e#; 16;)-6 E 33 +(LYRICS [1])130.336 132 R("see, by the";)6 E(\\)12 E +([2] "stars, through the";)180.336 144 Q(bar)130.336 156 Q 6(11)130.336 +180 S 6(:a)-6 G 6(;c)-6 G 6(;d)-6 G(#;)-6 E 6(12)130.336 192 S 6(:c)-6 G +6(;;b)-6 G(-;)-6 E 6(21)130.336 204 S 6(:a)-6 G 6(;;;)-6 G 6(22)130.336 +216 S 6(:f)-6 G 6(;;b)-6 G(-;)-6 E 33(LYRICS [1])130.336 228 R +("dawn's ear-ly";)6 E(\\)12 E([2] "per-il-ous";)180.336 240 Q(bar) +130.336 252 Q 6(11)130.336 276 S 6(:e)-6 G 6(;r)-6 G 6(;8)-6 G(e; ;)-6 E +6(12)130.336 288 S 6(:b)-6 G(-; r; 8b-; ;)-6 E 6(21)130.336 300 S 6(:g) +-6 G 6(;r)-6 G 6(;8)-6 G(g; ;)-6 E 6(22)130.336 312 S 6(:e)-6 G 6(;r)-6 +G 6(;8)-6 G(e; ;)-6 E 33(LYRICS [1])130.336 324 R("light what so";)6 E +(\\)12 E([2] "fight, o'er the";)180.336 336 Q(bar)130.336 348 Q 6(11) +130.336 372 S 6(:4)-6 G(.c+; 8b; 4a;)-6 E 6(12)130.336 384 S 6(:4)-6 G +(.e; 8; 4;)-6 E 6(21)130.336 396 S 6(:4)-6 G(.a; 8g; 4a;)-6 E 6(22) +130.336 408 S 6(:4)-6 G(.a-; 8b-; 4c;)-6 E 33(LYRICS [1])130.336 420 R +("proud-ly we";)6 E(\\)12 E([2] "ram-parts we";)180.336 432 Q(bar) +130.336 444 Q 6(11)130.336 468 S 6(:2)-6 G(g; 8.f; 16g;)-6 E 6(12) +130.336 480 S 6(:2)-6 G(e; 8.; 16;)-6 E 6(21)130.336 492 S 6(:2)-6 G +(b; 8.; 16;)-6 E 6(22)130.336 504 S 6(:2)-6 G(e; 8.d; 16;)-6 E 33 +(LYRICS [1])130.336 516 R("hailed, At the";)6 E(\\)12 E +([2] "watched, were so";)180.336 528 Q(bar)130.336 540 Q 6(11)130.336 +564 S 6(:a)-6 G 6(;;e)-6 G(;)-6 E 6(12)130.336 576 S 6(:e)-6 G 6(;;;)-6 +G 6(21)130.336 588 S 6(:a)-6 G 6(;;e)-6 G(;)-6 E 6(22)130.336 600 S 6 +(:c)-6 G 6(;;e)-6 G(;)-6 E 33(LYRICS [1])130.336 612 R +("twi-light's last";)6 E(\\)12 E([2] "gal-lant-ly";)180.336 624 Q +(bar ending "1.")130.336 636 Q(1-2 1-2: c; 8a-; r; 8.e; 16c;)130.336 660 +Q 33(LYRICS [1])130.336 672 R("gleam-ing, whose broad";)6 E +(repeatend ending "2.")130.336 684 Q 6(11)130.336 708 S 6(:c)-6 G 6(;8) +-6 G(a-; r; 8.c+; 16;)-6 E 6(12)130.336 720 S 6(:c)-6 G 6(;8)-6 G +(a-; r; 8.e; 16;)-6 E 6(21)130.336 732 S 6(:c)-6 G 6(;8)-6 G +(a-; r; 8.a; 16;)-6 E EP +%%Page: 159 165 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(59 -)-2.5 E/F1 10/Courier@0 +SF 6(22)130.336 96 S 6(:c)-6 G 6(;8)-6 G(a-; r; 8.a-; 16;)-6 E 33 +(LYRICS [2])130.336 108 R("stream-ing? And the";)6 E(bar endending) +130.336 120 Q 6(11)130.336 144 S 6(:c)-6 G(+; d+; e+;)-6 E 6(12)130.336 +156 S 6(:e)-6 G 6(;;;)-6 G 6(21)130.336 168 S 6(:a)-6 G 6(;b)-6 G 6(;c) +-6 G(+;)-6 E 6(22)130.336 180 S 6(:a)-6 G(-; ; ;)-6 E +(// continue to mark as verse 2 from now on,)130.336 192 Q +(// so that the lyrics will line up properly)130.336 204 Q +(// with the lyrics of the second ending.)130.336 216 Q 33(LYRICS [2]) +130.336 228 R("rock-ets' red";)6 E(bar)130.336 240 Q +(// Define a mapping, and use the chord-at-a-time input method for the) +105.336 264 Q(// next several measures.)105.336 276 Q +(Specify the voices in bottom to top order.)12 E(define M)105.336 288 Q +6([22)12 G 6(;21)-6 G 6(;12)-6 G -6 6(;11] @)-6 H +(M: a-c+ee+; rrrr; 8a-bed+; a-aec+;)130.336 312 Q 33(LYRICS [2])130.336 +324 R("glare, the bombs";)6 E(bar)130.336 336 Q(M: egeb; egec+; eged+;) +130.336 360 Q 33(LYRICS [2])130.336 372 R("burst-ing in";)6 E(bar) +130.336 384 Q(M: eged+; rrrr; eged+;)130.336 408 Q 33(LYRICS [2])130.336 +420 R("air, gave";)6 E(bar)130.336 432 Q(M: 4.a-aec+; 8b-geb; 4caea;) +130.336 456 Q 33(LYRICS [2])130.336 468 R("proof through the";)6 E(bar) +130.336 480 Q(M: 2ebeg; 8.ebdf; 16ebdg;)130.336 504 Q 33(LYRICS [2]) +130.336 516 R("night that our";)6 E(bar)130.336 528 Q +(M: faca; facc; b-ab-d#;)130.336 552 Q 33(LYRICS [2])130.336 564 R +("flag was still";)6 E(bar)130.336 576 Q(M: egb-e; rrrr; egb-e;)130.336 +600 Q 33(LYRICS [2])130.336 612 R("there. Oh";)6 E(bar)130.336 624 Q 6 +(11)130.336 648 S 6(:4)-6 G(a; ; 8<>; g;)-6 E 6(12)130.336 660 S 6(:4)-6 +G(c; b-; 4a-;)-6 E 6(21)130.336 672 S 6(:e)-6 G 6(;;;)-6 G 6(22)130.336 +684 S 6(:a)-6 G(-; b-; c;)-6 E 33(LYRICS [2])130.336 696 R +("say, does that";)6 E(bar)130.336 708 Q 6(11)130.336 732 S 6(:f)-6 G 6 +(;;;)-6 G EP +%%Page: 160 166 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(60 -)-2.5 E/F1 10/Courier@0 +SF 6(12)130.336 96 S 6(:d)-6 G 6(;;e)-6 G(;)-6 E 6(21)130.336 108 S 6 +(:a)-6 G 6(;;a)-6 G(#;)-6 E 6(22)130.336 120 S 6(:d)-6 G 6(;;c)-6 G(;)-6 +E 33(LYRICS [2])130.336 132 R("star-span-gled";)6 E(bar)130.336 144 Q 6 +(11)130.336 168 S 6(:4)-6 G(b; 8d+<>; c+; b<>; a;)-6 E 6(12)130.336 180 +S 6(:4)-6 G(d; 4f; ;)-6 E 6(21)130.336 192 S 6(:b)-6 G 6(;8)-6 G +(<>; a#; b<>; b#;)-6 E 6(22)130.336 204 S 6(:b)-6 G(-; 8<>; c; d<>; d#;) +-6 E 33(LYRICS [2])130.336 216 R("ban-ner yet";)6 E(bar)130.336 228 Q +(mussym\(12\) 1-2: 2 "ferm";)130.336 252 Q 6(11)130.336 264 S 6(:a)-6 G +(<>; 8g; r; e; ;)-6 E 6(12)130.336 276 S 6(:4)-6 G(.e; 8r; e; ;)-6 E 6 +(21)130.336 288 S 6(:c)-6 G(+<>; 8b; r; g; ;)-6 E 6(22)130.336 300 S 6 +(:4)-6 G(.e; 8r; d; ;)-6 E 33(LYRICS [2])130.336 312 R +("wave_ o'er the";)6 E(bar)130.336 324 Q 6(11)130.336 348 S 6(:4)-6 G +(.a<>; 8b; c+; d+;)-6 E 6(12)130.336 360 S 6(:4)-6 G(.e<>; 8; ; ;)-6 E 6 +(21)130.336 372 S 6(:4)-6 G(.a<>; 8g; a; ;)-6 E 6(22)130.336 384 S 6(:4) +-6 G(.c<>; 8e; a-; b-;)-6 E 33(LYRICS [2])130.336 396 R("land_ of the";) +6 E(bar)130.336 408 Q(mussym\(12\) 1-2: 1 "ferm";)130.336 432 Q 6(11) +130.336 444 S 6(:e)-6 G(+; r; 8a; b;)-6 E 6(12)130.336 456 S 6(:e)-6 G 6 +(;r)-6 G 6(;8)-6 G(d; ;)-6 E 6(21)130.336 468 S 6(:a)-6 G 6(;r)-6 G 6 +(;8)-6 G(a; ;)-6 E 6(22)130.336 480 S 6(:c)-6 G 6(;r)-6 G 6(;8)-6 G +(f; fn;)-6 E 33(LYRICS [2])130.336 492 R("free and the";)6 E(bar)130.336 +504 Q 6(11)130.336 528 S 6(:4)-6 G(.c+; 8d+; 4b;)-6 E 6(12)130.336 540 S +6(:4)-6 G(.e; 8; 4d;)-6 E 6(21)130.336 552 S 6(:4)-6 G(.a; 8; 4g;)-6 E 6 +(22)130.336 564 S 6(:4)-6 G(.e; 8; 4;)-6 E 33(LYRICS [2])130.336 576 R +("home of the";)6 E(bar)130.336 588 Q 6(11)130.336 612 S 6(:2)-6 G +(a; 4s;)-6 E 6(12)130.336 624 S 6(:2)-6 G(c; 4s;)-6 E 6(21)130.336 636 S +6(:2)-6 G(e; 4s;)-6 E 6(22)130.336 648 S 6(:2)-6 G(a-; 4s;)-6 E 33 +(LYRICS [2])130.336 660 R("brave?";)6 E(endbar)130.336 672 Q EP +%%Page: 161 167 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(61 -)-2.5 E 11.836 96 EBEGIN +gsave 0 0.25 0.75 setrgbcolor 0 636 rlineto 552 0 rlineto 0 636 neg rlineto closepath stroke grestore +EEND 24 127 552 552 -636 636 10.836 732 PBEGIN +%%BeginDocument: mugex102.ps +%%BoundingBox: 24 127 576 763 +save +1930114009 1930113259 sv +0.650000 0.650000 scale +% S_SSV +(/tmp/ugexiM5077) inputfile +12 linenum +% S_SSV +29 linenum +% S_FEED +334.29 1513.68 869.54 5 1.000000 1.000000 stf +334.29 1404.11 869.54 5 1.000000 1.000000 stf +117.79 1093.68 960.11 brace +0.70 setlinewidth +118.29 1093.68 moveto +118.29 960.11 lineto stroke +% S_CLEFSIG +130.08 1075.68 1.000000 gclef +130.33 978.11 1.000000 fclef +144.70 1093.68 1.000000 sharp +151.34 1084.68 1.000000 sharp +157.98 1096.68 1.000000 sharp +144.70 978.11 1.000000 sharp +151.34 969.11 1.000000 sharp +157.98 981.11 1.000000 sharp +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +164.30 1081.68 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +164.30 1069.66 moveto +(4) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +164.30 972.11 moveto +(3) show +/NewCenturySchlbk-Bold findfont +16 scalefont +setfont +164.30 960.09 moveto +(4) show +% S_CHHEAD +% S_STAFF +% staff 1 +save +41 linenum +206.76 1025.96 moveto +232.29 1025.96 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +186.17 1025.96 moveto +(Oh) show +191.32 1069.68 1.000000 4n +200.58 1072.68 1.000000 dot +195.00 1070.43 moveto +195.00 1088.52 lineto stroke +228.25 1063.68 1.000000 4n +222.02 1063.68 moveto +234.49 1063.68 lineto stroke +231.94 1064.43 moveto +231.94 1082.52 lineto stroke +newpath +194.65 1090.02 moveto +232.29 1084.02 lineto +232.29 1081.02 lineto +194.65 1087.02 lineto +closepath +fill +newpath +231.59 1079.02 moveto +223.52 1080.33 lineto +223.52 1077.33 lineto +231.59 1076.02 lineto +closepath +fill +191.32 1069.68 1.000000 4n +200.58 1072.68 1.000000 dot +187.64 1068.93 moveto +187.64 1050.83 lineto stroke +228.25 1063.68 1.000000 4n +222.02 1063.68 moveto +234.49 1063.68 lineto stroke +224.57 1062.93 moveto +224.57 1044.83 lineto stroke +newpath +187.29 1052.33 moveto +224.92 1046.33 lineto +224.92 1043.33 lineto +187.29 1049.33 lineto +closepath +fill +newpath +224.22 1051.33 moveto +216.16 1052.64 lineto +216.16 1049.64 lineto +224.22 1048.33 lineto +closepath +fill +191.32 1064.58 moveto +191.39 1064.77 lineto +195.95 1062.30 200.77 1060.55 205.86 1059.53 curveto +210.94 1058.51 216.07 1058.26 221.23 1058.78 curveto +221.22 1058.37 lineto +216.02 1057.30 210.82 1057.28 205.62 1058.33 curveto +200.42 1059.37 195.62 1061.39 191.24 1064.39 curveto +fill +205.58 1074.78 moveto +205.59 1075.00 lineto +209.65 1076.06 213.71 1076.06 217.77 1074.99 curveto +221.82 1073.91 225.36 1071.91 228.36 1068.98 curveto +228.15 1068.58 lineto +224.93 1071.02 221.36 1072.75 217.45 1073.79 curveto +213.54 1074.82 209.58 1075.08 205.57 1074.55 curveto +fill +restore +% S_STAFF +% staff 2 +save +191.32 975.11 1.000000 4n +200.58 975.11 1.000000 dot +0.70 setlinewidth +195.00 975.86 moveto +195.00 993.95 lineto stroke +228.25 969.11 1.000000 4n +231.94 969.86 moveto +231.94 987.95 lineto stroke +newpath +194.65 995.45 moveto +232.29 989.45 lineto +232.29 986.45 lineto +194.65 992.45 lineto +closepath +fill +newpath +231.59 984.45 moveto +223.52 985.76 lineto +223.52 982.76 lineto +231.59 981.45 lineto +closepath +fill +191.32 975.11 1.000000 4n +200.58 975.11 1.000000 dot +187.64 974.36 moveto +187.64 956.26 lineto stroke +228.25 969.11 1.000000 4n +224.57 968.36 moveto +224.57 950.26 lineto stroke +newpath +187.29 957.76 moveto +224.92 951.76 lineto +224.92 948.76 lineto +187.29 954.76 lineto +closepath +fill +newpath +224.22 956.76 moveto +216.16 958.07 lineto +216.16 955.07 lineto +224.22 953.76 lineto +closepath +fill +191.32 970.01 moveto +191.39 970.20 lineto +195.95 967.73 200.77 965.98 205.86 964.96 curveto +210.94 963.94 216.07 963.69 221.23 964.21 curveto +221.22 963.81 lineto +216.02 962.73 210.82 962.72 205.62 963.76 curveto +200.42 964.80 195.62 966.82 191.24 969.82 curveto +fill +205.58 980.21 moveto +205.59 980.43 lineto +209.65 981.50 213.71 981.49 217.77 980.42 curveto +221.82 979.34 225.36 977.34 228.36 974.41 curveto +228.15 974.01 lineto +224.93 976.45 221.36 978.19 217.45 979.22 curveto +213.54 980.26 209.58 980.51 205.57 979.98 curveto +fill +restore +% S_BAR +44 linenum +253.85 1084.68 1.000000 dot +253.85 1078.68 1.000000 dot +253.85 975.11 1.000000 dot +253.85 969.11 1.000000 dot +0.70 setlinewidth +250.85 1093.68 moveto +250.85 960.11 lineto stroke +3.00 setlinewidth +246.85 1093.68 moveto +246.85 960.11 lineto stroke +0.70 setlinewidth +% S_CHHEAD +% S_STAFF +% staff 1 +save +46 linenum +/Times-Roman findfont +12 scalefont +setfont +263.40 1025.96 moveto +(say.) show +/Times-Roman findfont +12 scalefont +setfont +311.82 1025.96 moveto +(can) show +/Times-Roman findfont +12 scalefont +setfont +358.21 1025.96 moveto +(you) show +46 linenum +/Times-Roman findfont +12 scalefont +setfont +260.34 1012.64 moveto +(stripes) show +/Times-Roman findfont +12 scalefont +setfont +311.66 1012.64 moveto +(and) show +/Times-Roman findfont +12 scalefont +setfont +355.56 1012.64 moveto +(bright) show +268.16 1057.68 1.000000 4n +261.92 1057.68 moveto +274.39 1057.68 lineto stroke +261.92 1063.68 moveto +274.39 1063.68 lineto stroke +271.84 1058.43 moveto +271.84 1081.68 lineto stroke +315.98 1063.68 1.000000 4n +309.74 1063.68 moveto +322.21 1063.68 lineto stroke +319.66 1064.43 moveto +319.66 1084.68 lineto stroke +362.69 1069.68 1.000000 4n +366.37 1070.43 moveto +366.37 1090.68 lineto stroke +268.16 1057.68 1.000000 4n +261.92 1057.68 moveto +274.39 1057.68 lineto stroke +261.92 1063.68 moveto +274.39 1063.68 lineto stroke +264.47 1056.93 moveto +264.47 1036.68 lineto stroke +315.98 1063.68 1.000000 4n +309.74 1063.68 moveto +322.21 1063.68 lineto stroke +312.29 1062.93 moveto +312.29 1042.68 lineto stroke +362.69 1060.68 1.000000 4n +356.46 1063.68 moveto +368.92 1063.68 lineto stroke +359.01 1059.93 moveto +359.01 1039.68 lineto stroke +restore +% S_STAFF +% staff 2 +save +268.16 963.11 1.000000 4n +0.70 setlinewidth +271.84 963.86 moveto +271.84 984.11 lineto stroke +315.98 984.11 1.000000 4n +319.66 984.86 moveto +319.66 1005.11 lineto stroke +362.69 987.11 1.000000 4n +366.37 987.86 moveto +366.37 1008.11 lineto stroke +268.16 963.11 1.000000 4n +264.47 962.36 moveto +264.47 942.11 lineto stroke +315.98 984.11 1.000000 4n +312.29 983.36 moveto +312.29 963.11 lineto stroke +362.69 981.11 1.000000 4n +359.01 980.36 moveto +359.01 960.11 lineto stroke +restore +% S_BAR +53 linenum +0.70 setlinewidth +408.44 1093.68 moveto +408.44 960.11 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +54 linenum +/Times-Roman findfont +12 scalefont +setfont +421.16 1025.96 moveto +(see,) show +/Times-Roman findfont +12 scalefont +setfont +496.19 1025.96 moveto +(by) show +/Times-Roman findfont +12 scalefont +setfont +532.97 1025.96 moveto +(the) show +54 linenum +/Times-Roman findfont +12 scalefont +setfont +419.51 1012.64 moveto +(stars,) show +/Times-Roman findfont +12 scalefont +setfont +489.89 1012.64 moveto +(through) show +/Times-Roman findfont +12 scalefont +setfont +532.97 1012.64 moveto +(the) show +425.75 1078.68 1.000000 2n +429.65 1079.43 moveto +429.65 1099.68 lineto stroke +499.18 1084.68 1.000000 4n +508.44 1084.68 1.000000 dot +502.86 1085.43 moveto +502.86 1103.85 lineto stroke +536.62 1081.68 1.000000 4n +540.30 1082.43 moveto +540.30 1100.85 lineto stroke +newpath +502.51 1105.35 moveto +540.65 1102.35 lineto +540.65 1099.35 lineto +502.51 1102.35 lineto +closepath +fill +newpath +539.95 1097.35 moveto +531.89 1098.00 lineto +531.89 1095.00 lineto +539.95 1094.35 lineto +closepath +fill +425.75 1063.68 1.000000 2n +419.30 1063.68 moveto +432.20 1063.68 lineto stroke +421.85 1062.93 moveto +421.85 1042.68 lineto stroke +499.18 1063.68 1.000000 4n +508.44 1060.68 1.000000 dot +492.94 1063.68 moveto +505.41 1063.68 lineto stroke +495.49 1062.93 moveto +495.49 1044.18 lineto stroke +536.62 1063.68 1.000000 4n +530.39 1063.68 moveto +542.85 1063.68 lineto stroke +532.94 1062.93 moveto +532.94 1044.18 lineto stroke +newpath +495.14 1045.68 moveto +533.29 1045.68 lineto +533.29 1042.68 lineto +495.14 1042.68 lineto +closepath +fill +newpath +532.59 1050.68 moveto +524.52 1050.68 lineto +524.52 1047.68 lineto +532.59 1047.68 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +425.75 984.11 1.000000 2n +0.70 setlinewidth +429.65 984.86 moveto +429.65 1005.11 lineto stroke +499.18 981.11 1.000000 4n +508.44 981.11 1.000000 dot +502.86 981.86 moveto +502.86 1000.61 lineto stroke +536.62 981.11 1.000000 4n +540.30 981.86 moveto +540.30 1000.61 lineto stroke +newpath +502.51 1002.11 moveto +540.65 1002.11 lineto +540.65 999.11 lineto +502.51 999.11 lineto +closepath +fill +newpath +539.95 997.11 moveto +531.89 997.11 lineto +531.89 994.11 lineto +539.95 994.11 lineto +closepath +fill +425.75 978.11 1.000000 2n +421.85 977.36 moveto +421.85 957.11 lineto stroke +499.18 975.11 1.000000 4n +489.82 975.11 1.000000 sharp +508.44 975.11 1.000000 dot +495.49 974.36 moveto +495.49 955.61 lineto stroke +536.62 975.11 1.000000 4n +532.94 974.36 moveto +532.94 955.61 lineto stroke +newpath +495.14 957.11 moveto +533.29 957.11 lineto +533.29 954.11 lineto +495.14 954.11 lineto +closepath +fill +newpath +532.59 962.11 moveto +524.52 962.11 lineto +524.52 959.11 lineto +532.59 959.11 lineto +closepath +fill +restore +% S_BAR +61 linenum +0.70 setlinewidth +554.71 1093.68 moveto +554.71 960.11 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +62 linenum +/Times-Roman findfont +12 scalefont +setfont +560.28 1025.96 moveto +(dawn's) show +/Times-Roman findfont +12 scalefont +setfont +643.21 1025.96 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +611.77 1025.96 moveto +(ear) show +/Times-Roman findfont +12 scalefont +setfont +663.03 1025.96 moveto +(ly) show +62 linenum +/Times-Roman findfont +12 scalefont +setfont +595.07 1012.64 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +564.12 1012.64 moveto +(per) show +/Times-Roman findfont +12 scalefont +setfont +639.29 1012.64 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +613.76 1012.64 moveto +(il) show +/Times-Roman findfont +12 scalefont +setfont +661.20 1012.64 moveto +(ous) show +568.92 1078.68 1.000000 4n +572.61 1079.43 moveto +572.61 1099.68 lineto stroke +616.41 1063.68 1.000000 4n +610.18 1063.68 moveto +622.64 1063.68 lineto stroke +620.09 1064.43 moveto +620.09 1084.68 lineto stroke +665.36 1066.68 1.000000 4n +656.00 1066.68 1.000000 sharp +669.04 1067.43 moveto +669.04 1087.68 lineto stroke +568.92 1063.68 1.000000 4n +562.69 1063.68 moveto +575.16 1063.68 lineto stroke +565.24 1062.93 moveto +565.24 1042.68 lineto stroke +616.41 1063.68 1.000000 4n +610.18 1063.68 moveto +622.64 1063.68 lineto stroke +612.73 1062.93 moveto +612.73 1042.68 lineto stroke +665.36 1060.68 1.000000 4n +659.12 1063.68 moveto +671.59 1063.68 lineto stroke +661.67 1059.93 moveto +661.67 1039.68 lineto stroke +restore +% S_STAFF +% staff 2 +save +568.92 984.11 1.000000 4n +0.70 setlinewidth +572.61 984.86 moveto +572.61 1005.11 lineto stroke +616.41 984.11 1.000000 4n +620.09 984.86 moveto +620.09 1005.11 lineto stroke +665.36 984.11 1.000000 4n +669.04 984.86 moveto +669.04 1005.11 lineto stroke +568.92 978.11 1.000000 4n +565.24 977.36 moveto +565.24 957.11 lineto stroke +616.41 978.11 1.000000 4n +612.73 977.36 moveto +612.73 957.11 lineto stroke +665.36 966.11 1.000000 4n +661.67 965.36 moveto +661.67 945.11 lineto stroke +restore +% S_BAR +69 linenum +0.70 setlinewidth +709.62 1093.68 moveto +709.62 960.11 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +70 linenum +/Times-Roman findfont +12 scalefont +setfont +718.76 1025.96 moveto +(light) show +/Times-Roman findfont +12 scalefont +setfont +806.74 1025.96 moveto +(what) show +/Times-Roman findfont +12 scalefont +setfont +838.98 1025.96 moveto +(so) show +70 linenum +/Times-Roman findfont +12 scalefont +setfont +717.84 1012.64 moveto +(fight,) show +/Times-Roman findfont +12 scalefont +setfont +807.75 1012.64 moveto +(o'er) show +/Times-Roman findfont +12 scalefont +setfont +837.99 1012.64 moveto +(the) show +724.23 1069.68 1.000000 4n +727.91 1070.43 moveto +727.91 1090.68 lineto stroke +772.16 1093.68 1.000000 4rest +812.56 1069.68 1.000000 4n +816.24 1070.43 moveto +816.24 1089.18 lineto stroke +841.64 1069.68 1.000000 4n +845.32 1070.43 moveto +845.32 1089.18 lineto stroke +newpath +815.89 1090.68 moveto +845.67 1090.68 lineto +845.67 1087.68 lineto +815.89 1087.68 lineto +closepath +fill +724.23 1060.68 1.000000 4n +718.00 1063.68 moveto +730.46 1063.68 lineto stroke +720.55 1059.93 moveto +720.55 1039.68 lineto stroke +772.16 1051.68 1.000000 4rest +812.56 1060.68 1.000000 4n +806.32 1063.68 moveto +818.79 1063.68 lineto stroke +808.87 1059.93 moveto +808.87 1041.18 lineto stroke +841.64 1060.68 1.000000 4n +835.41 1063.68 moveto +847.87 1063.68 lineto stroke +837.96 1059.93 moveto +837.96 1041.18 lineto stroke +newpath +808.52 1042.68 moveto +838.31 1042.68 lineto +838.31 1039.68 lineto +808.52 1039.68 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +724.23 981.11 1.000000 4n +0.70 setlinewidth +727.91 981.86 moveto +727.91 1002.11 lineto stroke +772.16 990.11 1.000000 4rest +812.56 981.11 1.000000 4n +816.24 981.86 moveto +816.24 1000.61 lineto stroke +841.64 981.11 1.000000 4n +845.32 981.86 moveto +845.32 1000.61 lineto stroke +newpath +815.89 1002.11 moveto +845.67 1002.11 lineto +845.67 999.11 lineto +815.89 999.11 lineto +closepath +fill +724.23 975.11 1.000000 4n +720.55 974.36 moveto +720.55 954.11 lineto stroke +772.16 960.11 1.000000 4rest +812.56 975.11 1.000000 4n +808.87 974.36 moveto +808.87 955.61 lineto stroke +841.64 975.11 1.000000 4n +837.96 974.36 moveto +837.96 955.61 lineto stroke +newpath +808.52 957.11 moveto +838.31 957.11 lineto +838.31 954.11 lineto +808.52 954.11 lineto +closepath +fill +restore +% S_BAR +77 linenum +0.70 setlinewidth +869.19 1093.68 moveto +869.19 960.11 lineto stroke +% S_FEED +298.00 1320.11 869.54 5 1.000000 1.000000 stf +/Times-Roman findfont +11 scalefont +setfont +86.50 914.11 moveto +(5) show +298.00 1207.41 869.54 5 1.000000 1.000000 stf +81.50 900.11 763.41 brace +82.00 900.11 moveto +82.00 763.41 lineto stroke +550.59 914.11 moveto +550.59 925.11 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +553.59 915.11 moveto +(1.) show +550.59 925.11 moveto +709.87 925.11 lineto stroke +709.87 925.11 moveto +709.87 914.11 lineto stroke +713.87 914.11 moveto +713.87 925.11 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +716.87 915.11 moveto +(2.) show +713.87 925.11 moveto +867.19 925.11 lineto stroke +% S_CLEFSIG +93.79 882.11 1.000000 gclef +94.04 781.41 1.000000 fclef +108.41 900.11 1.000000 sharp +115.05 891.11 1.000000 sharp +121.69 903.11 1.000000 sharp +108.41 781.41 1.000000 sharp +115.05 772.41 1.000000 sharp +121.69 784.41 1.000000 sharp +% S_CHHEAD +% S_STAFF +% staff 1 +save +78 linenum +/Times-Roman findfont +12 scalefont +setfont +183.52 829.33 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +141.70 829.33 moveto +(proud) show +/Times-Roman findfont +12 scalefont +setfont +200.47 829.33 moveto +(ly) show +/Times-Roman findfont +12 scalefont +setfont +230.02 829.33 moveto +(we) show +78 linenum +/Times-Roman findfont +12 scalefont +setfont +178.32 816.01 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +144.00 816.01 moveto +(ram) show +/Times-Roman findfont +12 scalefont +setfont +196.98 816.01 moveto +(parts) show +/Times-Roman findfont +12 scalefont +setfont +230.02 816.01 moveto +(we) show +149.66 891.11 1.000000 4n +158.92 891.11 1.000000 dot +153.34 891.86 moveto +153.34 912.11 lineto stroke +202.79 888.11 1.000000 4n +206.47 888.86 moveto +206.47 909.11 lineto stroke +209.50 909.11 1.000000 dnflag +233.51 885.11 1.000000 4n +237.20 885.86 moveto +237.20 906.11 lineto stroke +149.66 876.11 1.000000 4n +158.92 873.11 1.000000 dot +145.97 875.36 moveto +145.97 855.11 lineto stroke +202.79 876.11 1.000000 4n +199.11 875.36 moveto +199.11 855.11 lineto stroke +202.13 855.11 1.000000 upflag +233.51 876.11 1.000000 4n +229.83 875.36 moveto +229.83 855.11 lineto stroke +restore +% S_STAFF +% staff 2 +save +149.66 787.41 1.000000 4n +158.92 790.41 1.000000 dot +0.70 setlinewidth +153.34 788.16 moveto +153.34 808.41 lineto stroke +202.79 784.41 1.000000 4n +206.47 785.16 moveto +206.47 805.41 lineto stroke +209.50 805.41 1.000000 dnflag +233.51 787.41 1.000000 4n +237.20 788.16 moveto +237.20 808.41 lineto stroke +149.66 766.41 1.000000 4n +158.92 766.41 1.000000 dot +145.97 765.66 moveto +145.97 745.41 lineto stroke +202.79 769.41 1.000000 4n +199.11 768.66 moveto +199.11 748.41 lineto stroke +202.13 748.41 1.000000 upflag +233.51 772.41 1.000000 4n +229.83 771.66 moveto +229.83 751.41 lineto stroke +restore +% S_BAR +85 linenum +0.70 setlinewidth +273.60 900.11 moveto +273.60 763.41 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +86 linenum +/Times-Roman findfont +12 scalefont +setfont +284.58 829.33 moveto +(hailed,) show +/Times-Roman findfont +12 scalefont +setfont +358.92 829.33 moveto +(At) show +/Times-Roman findfont +12 scalefont +setfont +390.65 829.33 moveto +(the) show +86 linenum +/Times-Roman findfont +12 scalefont +setfont +281.91 816.01 moveto +(watched,) show +/Times-Roman findfont +12 scalefont +setfont +356.09 816.01 moveto +(were) show +/Times-Roman findfont +12 scalefont +setfont +391.64 816.01 moveto +(so) show +292.64 882.11 1.000000 2n +296.54 882.86 moveto +296.54 903.11 lineto stroke +358.23 879.11 1.000000 4n +374.85 879.11 1.000000 dot +361.91 879.86 moveto +361.91 898.94 lineto stroke +394.31 882.11 1.000000 4n +397.99 882.86 moveto +397.99 901.94 lineto stroke +newpath +361.56 900.44 moveto +398.34 903.44 lineto +398.34 900.44 lineto +361.56 897.44 lineto +closepath +fill +newpath +397.64 898.44 moveto +389.58 897.77 lineto +389.58 894.77 lineto +397.64 895.44 lineto +closepath +fill +292.64 876.11 1.000000 2n +288.74 875.36 moveto +288.74 855.11 lineto stroke +365.59 876.11 1.000000 4n +374.85 873.11 1.000000 dot +361.91 875.36 moveto +361.91 856.61 lineto stroke +394.31 876.11 1.000000 4n +390.63 875.36 moveto +390.63 856.61 lineto stroke +newpath +361.56 858.11 moveto +390.98 858.11 lineto +390.98 855.11 lineto +361.56 855.11 lineto +closepath +fill +newpath +390.28 863.11 moveto +382.21 863.11 lineto +382.21 860.11 lineto +390.28 860.11 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +292.64 790.41 1.000000 2n +0.70 setlinewidth +296.54 791.16 moveto +296.54 811.41 lineto stroke +361.91 790.41 1.000000 4n +371.17 790.41 1.000000 dot +365.59 791.16 moveto +365.59 809.91 lineto stroke +394.31 790.41 1.000000 4n +397.99 791.16 moveto +397.99 809.91 lineto stroke +newpath +365.24 811.41 moveto +398.34 811.41 lineto +398.34 808.41 lineto +365.24 808.41 lineto +closepath +fill +newpath +397.64 806.41 moveto +389.58 806.41 lineto +389.58 803.41 lineto +397.64 803.41 lineto +closepath +fill +292.64 778.41 1.000000 2n +288.74 777.66 moveto +288.74 757.41 lineto stroke +361.91 775.41 1.000000 4n +371.17 772.41 1.000000 dot +358.23 774.66 moveto +358.23 755.91 lineto stroke +394.31 775.41 1.000000 4n +390.63 774.66 moveto +390.63 755.91 lineto stroke +newpath +357.88 757.41 moveto +390.98 757.41 lineto +390.98 754.41 lineto +357.88 754.41 lineto +closepath +fill +newpath +390.28 762.41 moveto +382.21 762.41 lineto +382.21 759.41 lineto +390.28 759.41 lineto +closepath +fill +restore +% S_BAR +93 linenum +0.70 setlinewidth +411.13 900.11 moveto +411.13 763.41 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +94 linenum +/Times-Roman findfont +12 scalefont +setfont +443.03 829.33 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +418.15 829.33 moveto +(twi) show +/Times-Roman findfont +12 scalefont +setfont +455.65 829.33 moveto +(light's) show +/Times-Roman findfont +12 scalefont +setfont +504.01 829.33 moveto +(last) show +94 linenum +/Times-Roman findfont +12 scalefont +setfont +443.87 816.01 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +418.31 816.01 moveto +(gal) show +/Times-Roman findfont +12 scalefont +setfont +489.29 816.01 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +457.81 816.01 moveto +(lant) show +/Times-Roman findfont +12 scalefont +setfont +505.85 816.01 moveto +(ly) show +422.95 885.11 1.000000 4n +426.64 885.86 moveto +426.64 906.11 lineto stroke +463.28 885.11 1.000000 4n +466.96 885.86 moveto +466.96 906.11 lineto stroke +508.17 876.11 1.000000 4n +511.85 876.86 moveto +511.85 897.11 lineto stroke +422.95 876.11 1.000000 4n +419.27 875.36 moveto +419.27 855.11 lineto stroke +463.28 876.11 1.000000 4n +459.60 875.36 moveto +459.60 855.11 lineto stroke +508.17 876.11 1.000000 4n +504.49 875.36 moveto +504.49 855.11 lineto stroke +restore +% S_STAFF +% staff 2 +save +422.95 787.41 1.000000 4n +0.70 setlinewidth +426.64 788.16 moveto +426.64 808.41 lineto stroke +463.28 787.41 1.000000 4n +466.96 788.16 moveto +466.96 808.41 lineto stroke +508.17 778.41 1.000000 4n +511.85 779.16 moveto +511.85 799.41 lineto stroke +422.95 772.41 1.000000 4n +419.27 771.66 moveto +419.27 751.41 lineto stroke +463.28 772.41 1.000000 4n +459.60 771.66 moveto +459.60 751.41 lineto stroke +508.17 778.41 1.000000 4n +504.49 777.66 moveto +504.49 757.41 lineto stroke +restore +% S_BAR +100 linenum +0.70 setlinewidth +548.59 900.11 moveto +548.59 763.41 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +102 linenum +/Times-Roman findfont +12 scalefont +setfont +589.78 829.33 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +554.06 829.33 moveto +(gleam) show +/Times-Roman findfont +12 scalefont +setfont +599.20 829.33 moveto +(ing,) show +/Times-Roman findfont +12 scalefont +setfont +642.66 829.33 moveto +(whose) show +/Times-Roman findfont +12 scalefont +setfont +676.65 829.33 moveto +(broad) show +562.38 870.11 1.000000 4n +556.14 870.11 moveto +568.61 870.11 lineto stroke +566.06 870.86 moveto +566.06 891.11 lineto stroke +603.77 864.11 1.000000 4n +597.54 864.11 moveto +610.01 864.11 lineto stroke +597.54 870.11 moveto +610.01 870.11 lineto stroke +607.46 864.86 moveto +607.46 888.11 lineto stroke +610.48 888.11 1.000000 dnflag +628.61 900.11 1.000000 8rest +650.31 876.11 1.000000 4n +659.58 879.11 1.000000 dot +653.99 876.86 moveto +653.99 894.88 lineto stroke +683.45 870.11 1.000000 4n +677.22 870.11 moveto +689.69 870.11 lineto stroke +687.14 870.86 moveto +687.14 888.88 lineto stroke +newpath +653.64 896.38 moveto +687.49 890.38 lineto +687.49 887.38 lineto +653.64 893.38 lineto +closepath +fill +newpath +686.79 885.38 moveto +678.72 886.84 lineto +678.72 883.84 lineto +686.79 882.38 lineto +closepath +fill +562.38 870.11 1.000000 4n +556.14 870.11 moveto +568.61 870.11 lineto stroke +558.69 869.36 moveto +558.69 849.11 lineto stroke +603.77 864.11 1.000000 4n +597.54 864.11 moveto +610.01 864.11 lineto stroke +597.54 870.11 moveto +610.01 870.11 lineto stroke +600.09 863.36 moveto +600.09 843.11 lineto stroke +603.12 843.11 1.000000 upflag +628.61 846.11 1.000000 8rest +650.31 876.11 1.000000 4n +659.58 879.11 1.000000 dot +646.63 875.36 moveto +646.63 857.34 lineto stroke +683.45 870.11 1.000000 4n +677.22 870.11 moveto +689.69 870.11 lineto stroke +679.77 869.36 moveto +679.77 851.34 lineto stroke +newpath +646.28 858.84 moveto +680.12 852.84 lineto +680.12 849.84 lineto +646.28 855.84 lineto +closepath +fill +newpath +679.42 857.84 moveto +671.36 859.30 lineto +671.36 856.30 lineto +679.42 854.84 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +562.38 772.41 1.000000 4n +0.70 setlinewidth +566.06 773.16 moveto +566.06 793.41 lineto stroke +603.77 766.41 1.000000 4n +607.46 767.16 moveto +607.46 787.41 lineto stroke +610.48 787.41 1.000000 dnflag +628.61 793.41 1.000000 8rest +650.31 778.41 1.000000 4n +659.58 778.41 1.000000 dot +653.99 779.16 moveto +653.99 797.18 lineto stroke +683.45 772.41 1.000000 4n +687.14 773.16 moveto +687.14 791.18 lineto stroke +newpath +653.64 798.68 moveto +687.49 792.68 lineto +687.49 789.68 lineto +653.64 795.68 lineto +closepath +fill +newpath +686.79 787.68 moveto +678.72 789.14 lineto +678.72 786.14 lineto +686.79 784.68 lineto +closepath +fill +562.38 772.41 1.000000 4n +558.69 771.66 moveto +558.69 751.41 lineto stroke +603.77 766.41 1.000000 4n +600.09 765.66 moveto +600.09 745.41 lineto stroke +603.12 745.41 1.000000 upflag +628.61 751.41 1.000000 8rest +650.31 778.41 1.000000 4n +659.58 778.41 1.000000 dot +646.63 777.66 moveto +646.63 759.64 lineto stroke +683.45 772.41 1.000000 4n +679.77 771.66 moveto +679.77 753.64 lineto stroke +newpath +646.28 761.14 moveto +680.12 755.14 lineto +680.12 752.14 lineto +646.28 758.14 lineto +closepath +fill +newpath +679.42 760.14 moveto +671.36 761.60 lineto +671.36 758.60 lineto +679.42 757.14 lineto +closepath +fill +restore +% S_BAR +104 linenum +707.87 891.11 1.000000 dot +707.87 885.11 1.000000 dot +707.87 778.41 1.000000 dot +707.87 772.41 1.000000 dot +0.70 setlinewidth +711.87 900.11 moveto +711.87 763.41 lineto stroke +3.00 setlinewidth +715.87 900.11 moveto +715.87 763.41 lineto stroke +0.70 setlinewidth +% S_CHHEAD +% S_STAFF +% staff 1 +save +106 linenum +/Times-Roman findfont +12 scalefont +setfont +758.76 816.01 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +721.48 816.01 moveto +(stream) show +/Times-Roman findfont +12 scalefont +setfont +767.07 816.01 moveto +(ing?) show +/Times-Roman findfont +12 scalefont +setfont +815.15 816.01 moveto +(And) show +/Times-Roman findfont +12 scalefont +setfont +848.71 816.01 moveto +(the) show +730.47 870.11 1.000000 4n +724.23 870.11 moveto +736.70 870.11 lineto stroke +734.15 870.86 moveto +734.15 891.11 lineto stroke +772.22 864.11 1.000000 4n +765.98 864.11 moveto +778.45 864.11 lineto stroke +765.98 870.11 moveto +778.45 870.11 lineto stroke +775.90 864.86 moveto +775.90 888.11 lineto stroke +778.92 888.11 1.000000 dnflag +797.07 900.11 1.000000 8rest +820.30 891.11 1.000000 4n +829.57 891.11 1.000000 dot +823.98 891.86 moveto +823.98 910.61 lineto stroke +852.37 891.11 1.000000 4n +856.05 891.86 moveto +856.05 910.61 lineto stroke +newpath +823.63 912.11 moveto +856.40 912.11 lineto +856.40 909.11 lineto +823.63 909.11 lineto +closepath +fill +newpath +855.70 907.11 moveto +847.64 907.11 lineto +847.64 904.11 lineto +855.70 904.11 lineto +closepath +fill +730.47 870.11 1.000000 4n +724.23 870.11 moveto +736.70 870.11 lineto stroke +726.78 869.36 moveto +726.78 849.11 lineto stroke +772.22 864.11 1.000000 4n +765.98 864.11 moveto +778.45 864.11 lineto stroke +765.98 870.11 moveto +778.45 870.11 lineto stroke +768.53 863.36 moveto +768.53 843.11 lineto stroke +771.56 843.11 1.000000 upflag +797.07 846.11 1.000000 8rest +820.30 876.11 1.000000 4n +829.57 873.11 1.000000 dot +816.62 875.36 moveto +816.62 856.61 lineto stroke +852.37 876.11 1.000000 4n +848.69 875.36 moveto +848.69 856.61 lineto stroke +newpath +816.27 858.11 moveto +849.04 858.11 lineto +849.04 855.11 lineto +816.27 855.11 lineto +closepath +fill +newpath +848.34 863.11 moveto +840.27 863.11 lineto +840.27 860.11 lineto +848.34 860.11 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +730.47 772.41 1.000000 4n +0.70 setlinewidth +734.15 773.16 moveto +734.15 793.41 lineto stroke +772.22 766.41 1.000000 4n +775.90 767.16 moveto +775.90 787.41 lineto stroke +778.92 787.41 1.000000 dnflag +797.07 787.41 1.000000 8rest +820.30 787.41 1.000000 4n +829.57 790.41 1.000000 dot +823.98 788.16 moveto +823.98 806.91 lineto stroke +852.37 787.41 1.000000 4n +856.05 788.16 moveto +856.05 806.91 lineto stroke +newpath +823.63 808.41 moveto +856.40 808.41 lineto +856.40 805.41 lineto +823.63 805.41 lineto +closepath +fill +newpath +855.70 803.41 moveto +847.64 803.41 lineto +847.64 800.41 lineto +855.70 800.41 lineto +closepath +fill +730.47 772.41 1.000000 4n +726.78 771.66 moveto +726.78 751.41 lineto stroke +772.22 766.41 1.000000 4n +768.53 765.66 moveto +768.53 745.41 lineto stroke +771.56 745.41 1.000000 upflag +797.07 751.41 1.000000 8rest +820.30 766.41 1.000000 4n +829.57 766.41 1.000000 dot +816.62 765.66 moveto +816.62 746.91 lineto stroke +852.37 766.41 1.000000 4n +848.69 765.66 moveto +848.69 746.91 lineto stroke +newpath +816.27 748.41 moveto +849.04 748.41 lineto +849.04 745.41 lineto +816.27 745.41 lineto +closepath +fill +newpath +848.34 753.41 moveto +840.27 753.41 lineto +840.27 750.41 lineto +848.34 750.41 lineto +closepath +fill +restore +% S_BAR +111 linenum +0.70 setlinewidth +869.19 900.11 moveto +869.19 763.41 lineto stroke +% S_FEED +298.00 1123.41 869.54 5 1.000000 1.000000 stf +/Times-Roman findfont +11 scalefont +setfont +86.50 717.41 moveto +(10) show +298.00 1036.16 869.54 5 1.000000 1.000000 stf +81.50 703.41 592.16 brace +82.00 703.41 moveto +82.00 592.16 lineto stroke +% S_CLEFSIG +93.79 685.41 1.000000 gclef +94.04 610.16 1.000000 fclef +108.41 703.41 1.000000 sharp +115.05 694.41 1.000000 sharp +121.69 706.41 1.000000 sharp +108.41 610.16 1.000000 sharp +115.05 601.16 1.000000 sharp +121.69 613.16 1.000000 sharp +% S_CHHEAD +% S_STAFF +% staff 1 +save +113 linenum +/Times-Roman findfont +12 scalefont +setfont +172.42 647.69 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +140.28 647.69 moveto +(rock) show +/Times-Roman findfont +12 scalefont +setfont +186.33 647.69 moveto +(ets') show +/Times-Roman findfont +12 scalefont +setfont +232.00 647.69 moveto +(red) show +146.58 694.41 1.000000 4n +150.26 695.16 moveto +150.26 715.41 lineto stroke +190.65 697.41 1.000000 4n +194.33 698.16 moveto +194.33 718.41 lineto stroke +235.82 700.41 1.000000 4n +239.50 701.16 moveto +239.50 721.41 lineto stroke +146.58 679.41 1.000000 4n +142.90 678.66 moveto +142.90 658.41 lineto stroke +190.65 679.41 1.000000 4n +186.96 678.66 moveto +186.96 658.41 lineto stroke +235.82 679.41 1.000000 4n +232.14 678.66 moveto +232.14 658.41 lineto stroke +restore +% S_STAFF +% staff 2 +save +146.58 616.16 1.000000 4n +0.70 setlinewidth +150.26 616.91 moveto +150.26 637.16 lineto stroke +190.65 619.16 1.000000 4n +194.33 619.91 moveto +194.33 640.16 lineto stroke +235.82 622.16 1.000000 4n +229.59 622.16 moveto +242.05 622.16 lineto stroke +239.50 622.91 moveto +239.50 643.16 lineto stroke +146.58 595.16 1.000000 4n +142.90 594.41 moveto +142.90 574.16 lineto stroke +190.65 595.16 1.000000 4n +186.96 594.41 moveto +186.96 574.16 lineto stroke +235.82 595.16 1.000000 4n +232.14 594.41 moveto +232.14 574.16 lineto stroke +restore +% S_BAR +122 linenum +0.70 setlinewidth +277.54 703.41 moveto +277.54 592.16 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +127 linenum +/Times-Roman findfont +12 scalefont +setfont +285.11 647.69 moveto +(glare,) show +/Times-Roman findfont +12 scalefont +setfont +371.78 647.69 moveto +(the) show +/Times-Roman findfont +12 scalefont +setfont +392.14 647.69 moveto +(bombs) show +291.84 700.41 1.000000 4n +295.53 701.16 moveto +295.53 721.41 lineto stroke +337.10 703.41 1.000000 4rest +375.44 697.41 1.000000 4n +379.12 698.16 moveto +379.12 716.42 lineto stroke +400.13 694.41 1.000000 4n +403.82 695.16 moveto +403.82 713.42 lineto stroke +newpath +378.77 717.92 moveto +404.17 714.92 lineto +404.17 711.92 lineto +378.77 714.92 lineto +closepath +fill +291.84 679.41 1.000000 4n +288.16 678.66 moveto +288.16 658.41 lineto stroke +337.10 679.41 1.000000 4rest +375.44 679.41 1.000000 4n +371.76 678.66 moveto +371.76 659.91 lineto stroke +400.13 679.41 1.000000 4n +396.45 678.66 moveto +396.45 659.91 lineto stroke +newpath +371.41 661.41 moveto +396.80 661.41 lineto +396.80 658.41 lineto +371.41 658.41 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +291.84 622.16 1.000000 4n +0.70 setlinewidth +285.61 622.16 moveto +298.08 622.16 lineto stroke +295.53 622.91 moveto +295.53 643.16 lineto stroke +337.10 616.16 1.000000 4rest +375.44 619.16 1.000000 4n +379.12 619.91 moveto +379.12 638.18 lineto stroke +400.13 616.16 1.000000 4n +403.82 616.91 moveto +403.82 635.18 lineto stroke +newpath +378.77 639.68 moveto +404.17 636.68 lineto +404.17 633.68 lineto +378.77 636.68 lineto +closepath +fill +291.84 595.16 1.000000 4n +288.16 594.41 moveto +288.16 574.16 lineto stroke +337.10 592.16 1.000000 4rest +375.44 595.16 1.000000 4n +371.76 594.41 moveto +371.76 575.66 lineto stroke +400.13 595.16 1.000000 4n +396.45 594.41 moveto +396.45 575.66 lineto stroke +newpath +371.41 577.16 moveto +396.80 577.16 lineto +396.80 574.16 lineto +371.41 574.16 lineto +closepath +fill +restore +% S_BAR +130 linenum +0.70 setlinewidth +428.49 703.41 moveto +428.49 592.16 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +131 linenum +/Times-Roman findfont +12 scalefont +setfont +469.28 647.69 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +434.93 647.69 moveto +(burst) show +/Times-Roman findfont +12 scalefont +setfont +482.73 647.69 moveto +(ing) show +/Times-Roman findfont +12 scalefont +setfont +529.89 647.69 moveto +(in) show +441.89 691.41 1.000000 4n +445.58 692.16 moveto +445.58 712.41 lineto stroke +486.54 694.41 1.000000 4n +490.23 695.16 moveto +490.23 715.41 lineto stroke +532.21 697.41 1.000000 4n +535.89 698.16 moveto +535.89 718.41 lineto stroke +441.89 679.41 1.000000 4n +438.21 678.66 moveto +438.21 658.41 lineto stroke +486.54 679.41 1.000000 4n +482.86 678.66 moveto +482.86 658.41 lineto stroke +532.21 679.41 1.000000 4n +528.53 678.66 moveto +528.53 658.41 lineto stroke +restore +% S_STAFF +% staff 2 +save +441.89 613.16 1.000000 4n +0.70 setlinewidth +445.58 613.91 moveto +445.58 634.16 lineto stroke +486.54 613.16 1.000000 4n +490.23 613.91 moveto +490.23 634.16 lineto stroke +532.21 613.16 1.000000 4n +535.89 613.91 moveto +535.89 634.16 lineto stroke +441.89 607.16 1.000000 4n +438.21 606.41 moveto +438.21 586.16 lineto stroke +486.54 607.16 1.000000 4n +482.86 606.41 moveto +482.86 586.16 lineto stroke +532.21 607.16 1.000000 4n +528.53 606.41 moveto +528.53 586.16 lineto stroke +restore +% S_BAR +134 linenum +0.70 setlinewidth +573.19 703.41 moveto +573.19 592.16 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +135 linenum +/Times-Roman findfont +12 scalefont +setfont +583.30 647.69 moveto +(air,) show +/Times-Roman findfont +12 scalefont +setfont +667.66 647.69 moveto +(gave) show +587.20 697.41 1.000000 4n +590.89 698.16 moveto +590.89 718.41 lineto stroke +630.94 703.41 1.000000 4rest +673.31 697.41 1.000000 4n +676.99 698.16 moveto +676.99 718.41 lineto stroke +587.20 679.41 1.000000 4n +583.52 678.66 moveto +583.52 658.41 lineto stroke +630.94 679.41 1.000000 4rest +673.31 679.41 1.000000 4n +669.63 678.66 moveto +669.63 658.41 lineto stroke +restore +% S_STAFF +% staff 2 +save +587.20 613.16 1.000000 4n +0.70 setlinewidth +590.89 613.91 moveto +590.89 634.16 lineto stroke +630.94 622.16 1.000000 4rest +673.31 613.16 1.000000 4n +676.99 613.91 moveto +676.99 634.16 lineto stroke +587.20 607.16 1.000000 4n +583.52 606.41 moveto +583.52 586.16 lineto stroke +630.94 592.16 1.000000 4rest +673.31 607.16 1.000000 4n +669.63 606.41 moveto +669.63 586.16 lineto stroke +restore +% S_BAR +138 linenum +0.70 setlinewidth +715.95 703.41 moveto +715.95 592.16 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +139 linenum +/Times-Roman findfont +12 scalefont +setfont +724.22 647.69 moveto +(proof) show +/Times-Roman findfont +12 scalefont +setfont +776.90 647.69 moveto +(through) show +/Times-Roman findfont +12 scalefont +setfont +823.89 647.69 moveto +(the) show +730.68 694.41 1.000000 4n +739.94 694.41 1.000000 dot +734.36 695.16 moveto +734.36 715.41 lineto stroke +786.19 691.41 1.000000 4n +789.87 692.16 moveto +789.87 712.41 lineto stroke +792.90 712.41 1.000000 dnflag +827.55 688.41 1.000000 4n +831.23 689.16 moveto +831.23 709.41 lineto stroke +730.68 679.41 1.000000 4n +739.94 676.41 1.000000 dot +727.00 678.66 moveto +727.00 658.41 lineto stroke +786.19 679.41 1.000000 4n +782.51 678.66 moveto +782.51 658.41 lineto stroke +785.53 658.41 1.000000 upflag +827.55 679.41 1.000000 4n +823.86 678.66 moveto +823.86 658.41 lineto stroke +restore +% S_STAFF +% staff 2 +save +730.68 616.16 1.000000 4n +739.94 619.16 1.000000 dot +0.70 setlinewidth +734.36 616.91 moveto +734.36 637.16 lineto stroke +786.19 613.16 1.000000 4n +789.87 613.91 moveto +789.87 634.16 lineto stroke +792.90 634.16 1.000000 dnflag +827.55 616.16 1.000000 4n +831.23 616.91 moveto +831.23 637.16 lineto stroke +730.68 595.16 1.000000 4n +739.94 595.16 1.000000 dot +727.00 594.41 moveto +727.00 574.16 lineto stroke +786.19 598.16 1.000000 4n +782.51 597.41 moveto +782.51 577.16 lineto stroke +785.53 577.16 1.000000 upflag +827.55 601.16 1.000000 4n +823.86 600.41 moveto +823.86 580.16 lineto stroke +restore +% S_BAR +142 linenum +0.70 setlinewidth +869.19 703.41 moveto +869.19 592.16 lineto stroke +% S_FEED +298.00 952.16 869.54 5 1.000000 1.000000 stf +/Times-Roman findfont +11 scalefont +setfont +86.50 546.16 moveto +(15) show +298.00 855.84 869.54 5 1.000000 1.000000 stf +81.50 532.16 411.84 brace +82.00 532.16 moveto +82.00 411.84 lineto stroke +% S_CLEFSIG +93.79 514.16 1.000000 gclef +94.04 429.84 1.000000 fclef +108.41 532.16 1.000000 sharp +115.05 523.16 1.000000 sharp +121.69 535.16 1.000000 sharp +108.41 429.84 1.000000 sharp +115.05 420.84 1.000000 sharp +121.69 432.84 1.000000 sharp +% S_CHHEAD +% S_STAFF +% staff 1 +save +143 linenum +/Times-Roman findfont +12 scalefont +setfont +145.59 464.44 moveto +(night) show +/Times-Roman findfont +12 scalefont +setfont +218.99 464.44 moveto +(that) show +/Times-Roman findfont +12 scalefont +setfont +253.20 464.44 moveto +(our) show +151.73 514.16 1.000000 2n +155.63 514.91 moveto +155.63 535.16 lineto stroke +223.47 511.16 1.000000 4n +232.73 511.16 1.000000 dot +227.15 511.91 moveto +227.15 531.02 lineto stroke +257.18 514.16 1.000000 4n +260.86 514.91 moveto +260.86 534.02 lineto stroke +newpath +226.80 532.52 moveto +261.21 535.52 lineto +261.21 532.52 lineto +226.80 529.52 lineto +closepath +fill +newpath +260.51 530.52 moveto +252.45 529.81 lineto +252.45 526.81 lineto +260.51 527.52 lineto +closepath +fill +151.73 508.16 1.000000 2n +147.83 507.41 moveto +147.83 487.16 lineto stroke +223.47 505.16 1.000000 4n +232.73 505.16 1.000000 dot +219.79 504.41 moveto +219.79 485.66 lineto stroke +257.18 505.16 1.000000 4n +253.50 504.41 moveto +253.50 485.66 lineto stroke +newpath +219.44 487.16 moveto +253.85 487.16 lineto +253.85 484.16 lineto +219.44 484.16 lineto +closepath +fill +newpath +253.15 492.16 moveto +245.08 492.16 lineto +245.08 489.16 lineto +253.15 489.16 lineto +closepath +fill +restore +% S_STAFF +% staff 2 +save +151.73 438.84 1.000000 2n +0.70 setlinewidth +155.63 439.59 moveto +155.63 459.84 lineto stroke +223.47 438.84 1.000000 4n +232.73 438.84 1.000000 dot +227.15 439.59 moveto +227.15 458.34 lineto stroke +257.18 438.84 1.000000 4n +260.86 439.59 moveto +260.86 458.34 lineto stroke +newpath +226.80 459.84 moveto +261.21 459.84 lineto +261.21 456.84 lineto +226.80 456.84 lineto +closepath +fill +newpath +260.51 454.84 moveto +252.45 454.84 lineto +252.45 451.84 lineto +260.51 451.84 lineto +closepath +fill +151.73 426.84 1.000000 2n +147.83 426.09 moveto +147.83 405.84 lineto stroke +223.47 426.84 1.000000 4n +232.73 426.84 1.000000 dot +219.79 426.09 moveto +219.79 407.34 lineto stroke +257.18 426.84 1.000000 4n +253.50 426.09 moveto +253.50 407.34 lineto stroke +newpath +219.44 408.84 moveto +253.85 408.84 lineto +253.85 405.84 lineto +219.44 405.84 lineto +closepath +fill +newpath +253.15 413.84 moveto +245.08 413.84 lineto +245.08 410.84 lineto +253.15 410.84 lineto +closepath +fill +restore +% S_BAR +146 linenum +0.70 setlinewidth +274.98 532.16 moveto +274.98 411.84 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +147 linenum +/Times-Roman findfont +12 scalefont +setfont +282.67 464.44 moveto +(flag) show +/Times-Roman findfont +12 scalefont +setfont +325.99 464.44 moveto +(was) show +/Times-Roman findfont +12 scalefont +setfont +373.83 464.44 moveto +(still) show +287.31 517.16 1.000000 4n +290.99 517.91 moveto +290.99 538.16 lineto stroke +330.65 502.16 1.000000 4n +324.42 502.16 moveto +336.88 502.16 lineto stroke +334.33 502.91 moveto +334.33 523.16 lineto stroke +378.31 505.16 1.000000 4n +368.96 505.16 1.000000 sharp +381.99 505.91 moveto +381.99 526.16 lineto stroke +287.31 502.16 1.000000 4n +281.08 502.16 moveto +293.54 502.16 lineto stroke +283.63 501.41 moveto +283.63 481.16 lineto stroke +330.65 502.16 1.000000 4n +324.42 502.16 moveto +336.88 502.16 lineto stroke +326.97 501.41 moveto +326.97 481.16 lineto stroke +378.31 499.16 1.000000 4n +372.08 502.16 moveto +384.54 502.16 lineto stroke +374.63 498.41 moveto +374.63 478.16 lineto stroke +restore +% S_STAFF +% staff 2 +save +287.31 435.84 1.000000 4n +0.70 setlinewidth +290.99 436.59 moveto +290.99 456.84 lineto stroke +330.65 435.84 1.000000 4n +334.33 436.59 moveto +334.33 456.84 lineto stroke +378.31 435.84 1.000000 4n +381.99 436.59 moveto +381.99 456.84 lineto stroke +287.31 429.84 1.000000 4n +283.63 429.09 moveto +283.63 408.84 lineto stroke +330.65 429.84 1.000000 4n +326.97 429.09 moveto +326.97 408.84 lineto stroke +378.31 417.84 1.000000 4n +374.63 417.09 moveto +374.63 396.84 lineto stroke +restore +% S_BAR +150 linenum +0.70 setlinewidth +421.37 532.16 moveto +421.37 411.84 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +151 linenum +/Times-Roman findfont +12 scalefont +setfont +429.14 464.44 moveto +(there.) show +/Times-Roman findfont +12 scalefont +setfont +523.16 464.44 moveto +(Oh) show +435.88 508.16 1.000000 4n +439.56 508.91 moveto +439.56 529.16 lineto stroke +482.34 532.16 1.000000 4rest +526.82 508.16 1.000000 4n +530.50 508.91 moveto +530.50 529.16 lineto stroke +435.88 499.16 1.000000 4n +429.64 502.16 moveto +442.11 502.16 lineto stroke +432.19 498.41 moveto +432.19 478.16 lineto stroke +482.34 490.16 1.000000 4rest +526.82 499.16 1.000000 4n +520.58 502.16 moveto +533.05 502.16 lineto stroke +523.13 498.41 moveto +523.13 478.16 lineto stroke +restore +% S_STAFF +% staff 2 +save +435.88 432.84 1.000000 4n +0.70 setlinewidth +439.56 433.59 moveto +439.56 453.84 lineto stroke +482.34 441.84 1.000000 4rest +526.82 432.84 1.000000 4n +530.50 433.59 moveto +530.50 453.84 lineto stroke +435.88 426.84 1.000000 4n +432.19 426.09 moveto +432.19 405.84 lineto stroke +482.34 411.84 1.000000 4rest +526.82 426.84 1.000000 4n +523.13 426.09 moveto +523.13 405.84 lineto stroke +restore +% S_BAR +154 linenum +0.70 setlinewidth +569.46 532.16 moveto +569.46 411.84 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +155 linenum +/Times-Roman findfont +12 scalefont +setfont +576.91 464.44 moveto +(say,) show +/Times-Roman findfont +12 scalefont +setfont +620.67 464.44 moveto +(does) show +/Times-Roman findfont +12 scalefont +setfont +664.26 464.44 moveto +(that) show +581.67 517.16 1.000000 4n +585.35 517.91 moveto +585.35 538.16 lineto stroke +626.16 517.16 1.000000 4n +629.84 517.91 moveto +629.84 538.16 lineto stroke +668.74 517.16 1.000000 4n +672.42 517.91 moveto +672.42 536.23 lineto stroke +696.74 514.16 1.000000 4n +700.42 514.91 moveto +700.42 533.23 lineto stroke +newpath +672.07 537.73 moveto +700.77 534.73 lineto +700.77 531.73 lineto +672.07 534.73 lineto +closepath +fill +581.67 502.16 1.000000 4n +575.43 502.16 moveto +587.90 502.16 lineto stroke +577.98 501.41 moveto +577.98 481.16 lineto stroke +626.16 499.16 1.000000 4n +619.93 502.16 moveto +632.39 502.16 lineto stroke +622.48 498.41 moveto +622.48 478.16 lineto stroke +668.74 496.16 1.000000 4n +662.51 496.16 moveto +674.97 496.16 lineto stroke +662.51 502.16 moveto +674.97 502.16 lineto stroke +665.06 495.41 moveto +665.06 475.16 lineto stroke +674.77 522.26 moveto +674.75 522.49 lineto +678.42 524.07 682.24 524.60 686.21 524.05 curveto +690.17 523.51 693.71 521.99 696.83 519.48 curveto +696.66 519.05 lineto +693.38 521.05 689.84 522.31 686.04 522.83 curveto +682.24 523.35 678.49 523.08 674.80 522.04 curveto +fill +restore +% S_STAFF +% staff 2 +save +581.67 426.84 1.000000 4n +0.70 setlinewidth +585.35 427.59 moveto +585.35 447.84 lineto stroke +626.16 426.84 1.000000 4n +629.84 427.59 moveto +629.84 447.84 lineto stroke +668.74 426.84 1.000000 4n +672.42 427.59 moveto +672.42 447.84 lineto stroke +581.67 414.84 1.000000 4n +577.98 414.09 moveto +577.98 393.84 lineto stroke +626.16 417.84 1.000000 4n +622.48 417.09 moveto +622.48 396.84 lineto stroke +668.74 420.84 1.000000 4n +665.06 420.09 moveto +665.06 399.84 lineto stroke +restore +% S_BAR +161 linenum +0.70 setlinewidth +722.52 532.16 moveto +722.52 411.84 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +162 linenum +/Times-Roman findfont +12 scalefont +setfont +757.80 464.44 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +729.75 464.44 moveto +(star) show +/Times-Roman findfont +12 scalefont +setfont +805.59 464.44 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +771.58 464.44 moveto +(span) show +/Times-Roman findfont +12 scalefont +setfont +820.64 464.44 moveto +(gled) show +735.06 511.16 1.000000 4n +738.74 511.91 moveto +738.74 532.16 lineto stroke +778.06 511.16 1.000000 4n +781.74 511.91 moveto +781.74 532.16 lineto stroke +822.11 511.16 1.000000 4n +825.79 511.91 moveto +825.79 532.16 lineto stroke +735.06 505.16 1.000000 4n +731.37 504.41 moveto +731.37 484.16 lineto stroke +778.06 505.16 1.000000 4n +774.38 504.41 moveto +774.38 484.16 lineto stroke +829.47 508.16 1.000000 4n +825.79 507.41 moveto +825.79 487.16 lineto stroke +restore +% S_STAFF +% staff 2 +save +735.06 435.84 1.000000 4n +0.70 setlinewidth +738.74 436.59 moveto +738.74 456.84 lineto stroke +778.06 435.84 1.000000 4n +781.74 436.59 moveto +781.74 456.84 lineto stroke +825.79 435.84 1.000000 4n +816.44 435.84 1.000000 sharp +829.47 436.59 moveto +829.47 456.84 lineto stroke +735.06 423.84 1.000000 4n +731.37 423.09 moveto +731.37 402.84 lineto stroke +778.06 423.84 1.000000 4n +774.38 423.09 moveto +774.38 402.84 lineto stroke +825.79 420.84 1.000000 4n +822.11 420.09 moveto +822.11 399.84 lineto stroke +restore +% S_BAR +168 linenum +0.70 setlinewidth +869.19 532.16 moveto +869.19 411.84 lineto stroke +% S_FEED +298.00 771.84 869.54 5 1.000000 1.000000 stf +/Times-Roman findfont +11 scalefont +setfont +86.50 365.84 moveto +(20) show +298.00 669.57 869.54 5 1.000000 1.000000 stf +81.50 351.84 225.57 brace +82.00 351.84 moveto +82.00 225.57 lineto stroke +% S_CLEFSIG +93.79 333.84 1.000000 gclef +94.04 243.57 1.000000 fclef +108.41 351.84 1.000000 sharp +115.05 342.84 1.000000 sharp +121.69 354.84 1.000000 sharp +108.41 243.57 1.000000 sharp +115.05 234.57 1.000000 sharp +121.69 246.57 1.000000 sharp +% S_CHHEAD +% S_STAFF +% staff 1 +save +169 linenum +/Times-Roman findfont +12 scalefont +setfont +163.61 290.12 moveto +(-) show +/Times-Roman findfont +12 scalefont +setfont +139.36 290.12 moveto +(ban) show +/Times-Roman findfont +12 scalefont +setfont +173.58 290.12 moveto +(ner) show +/Times-Roman findfont +12 scalefont +setfont +221.23 290.12 moveto +(yet) show +144.67 339.84 1.000000 4n +148.35 340.59 moveto +148.35 360.84 lineto stroke +177.39 345.84 1.000000 4n +181.08 346.59 moveto +181.08 364.93 lineto stroke +206.42 342.84 1.000000 4n +210.10 343.59 moveto +210.10 361.93 lineto stroke +224.88 339.84 1.000000 4n +228.57 340.59 moveto +228.57 359.03 lineto stroke +263.39 336.84 1.000000 4n +267.07 337.59 moveto +267.07 356.03 lineto stroke +newpath +180.73 366.43 moveto +210.45 363.43 lineto +210.45 360.43 lineto +180.73 363.43 lineto +closepath +fill +newpath +228.22 360.53 moveto +267.42 357.53 lineto +267.42 354.53 lineto +228.22 357.53 lineto +closepath +fill +144.67 324.84 1.000000 4n +140.99 324.09 moveto +140.99 303.84 lineto stroke +177.39 330.84 1.000000 4n +173.71 330.09 moveto +173.71 309.84 lineto stroke +224.88 330.84 1.000000 4n +221.20 330.09 moveto +221.20 309.84 lineto stroke +230.92 344.94 moveto +230.90 345.14 lineto +236.32 346.73 241.84 347.26 247.46 346.74 curveto +253.08 346.22 258.40 344.69 263.44 342.14 curveto +263.34 341.75 lineto +258.18 343.76 252.85 345.02 247.34 345.52 curveto +241.84 346.03 236.37 345.77 230.93 344.75 curveto +fill +183.43 350.94 moveto +183.40 351.17 lineto +187.25 352.75 191.23 353.27 195.35 352.74 curveto +199.47 352.20 203.19 350.67 206.50 348.16 curveto +206.34 347.73 lineto +202.87 349.73 199.16 350.99 195.19 351.51 curveto +191.22 352.03 187.31 351.76 183.45 350.72 curveto +fill +restore +% S_STAFF +% staff 2 +save +144.67 252.57 1.000000 4n +0.70 setlinewidth +148.35 253.32 moveto +148.35 273.57 lineto stroke +177.39 252.57 1.000000 4n +181.08 253.32 moveto +181.08 271.66 lineto stroke +206.42 249.57 1.000000 4n +197.07 249.57 1.000000 sharp +210.10 250.32 moveto +210.10 268.66 lineto stroke +224.88 252.57 1.000000 4n +228.57 253.32 moveto +228.57 272.07 lineto stroke +263.39 252.57 1.000000 4n +254.03 252.57 1.000000 sharp +267.07 253.32 moveto +267.07 272.07 lineto stroke +newpath +180.73 273.16 moveto +210.45 270.16 lineto +210.45 267.16 lineto +180.73 270.16 lineto +closepath +fill +newpath +228.22 273.57 moveto +267.42 273.57 lineto +267.42 270.57 lineto +228.22 270.57 lineto +closepath +fill +144.67 231.57 1.000000 4n +140.99 230.82 moveto +140.99 210.57 lineto stroke +177.39 231.57 1.000000 4n +173.71 230.82 moveto +173.71 211.66 lineto stroke +206.42 234.57 1.000000 4n +202.74 233.82 moveto +202.74 214.66 lineto stroke +224.88 237.57 1.000000 4n +221.20 236.82 moveto +221.20 218.07 lineto stroke +263.39 237.57 1.000000 4n +245.40 237.57 1.000000 sharp +259.71 236.82 moveto +259.71 218.07 lineto stroke +newpath +173.36 213.16 moveto +203.09 216.16 lineto +203.09 213.16 lineto +173.36 210.16 lineto +closepath +fill +newpath +220.85 219.57 moveto +260.06 219.57 lineto +260.06 216.57 lineto +220.85 216.57 lineto +closepath +fill +224.88 232.47 moveto +224.97 232.71 lineto +227.06 231.17 229.39 230.40 231.98 230.40 curveto +234.57 230.40 236.90 231.17 238.99 232.71 curveto +239.16 232.24 lineto +237.21 230.18 234.82 229.15 231.98 229.15 curveto +229.14 229.15 226.75 230.18 224.79 232.24 curveto +fill +177.39 226.47 moveto +177.42 226.70 lineto +181.11 225.66 184.87 225.39 188.67 225.91 curveto +192.48 226.43 196.02 227.69 199.30 229.69 curveto +199.47 229.26 lineto +196.35 226.75 192.81 225.22 188.84 224.68 curveto +184.87 224.14 181.05 224.66 177.37 226.25 curveto +fill +230.92 257.67 moveto +230.88 257.87 lineto +236.11 259.95 241.53 260.98 247.15 260.98 curveto +252.77 260.98 258.20 259.95 263.42 257.87 curveto +263.35 257.48 lineto +258.06 259.00 252.66 259.76 247.15 259.76 curveto +241.64 259.76 236.24 259.00 230.95 257.48 curveto +fill +183.43 257.67 moveto +183.40 257.90 lineto +187.25 259.48 191.23 260.00 195.35 259.46 curveto +199.47 258.93 203.19 257.40 206.50 254.88 curveto +206.34 254.46 lineto +202.87 256.46 199.16 257.72 195.19 258.24 curveto +191.22 258.75 187.31 258.49 183.45 257.45 curveto +fill +restore +% S_BAR +175 linenum +0.70 setlinewidth +284.51 351.84 moveto +284.51 225.57 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +177 linenum +/Times-Roman findfont +12 scalefont +setfont +290.74 290.12 moveto +(wave) show +/Times-Roman findfont +12 scalefont +setfont +366.39 290.12 moveto +(o'er) show +/Times-Roman findfont +12 scalefont +setfont +391.54 290.12 moveto +(the) show +298.55 336.84 1.000000 4n +302.24 337.59 moveto +302.24 357.84 lineto stroke +331.82 333.84 1.000000 4n +335.50 334.59 moveto +335.50 354.84 lineto stroke +338.52 354.84 1.000000 dnflag +352.80 351.84 1.000000 8rest +371.19 327.84 1.000000 4n +374.88 328.59 moveto +374.88 347.34 lineto stroke +395.20 327.84 1.000000 4n +398.88 328.59 moveto +398.88 347.34 lineto stroke +newpath +374.53 348.84 moveto +399.23 348.84 lineto +399.23 345.84 lineto +374.53 345.84 lineto +closepath +fill +298.55 327.84 1.000000 4n +307.82 324.84 1.000000 dot +294.87 327.09 moveto +294.87 306.84 lineto stroke +352.80 309.84 1.000000 8rest +371.19 327.84 1.000000 4n +367.51 327.09 moveto +367.51 308.34 lineto stroke +395.20 327.84 1.000000 4n +391.52 327.09 moveto +391.52 308.34 lineto stroke +newpath +367.16 309.84 moveto +391.87 309.84 lineto +391.87 306.84 lineto +367.16 306.84 lineto +closepath +fill +304.59 341.94 moveto +304.57 342.16 lineto +309.11 343.74 313.78 344.27 318.57 343.74 curveto +323.35 343.21 327.79 341.68 331.88 339.15 curveto +331.75 338.74 lineto +327.52 340.75 323.08 342.00 318.43 342.52 curveto +313.78 343.03 309.17 342.77 304.60 341.73 curveto +fill +/Times-Roman findfont +12 scalefont +setfont +322.78 356.85 moveto +331.82 356.85 1.000000 ferm +340.85 356.85 moveto +restore +% S_STAFF +% staff 2 +save +298.55 255.57 1.000000 4n +0.70 setlinewidth +292.32 255.57 moveto +304.79 255.57 lineto stroke +302.24 256.32 moveto +302.24 276.57 lineto stroke +331.82 252.57 1.000000 4n +335.50 253.32 moveto +335.50 273.57 lineto stroke +338.52 273.57 1.000000 dnflag +352.80 255.57 1.000000 8rest +371.19 246.57 1.000000 4n +374.88 247.32 moveto +374.88 266.07 lineto stroke +395.20 246.57 1.000000 4n +398.88 247.32 moveto +398.88 266.07 lineto stroke +newpath +374.53 267.57 moveto +399.23 267.57 lineto +399.23 264.57 lineto +374.53 264.57 lineto +closepath +fill +298.55 240.57 1.000000 4n +307.82 240.57 1.000000 dot +294.87 239.82 moveto +294.87 219.57 lineto stroke +352.80 225.57 1.000000 8rest +371.19 237.57 1.000000 4n +367.51 236.82 moveto +367.51 218.07 lineto stroke +395.20 237.57 1.000000 4n +391.52 236.82 moveto +391.52 218.07 lineto stroke +newpath +367.16 219.57 moveto +391.87 219.57 lineto +391.87 216.57 lineto +367.16 216.57 lineto +closepath +fill +304.59 260.67 moveto +304.57 260.88 lineto +309.11 262.47 313.78 263.00 318.57 262.47 curveto +323.35 261.94 327.79 260.41 331.88 257.88 curveto +331.75 257.47 lineto +327.52 259.47 323.08 260.73 318.43 261.24 curveto +313.78 261.76 309.17 261.50 304.60 260.46 curveto +fill +/Times-Roman findfont +12 scalefont +setfont +322.78 275.58 moveto +331.82 275.58 1.000000 ferm +340.85 275.58 moveto +restore +% S_BAR +183 linenum +0.70 setlinewidth +417.31 351.84 moveto +417.31 225.57 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +184 linenum +450.98 290.12 moveto +480.84 290.12 lineto stroke +/Times-Roman findfont +12 scalefont +setfont +424.41 290.12 moveto +(land) show +/Times-Roman findfont +12 scalefont +setfont +494.41 290.12 moveto +(of) show +/Times-Roman findfont +12 scalefont +setfont +514.14 290.12 moveto +(the) show +431.05 336.84 1.000000 4n +440.32 336.84 1.000000 dot +434.73 337.59 moveto +434.73 357.84 lineto stroke +476.81 339.84 1.000000 4n +480.49 340.59 moveto +480.49 360.84 lineto stroke +483.52 360.84 1.000000 dnflag +496.89 342.84 1.000000 4n +500.57 343.59 moveto +500.57 362.92 lineto stroke +517.79 345.84 1.000000 4n +521.48 346.59 moveto +521.48 365.92 lineto stroke +newpath +500.22 364.42 moveto +521.83 367.42 lineto +521.83 364.42 lineto +500.22 361.42 lineto +closepath +fill +431.05 327.84 1.000000 4n +440.32 324.84 1.000000 dot +427.37 327.09 moveto +427.37 306.84 lineto stroke +476.81 327.84 1.000000 4n +473.13 327.09 moveto +473.13 306.84 lineto stroke +476.15 306.84 1.000000 upflag +496.89 327.84 1.000000 4n +493.21 327.09 moveto +493.21 308.34 lineto stroke +517.79 327.84 1.000000 4n +514.11 327.09 moveto +514.11 308.34 lineto stroke +newpath +492.86 309.84 moveto +514.46 309.84 lineto +514.46 306.84 lineto +492.86 306.84 lineto +closepath +fill +431.05 322.74 moveto +431.08 322.92 lineto +437.42 321.30 443.87 320.49 450.42 320.49 curveto +456.96 320.49 463.41 321.30 469.75 322.92 curveto +469.80 322.57 lineto +463.54 320.32 457.07 319.20 450.42 319.20 curveto +443.76 319.20 437.29 320.32 431.03 322.57 curveto +fill +445.32 341.94 moveto +445.26 342.14 lineto +450.12 344.69 455.29 346.22 460.75 346.74 curveto +466.21 347.26 471.57 346.73 476.83 345.14 curveto +476.80 344.75 lineto +471.52 345.77 466.21 346.03 460.87 345.52 curveto +455.52 345.01 450.35 343.76 445.37 341.75 curveto +fill +restore +% S_STAFF +% staff 2 +save +431.05 249.57 1.000000 4n +440.32 252.57 1.000000 dot +0.70 setlinewidth +434.73 250.32 moveto +434.73 270.57 lineto stroke +476.81 246.57 1.000000 4n +480.49 247.32 moveto +480.49 267.57 lineto stroke +483.52 267.57 1.000000 dnflag +496.89 249.57 1.000000 4n +500.57 250.32 moveto +500.57 269.07 lineto stroke +517.79 249.57 1.000000 4n +521.48 250.32 moveto +521.48 269.07 lineto stroke +newpath +500.22 270.57 moveto +521.83 270.57 lineto +521.83 267.57 lineto +500.22 267.57 lineto +closepath +fill +431.05 234.57 1.000000 4n +440.32 234.57 1.000000 dot +427.37 233.82 moveto +427.37 213.57 lineto stroke +476.81 240.57 1.000000 4n +473.13 239.82 moveto +473.13 219.57 lineto stroke +476.15 219.57 1.000000 upflag +496.89 228.57 1.000000 4n +493.21 227.82 moveto +493.21 208.49 lineto stroke +517.79 231.57 1.000000 4n +514.11 230.82 moveto +514.11 211.49 lineto stroke +newpath +492.86 209.99 moveto +514.46 212.99 lineto +514.46 209.99 lineto +492.86 206.99 lineto +closepath +fill +431.05 229.47 moveto +431.05 229.65 lineto +437.65 229.01 444.22 229.20 450.77 230.21 curveto +457.31 231.23 463.63 233.04 469.73 235.64 curveto +469.83 235.30 lineto +463.91 232.08 457.62 229.96 450.97 228.93 curveto +444.31 227.89 437.67 228.02 431.05 229.30 curveto +fill +445.32 254.67 moveto +445.30 254.87 lineto +450.56 256.46 455.91 256.99 461.38 256.47 curveto +466.84 255.95 472.00 254.42 476.86 251.87 curveto +476.76 251.48 lineto +471.77 253.48 466.61 254.74 461.26 255.25 curveto +455.91 255.76 450.60 255.50 445.33 254.47 curveto +fill +restore +% S_BAR +190 linenum +0.70 setlinewidth +539.91 351.84 moveto +539.91 225.57 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +192 linenum +/Times-Roman findfont +12 scalefont +setfont +547.50 290.12 moveto +(free) show +/Times-Roman findfont +12 scalefont +setfont +614.27 290.12 moveto +(and) show +/Times-Roman findfont +12 scalefont +setfont +644.33 290.12 moveto +(the) show +552.14 348.84 1.000000 4n +555.82 349.59 moveto +555.82 369.84 lineto stroke +587.85 351.84 1.000000 4rest +618.59 336.84 1.000000 4n +622.28 337.59 moveto +622.28 356.76 lineto stroke +647.98 339.84 1.000000 4n +651.66 340.59 moveto +651.66 359.76 lineto stroke +newpath +621.93 358.26 moveto +652.01 361.26 lineto +652.01 358.26 lineto +621.93 355.26 lineto +closepath +fill +552.14 327.84 1.000000 4n +548.46 327.09 moveto +548.46 306.84 lineto stroke +587.85 321.84 1.000000 4rest +618.59 324.84 1.000000 4n +614.91 324.09 moveto +614.91 305.34 lineto stroke +647.98 324.84 1.000000 4n +644.30 324.09 moveto +644.30 305.34 lineto stroke +newpath +614.56 306.84 moveto +644.65 306.84 lineto +644.65 303.84 lineto +614.56 303.84 lineto +closepath +fill +/Times-Roman findfont +12 scalefont +setfont +543.10 371.85 moveto +552.14 371.85 1.000000 ferm +561.18 371.85 moveto +restore +% S_STAFF +% staff 2 +save +552.14 249.57 1.000000 4n +0.70 setlinewidth +555.82 250.32 moveto +555.82 270.57 lineto stroke +587.85 261.57 1.000000 4rest +618.59 249.57 1.000000 4n +622.28 250.32 moveto +622.28 269.07 lineto stroke +647.98 249.57 1.000000 4n +651.66 250.32 moveto +651.66 269.07 lineto stroke +newpath +621.93 270.57 moveto +652.01 270.57 lineto +652.01 267.57 lineto +621.93 267.57 lineto +closepath +fill +552.14 234.57 1.000000 4n +548.46 233.82 moveto +548.46 213.57 lineto stroke +587.85 225.57 1.000000 4rest +618.59 243.57 1.000000 4n +614.91 242.82 moveto +614.91 224.07 lineto stroke +647.98 243.57 1.000000 4n +639.53 243.57 1.000000 nat +644.30 242.82 moveto +644.30 224.07 lineto stroke +newpath +614.56 225.57 moveto +644.65 225.57 lineto +644.65 222.57 lineto +614.56 222.57 lineto +closepath +fill +/Times-Roman findfont +12 scalefont +setfont +543.10 272.58 moveto +552.14 272.58 1.000000 ferm +561.18 272.58 moveto +restore +% S_BAR +198 linenum +0.70 setlinewidth +670.10 351.84 moveto +670.10 225.57 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +199 linenum +/Times-Roman findfont +12 scalefont +setfont +677.01 290.12 moveto +(home) show +/Times-Roman findfont +12 scalefont +setfont +727.06 290.12 moveto +(of) show +/Times-Roman findfont +12 scalefont +setfont +749.28 290.12 moveto +(the) show +683.67 342.84 1.000000 4n +692.93 342.84 1.000000 dot +687.35 343.59 moveto +687.35 363.84 lineto stroke +729.54 345.84 1.000000 4n +733.23 346.59 moveto +733.23 366.84 lineto stroke +736.25 366.84 1.000000 dnflag +752.94 339.84 1.000000 4n +756.62 340.59 moveto +756.62 360.84 lineto stroke +683.67 327.84 1.000000 4n +692.93 324.84 1.000000 dot +679.99 327.09 moveto +679.99 306.84 lineto stroke +729.54 327.84 1.000000 4n +725.86 327.09 moveto +725.86 306.84 lineto stroke +728.89 306.84 1.000000 upflag +752.94 324.84 1.000000 4n +749.25 324.09 moveto +749.25 303.84 lineto stroke +restore +% S_STAFF +% staff 2 +save +683.67 249.57 1.000000 4n +692.93 252.57 1.000000 dot +0.70 setlinewidth +687.35 250.32 moveto +687.35 270.57 lineto stroke +729.54 249.57 1.000000 4n +733.23 250.32 moveto +733.23 270.57 lineto stroke +736.25 270.57 1.000000 dnflag +752.94 246.57 1.000000 4n +756.62 247.32 moveto +756.62 267.57 lineto stroke +683.67 240.57 1.000000 4n +692.93 240.57 1.000000 dot +679.99 239.82 moveto +679.99 219.57 lineto stroke +729.54 240.57 1.000000 4n +725.86 239.82 moveto +725.86 219.57 lineto stroke +728.89 219.57 1.000000 upflag +752.94 240.57 1.000000 4n +749.25 239.82 moveto +749.25 219.57 lineto stroke +restore +% S_BAR +205 linenum +0.70 setlinewidth +787.49 351.84 moveto +787.49 225.57 lineto stroke +% S_CHHEAD +% S_STAFF +% staff 1 +save +206 linenum +/Times-Roman findfont +12 scalefont +setfont +796.68 290.12 moveto +(brave?) show +804.65 336.84 1.000000 2n +808.55 337.59 moveto +808.55 357.84 lineto stroke +804.65 321.84 1.000000 2n +798.21 321.84 moveto +811.10 321.84 lineto stroke +800.76 321.09 moveto +800.76 300.84 lineto stroke +restore +% S_STAFF +% staff 2 +save +804.65 240.57 1.000000 2n +0.70 setlinewidth +808.55 241.32 moveto +808.55 261.57 lineto stroke +804.65 228.57 1.000000 2n +800.76 227.82 moveto +800.76 207.57 lineto stroke +restore +% S_BAR +211 linenum +0.70 setlinewidth +864.04 351.84 moveto +864.04 225.57 lineto stroke +3.00 setlinewidth +868.04 351.84 moveto +868.04 225.57 lineto stroke +0.70 setlinewidth +% Printing header/footer +/Times-Roman findfont +18 scalefont +setfont +376.16 1148.50 moveto +(The Star Spangled Banner) show +/Times-Italic findfont +12 scalefont +setfont +381.99 1135.68 moveto +(\(The United States National Anthem\)) show +/Times-Roman findfont +9 scalefont +setfont +72.00 1126.07 moveto +(Text: Francis Scott Key) show +/Times-Roman findfont +9 scalefont +setfont +807.22 1126.07 moveto +(Tune: J. S. Smith) show +/Times-Roman findfont +9 scalefont +setfont +72.00 1116.46 moveto +/Times-Roman findfont +9 scalefont +setfont +790.16 1116.46 moveto +(arr: William J. Krauss) show +showpage +restore +%%DocumentFonts: /Times-Roman /Times-Italic /NewCenturySchlbk-Bold +%%Pages: 2 +%%EndDocument +end PEND EP +%%Page: 162 168 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(62 -)-2.5 E(INDEX)269.786 98 +Q(abo)69.336 122 Q -1.28 -.15(ve .)-.15 H(.............................\ +.......................................................................\ +............................33, 43, 71, 73, 78, 80).15 E -2.43(accents \ +.......................................................................\ +.......................................................................\ +...22,)69.336 134 R(65, 67)2.5 E -2.43(accidentals ....................\ +.......................................................................\ +................................17,)69.336 146 R(20, 63, 121, 135)2.5 E +(adjusting output)69.336 158 Q(........................................\ +.......................................................................\ +.............................129)2.27 E(alignment of lyrics)69.336 170 Q +(......................................................................\ +....................................................48, 113, 129)1.45 E +(alignment of te)69.336 182 Q -1.18(xt ................................\ +.......................................................................\ +................................69,)-.15 F(75)2.5 E -.5(all ...........\ +.......................................................................\ +........................................................48,)69.336 194 R +(71, 74, 74, 151)2.5 E -.77(alternation ...............................\ +.......................................................................\ +.........................................32,)69.336 206 R(151)2.5 E -.22 +(analysis .............................................................\ +......................................................................7\ +4,)69.336 218 R(102, 105, 106)2.5 E(angle brack)69.336 230 Q -.38(ets .\ +.......................................................................\ +.............................................................20,)-.1 F +(46, 48)2.5 E(ar)69.336 242 Q(guments, command line)-.18 E(............\ +.......................................................................\ +............................11, 127, 150)1.08 E(Arkkra Enterprises) +69.336 254 Q(..........................................................\ +.......................................................................\ +.......155)1.19 E -1.88(backslash .....................................\ +.......................................................................\ +.......................................13,)69.336 266 R(95)2.5 E -1.59(\ +backspace .............................................................\ +.......................................................................\ +..............63,)69.336 278 R(69)2.5 E -.77(bar ......................\ +.......................................................................\ +........2,)69.336 290 R(8, 13, 15, 37, 72, 84, 85, 103, 110, 138)2.5 E +-2.16(barstyle ........................................................\ +.......................................................................\ +...................103,)69.336 302 R(110)2.5 E -2.44(beaming ..........\ +.......................................................................\ +....................................................21,)69.336 314 R +(27, 105, 138)2.5 E -1.05(beamstyle ...................................\ +.......................................................................\ +........................27,)69.336 326 R(28, 105, 138)2.5 E -1.05(beats\ + ......................................................................\ +......................................................22,)69.336 338 R +(72, 72, 105, 135, 152)2.5 E(be)69.336 350 Q -.35(gintime .............\ +.......................................................................\ +..............................71,)-.15 F(72, 72, 78, 79, 80, 151)2.5 E +(belo)69.336 362 Q .31(w.)-.25 G(......................................\ +.......................................................................\ +...............6, 17, 33, 43, 71, 78, 80)-.31 E -2.44(bend ............\ +.......................................................................\ +.......................................................................\ +.......53)69.336 374 R -1.32(between ..................................\ +.......................................................................\ +......................................43,)69.336 386 R(71, 73)2.5 E -.22 +(block ................................................................\ +...........................................................14,)69.336 +398 R(14, 88, 106, 141, 145)2.5 E -.78(bold ...........................\ +..............................................................68,)69.336 +410 R(71, 73, 74, 86, 102, 105, 106, 109, 110, 113)2.5 E -1.06(boldital\ + ......................................................................\ +......................68,)69.336 422 R +(71, 73, 74, 86, 102, 105, 106, 109, 110)2.5 E -1.34 +(bottom ...........................4,)69.336 434 R(13, 13, 14, 14, 16, \ +43, 71, 72, 73, 82, 84, 84, 89, 93, 103, 106, 121, 123, 125, 150)2.5 E +(bottommar)69.336 446 Q -1.99(gin .....................................\ +.......................................................................\ +....................................106)-.18 F(box)69.336 458 Q(ed te) +-.15 E -2.14(xt .......................................................\ +.......................................................................\ +..........................70)-.15 F -2.15(brace .......................\ +.......................................................................\ +..........................................33,)69.336 470 R +(107, 110, 112)2.5 E(brack)69.336 482 Q -2.33(et ......................\ +.......................................................................\ +..............21,)-.1 F(24, 33, 44, 107, 110, 112, 136)2.5 E +(breath marks)69.336 494 Q(............................................\ +.......................................................................\ +...............................148).07 E -.2(cadenza ..................\ +.......................................................................\ +................................................................143) +69.336 506 R(cancelk)69.336 518 Q .07 -.15(ey .)-.1 H(.................\ +.......................................................................\ +.............................................................107).15 E +-1.88(capo ............................................................\ +.......................................................................\ +..............................54)69.336 530 R -2.43(center ............\ +.......................................................................\ +..........................................................13,)69.336 542 +R(45, 86, 95)2.5 E -1.6(channel .......................................\ +.......................................................................\ +....................................150,)69.336 554 R(152)2.5 E -2.16(c\ +hant ..................................................................\ +.......................................................................\ +...............48,)69.336 566 R(131)2.5 E -.77 +(chord .................................................2,)69.336 578 R +(15, 21, 34, 73, 74, 78, 80, 82, 102, 105, 106, 108, 110, 116, 121, 121) +2.5 E -.22(chorddist ..................................................\ +.......................................................................\ +74,)69.336 590 R(108, 109, 109, 129)2.5 E(circled te)69.336 602 Q -.06(\ +xt ....................................................................\ +.......................................................................\ +...........70)-.15 F -.49(clef ........................................\ +..................................................................3,) +69.336 614 R(8, 18, 25, 39, 40, 63, 108, 108, 121)2.5 E -1.88(coda ....\ +.......................................................................\ +.......................................................................\ +.......65,)69.336 626 R(150)2.5 E(command line ar)69.336 638 Q -1.42(gu\ +ments .................................................................\ +...............................................11,)-.18 F(127, 150)2.5 E +-1.61(comments ........................................................\ +.......................................................................\ +.............8,)69.336 650 R(13, 155)2.5 E(conte)69.336 662 Q -1.18(xts\ + ......................................................................\ +...........................................3,)-.15 F +(8, 14, 15, 89, 93, 102, 129)2.5 E(cop)69.336 674 Q -1.23(yright ......\ +.......................................................................\ +..............................................................14,)-.1 F +(65, 152)2.5 E -.48(crescendo .........................................\ +...................................................................71,) +69.336 686 R(76, 79, 102, 105, 106, 109)2.5 E(cross-staf)69.336 698 Q +2.5(fb)-.25 G -2.45(eams ..............................................\ +.......................................................................\ +................31,)-2.5 F(135)2.5 E(cross-staf)69.336 710 Q 2.5(fs)-.25 +G -2.18(tems ..........................................................\ +.......................................................................\ +.............25)-2.5 F(cue notes)69.336 722 Q(.........................\ +.......................................................................\ +.............................................21, 52, 67)2.01 E(curv) +69.336 734 Q 2.44(e.)-.15 G(...........................................\ +.......................................................................\ +..........................13, 46, 84, 91)-2.44 E EP +%%Page: 163 169 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(63 -)-2.5 E(custom beaming) +69.336 96 Q(...........................................................\ +.....................................................................27\ +, 54, 105)1.17 E(dashed line)69.336 108 Q(.............................\ +.......................................................................\ +................................37, 76, 80, 90)1.73 E +(dashed ties and slurs)69.336 120 Q(...................................\ +.......................................................................\ +...........19, 20, 27, 27)2.01 E(deb)69.336 132 Q -.02(ugging .........\ +.......................................................................\ +.................................................................8,)-.2 +F(129)2.5 E -2.42(decrescendo .........................................\ +......................................................................7\ +1,)69.336 144 R(79, 102, 105, 106, 109)2.5 E -2.44(de\214ne ...........\ +.......................................................................\ +.......................................................................\ +......95)69.336 156 R -.49(defoct .....................................\ +.......................................................................\ +....................................18,)69.336 168 R(25, 108)2.5 E +(diacritical marks)69.336 180 Q(.......................................\ +.......................................................................\ +................................69).07 E(diamond-shaped notes)69.336 192 +Q(.....................................................................\ +...................................................21, 52, 64)2.29 E +-2.45(diminished ......................................................\ +.......................................................................\ +....65,)69.336 204 R(74, 102, 126)2.5 E -2.45(dist ....................\ +.......................................................................\ +......................................................109,)69.336 216 R +(109, 129)2.5 E(di)69.336 228 Q -2.48(vision ..........................\ +.......................................................................\ +.........................................................109)-.25 F +(dotted line)69.336 240 Q(.............................................\ +.......................................................................\ +.......................37, 84, 90)2 E(dotted note)69.336 252 Q(........\ +.......................................................................\ +...............16, 21, 33, 43, 65, 105, 116, 125, 135)2.28 E +(dotted ties and slurs)69.336 264 Q(...................................\ +.......................................................................\ +............19, 20, 27, 27)2.28 E(drum clef)69.336 276 Q(..............\ +.......................................................................\ +..........................................................108, 121).9 E +(D. S.)69.336 288 Q(...................................................\ +.......................................................................\ +..............................65, 150)1.72 E -1.33(duration ...........\ +.......................................................................\ +...........13,)69.336 300 R(15, 27, 71, 76, 77, 78, 79, 80, 81, 105)2.5 +E -1.33(dynamics ......................................................\ +...................................................1,)69.336 312 R +(14, 48, 71, 102, 105, 106, 151)2.5 E -1.05(east ......................\ +.......................................................................\ +.....................................................................84) +69.336 324 R -1.61(endings ............................................\ +.......................................................................\ +...........40,)69.336 336 R(74, 102, 110, 150)2.5 E -1.61(endingstyle .\ +.......................................................................\ +........................................................40,)69.336 348 R +(40, 110, 114)2.5 E(error messages)69.336 360 Q(.......................\ +.......................................................................\ +........................4, 6, 102, 126, 129)2.3 E -2.15 -.25(ev e)69.336 +372 T 2.5(np).25 G -1.75(ages .........................................\ +.......................................................................\ +.................................9,)-2.5 F(140)2.5 E(\214gured bass) +69.336 384 Q(..........................................................\ +.............................................................69, 74, 10\ +2, 105, 106)1.45 E -1.89(\215ags ......................................\ +.......................................................................\ +......................................21,)69.336 396 R(63, 105)2.5 E +-.78(\215at ...........................................................\ +............................................................3,)69.336 +408 R(4, 17, 63, 74, 102, 112, 126)2.5 E -1.61(font ...................\ +.......................................................................\ +..........5,)69.336 420 R(22, 40, 48, 68, 71, 74, 86, 95, 110, 113)2.5 E +(fontf)69.336 432 Q -.12(amily ........................................\ +.......................................................................\ +..............22,)-.1 F(48, 74, 95, 110)2.5 E -1.88(footer ............\ +.......................................................................\ +......................................5,)69.336 444 R +(10, 84, 89, 93, 110, 121)2.5 E -1.88(fret ............................\ +.......................................................................\ +................................................................51) +69.336 456 R -1.61(Ghostscript ........................................\ +.......................................................................\ +.............................6,)69.336 468 R(11, 68)2.5 E -.78(glissand\ +o .....................................................................\ +.......................................................................\ +.............90)69.336 480 R(grace notes)69.336 492 Q(.................\ +.......................................................................\ +....................................21, 22, 52, 72, 151)1.74 E -.5(grid\ +s .....................................................................\ +.......................................................................\ +......14,)69.336 504 R(76, 110)2.5 E -1.33(guitar .....................\ +.......................................................................\ +...........................................................50,)69.336 +516 R(147)2.5 E -2.15(header ..........................................\ +.......................................................................\ +.5,)69.336 528 R(10, 14, 84, 89, 93, 110, 121)2.5 E -2.16(heel. .......\ +.......................................................................\ +.......................................................................\ +..........148)69.336 540 R -2.43(hidechanges ..........................\ +.......................................................................\ +....................................................41)69.336 552 R +-1.88(ifdef ...........................................................\ +.......................................................................\ +.......................96,)69.336 564 R(151)2.5 E(impro)69.336 576 Q +-.91(visation .........................................................\ +.......................................................................\ +................147)-.15 F -2.44(include ..............................\ +.......................................................................\ +..................................................9,)69.336 588 R(100) +2.5 E(in)69.336 600 Q -2.32(visbar ....................................\ +.......................................................................\ +.........................................37,)-.4 F(129)2.5 E -1.89(ital\ +ics ...................................................................\ +........48,)69.336 612 R +(68, 71, 73, 74, 80, 86, 102, 105, 106, 109, 110, 113)2.5 E -.23(justi\ +\214cation ............................................................\ +.......................................................................\ +..............5,)69.336 624 R(86)2.5 E -.1(ke)69.336 636 S 2.5(ys)-.05 G +-1.35(ignature ........................................................\ +.....................3,)-2.5 F +(8, 39, 41, 102, 102, 112, 121, 121, 126, 126)2.5 E -1.33(labels ......\ +.......................................................................\ +......................................................40,)69.336 648 R +(40, 69, 107, 112)2.5 E(leftmar)69.336 660 Q -1.98(gin ................\ +.......................................................................\ +.................................................93,)-.18 F(113, 140)2.5 +E(le)69.336 672 Q -.05(ga)-.15 G -2.24(to .............................\ +.......................................................................\ +.....................................................22,).05 F(65)2.5 E +-.5(length ............................................................\ +.......................................................................\ +...................23,)69.336 684 R(123)2.5 E -.5(line ................\ +.......................................................................\ +.......................................................13,)69.336 696 R +(84, 90, 138)2.5 E -.22(lyrics ........................................\ +...........................................................5,)69.336 708 +R(14, 14, 43, 69, 74, 102, 105, 106, 113)2.5 E -.22(lyricsalign .......\ +.......................................................................\ +.........................................................48,)69.336 720 +R(113, 129)2.5 E -1.88(macros .........................................\ +.......................................................................\ +.............................8,)69.336 732 R(9, 95, 150)2.5 E EP +%%Page: 164 170 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(64 -)-2.5 E +(manual placement)69.336 96 Q(.........................................\ +.......................................................................\ +.....46, 90, 135, 135)1.46 E -.22(map .................................\ +.......................................................................\ +.........................................................34)69.336 108 R +(mar)69.336 120 Q -1.15(gin ...........................................\ +............................................................84,)-.18 F +(86, 106, 113, 119, 126, 129, 140)2.5 E -1.32 +(measure .....................2,)69.336 132 R(8, 15, 17, 18, 19, 24, 27\ +, 37, 42, 47, 69, 72, 82, 85, 93, 105, 110, 114, 125, 138, 152)2.5 E +(measure numbers)69.336 144 Q(.........................................\ +.......................................................................\ +......40, 41, 110, 114)1.74 E(measure repeat)69.336 156 Q(.............\ +.......................................................................\ +......................................................17, 65)1.75 E +(measure rest)69.336 168 Q(............................................\ +.......................................................................\ +...........................17, 42)1.74 E -.77(MIDI ....................\ +.......................................................................\ +..............1,)69.336 180 R(9, 18, 50, 109, 112, 121, 135, 150)2.5 E +(mid-measure parameter changes)69.336 192 Q(...........................\ +.......................................................................\ +...................25).1 E -1.33(mordent ..............................\ +.......................................................................\ +......................................................64)69.336 204 R +-1.61(mouse ...........................................................\ +.......................................................................\ +............................12)69.336 216 R -.78(MS-DOS ...............\ +.......................................................................\ +...........................................................1,)69.336 228 +R(7, 11)2.5 E -1.06(multirest .........................................\ +.......................................................................\ +................................8,)69.336 240 R(13, 42)2.5 E -2.45(mupd\ +isp ...................................................................\ +.......................................................................\ +.................11)69.336 252 R -1.89(mupprnt ........................\ +.......................................................................\ +............................................................11)69.336 +264 R(music conte)69.336 276 Q -1.18(xt ...............................\ +.......................................................................\ +........3,)-.15 F(14, 15, 84, 89, 95, 129)2.5 E -1.34(mussym ..........\ +.......................................................................\ +........................71,)69.336 288 R(73, 77, 90, 102, 105, 106, 151) +2.5 E(neutral clef)69.336 300 Q(.......................................\ +.......................................................................\ +..............................108, 121)1.74 E(ne)69.336 312 Q -.79(wpag\ +e .....................................................................\ +.......................................................................\ +13,)-.25 F(93, 129)2.5 E(ne)69.336 324 Q -.51(wscore ..................\ +.......................................................................\ +..................................................13,)-.25 F(93, 129)2.5 +E -1.61(north .........................................................\ +.......................................................................\ +................................84)69.336 336 R -1.61(notes ....2,) +69.336 348 R(8, 14, 16, 19, 33, 42, 45, 48, 63, 67, 72, 72, 80, 84, 84,\ + 85, 105, 108, 109, 116, 128, 135, 150, 151)2.5 E(numbering pages)69.336 +360 Q(.................................................................\ +......................................................................1\ +0, 94).9 E(octa)69.336 372 Q -.95 -.15(ve .)-.2 H(.....................\ +..................................................................2, 17\ +, 20, 71, 80, 102, 102, 105, 108, 126, 151).15 E(odd pages)69.336 384 Q +(......................................................................\ +.......................................................................\ +.....9, 140)1.73 E -2.16(ornaments ....................................\ +.......................................................................\ +...............................64,)69.336 396 R(71, 151)2.5 E(pack) +69.336 408 Q -.15(ex)-.1 G 1.43(p.).15 G(..............................\ +.......................................................................\ +...........................................116, 129)-1.43 E(packf)69.336 +420 Q -1.77(act .......................................................\ +.......................................................................\ +...................116,)-.1 F(129)2.5 E -.22(padding ..................\ +.......................................................................\ +....................................................23,)69.336 432 R +(39, 135)2.5 E(page footer)69.336 444 Q(...............................\ +.......................................................................\ +..........5, 10, 84, 89, 93, 110, 121)1.74 E(page header)69.336 456 Q(.\ +.......................................................................\ +.................................5, 10, 14, 84, 89, 93, 110, 121)1.47 E +-1.88(pageheight ......................................................\ +.......................................................................\ +........................117)69.336 468 R(page number)69.336 480 Q(.....\ +.......................................................................\ +..................................................................10, 9\ +4).07 E(page)69.336 492 Q -1.91(width .................................\ +.......................................................................\ +..............................................117)-.25 F -.48(paragraph\ + ......................................................................\ +.......................................................................\ +...........87)69.336 504 R -1.87(parameters ...........................\ +.......................................................................\ +.............3,)69.336 516 R(13, 14, 96, 102, 129, 152)2.5 E -2.15(pare\ +ntheses ...............................................................\ +.......................................................................\ +....16,)69.336 528 R(17, 51)2.5 E -2.16(pedal .........................\ +.......................................................................\ +........................5,)69.336 540 R(64, 71, 81, 105, 117, 151)2.5 E +-1.33(pedstyle ........................................................\ +.......................................................................\ +....................81,)69.336 552 R(117)2.5 E -.77(percussion ........\ +.......................................................................\ +......................................................................1\ +21)69.336 564 R -1.6(phrase ...........................................\ +.......................................................................\ +............................5,)69.336 576 R(14, 71, 78)2.5 E +(piano reduction)69.336 588 Q(.........................................\ +.......................................................................\ +.............................145)2.01 E(pickup measure)69.336 600 Q(...\ +.......................................................................\ +...........................................................4, 10, 16) +1.46 E(piled te)69.336 612 Q -.35(xt ..................................\ +.......................................................................\ +..........................................69,)-.15 F(75)2.5 E -.5(pitch\ + ......................................................................\ +..........................................2,)69.336 624 R +(16, 17, 18, 18, 19, 20, 26, 121)2.5 E -1.62(PostScript ...............\ +.......................................................................\ +....................................................1,)69.336 636 R +(6, 11, 68)2.5 E -1.89(print ..........................................\ +...................................1,)69.336 648 R +(6, 7, 11, 13, 72, 84, 86, 110, 121, 121, 125, 127, 135)2.5 E -1.06(quo\ +ting ..................................................................\ +.......................................................................\ +...................97)69.336 660 R -.77(reduction .....................\ +.......................................................................\ +...........................................................145)69.336 +672 R(re)69.336 684 Q -.9(gistration ..................................\ +.......................................................................\ +.........................................1,)-.15 F(10)2.5 E +(rehearsal marks)69.336 696 Q(.........................................\ +........................................................40, 74, 102, 11\ +0, 114, 118, 151)1.47 E -.76(release ..................................\ +.......................................................................\ +....................................................25)69.336 708 R +-2.43(repeat ..........................................................\ +.......................................................................\ +..33,)69.336 720 R(37, 65, 147, 150)2.5 E -2.44(rest ..................\ +.......................................................................\ +..........................8,)69.336 732 R +(16, 18, 22, 42, 45, 64, 85, 128)2.5 E EP +%%Page: 165 171 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(65 -)-2.5 E -.49(restart ..\ +.......................................................................\ +.......................................................................\ +..............37)69.336 96 R(rightmar)69.336 108 Q -.04(gin ...........\ +.......................................................................\ +...................................................93,)-.18 F(119, 140) +2.5 E -1.89(roll ......................................................\ +.......................................................................\ +................................81,)69.336 120 R(90)2.5 E -1.05(roman .\ +.......................................................................\ +..........40,)69.336 132 R +(48, 68, 71, 73, 74, 86, 102, 105, 106, 110, 113)2.5 E -.49(scale .....\ +.......................................................................\ +.......................................................................\ +...119,)69.336 144 R(129)2.5 E -1.6 +(score ..................................1,)69.336 156 R(3, 4, 5, 8, 14\ +, 39, 40, 48, 49, 74, 93, 95, 102, 107, 112, 114, 120, 128, 151, 155)2.5 +E -1.04(scorepad ......................................................\ +.......................................................................\ +...................120,)69.336 168 R(129)2.5 E -2.43(scoresep .........\ +.......................................................................\ +.......................................................................\ +..121)69.336 180 R -.5(scrolling ......................................\ +.......................................................................\ +.............................................11)69.336 192 R -1.61(semi\ +colon .................................................................\ +.....................................2,)69.336 204 R +(13, 15, 21, 33, 43, 72, 102, 129)2.5 E(shaped notes)69.336 216 Q(.....\ +.......................................................................\ +..............................................14, 20, 22, 56, 114).62 E +(share)69.336 228 Q -.1(wa)-.25 G -.68(re .............................\ +.......................................................................\ +................................................1,).1 F(10)2.5 E -2.16(\ +sharp .................................................................\ +...................................................3,)69.336 240 R +(4, 17, 63, 74, 102, 112, 126)2.5 E -1.05(size ........................\ +......................................................................5\ +,)69.336 252 R(22, 40, 48, 68, 68, 74, 78, 86, 86, 113, 121)2.5 E -.5(s\ +lash ..................................................................\ +............................................7,)69.336 264 R +(22, 22, 33, 52, 70, 75, 147, 151)2.5 E -1.89(slide ...................\ +.......................................................................\ +.......................................................................\ +52)69.336 276 R -1.61(slope ...........................................\ +.......................................................................\ +......................................32,)69.336 288 R(103)2.5 E -.5(sl\ +ur ....................................................................\ +.......................................................................\ +.................20,)69.336 300 R(27)2.5 E -2.17(small ................\ +.......................................................................\ +.......................................................11,)69.336 312 R +(19, 21, 67)2.5 E -2.17(south .........................................\ +.......................................................................\ +................................................84)69.336 324 R -.21 +(space ...........................................................2,) +69.336 336 R +(4, 8, 13, 16, 18, 23, 39, 45, 47, 47, 68, 116, 120, 122, 128, 135)2.5 E +-.2(spacing ...........................................................\ +.......................................................................\ +........\(see)69.336 348 R(padding\))2.5 E -.21(staccato ..............\ +.......................................................................\ +......................................................................2\ +2)69.336 360 R(staf)69.336 372 Q 1.98(f.)-.25 G(....................13,\ + 14, 15, 43, 48, 69, 71, 74, 81, 82, 84, 102, 107, 108, 110, 112, 122, \ +122, 127, 150, 151)-1.98 E(staf)69.336 384 Q 2.5(fp)-.25 G -.23(aper ..\ +.......................................................................\ +.......................................................................\ +.....149)-2.5 F(staf)69.336 396 Q -1.36(\215ines ......................\ +.......................................................................\ +.....................................................50,)-.25 F(121)2.5 +E(staf)69.336 408 Q -2.46(fpad ........................................\ +.......................................................................\ +...................................122,)-.25 F(129)2.5 E(staf)69.336 420 +Q -1.35(fsep ..........................................................\ +.......................................................................\ +.................123,)-.25 F(129)2.5 E -1.89(stem .....................\ +.......................................................................\ +.....................................22,)69.336 432 R +(22, 32, 63, 84, 128)2.5 E(stem direction)69.336 444 Q(................\ +.......................................................................\ +.......................................22, 22, 31, 127).06 E +(stem length)69.336 456 Q(.............................................\ +.......................................................................\ +..........................23, 123).61 E -2.16(stepsize ................\ +..........................................................13,)69.336 468 +R(23, 39, 85, 108, 109, 109, 120, 121, 122, 123, 135)2.5 E -2.17(string\ +s ............................................................14,)69.336 +480 R(22, 22, 22, 40, 40, 44, 67, 72, 80, 86, 95, 107, 110, 112, 121)2.5 +E -.78(strum ..........................................................\ +.......................................................................\ +............................147)69.336 492 R -.77(subscript/superscript\ + ......................................................................\ +.................................................................69) +69.336 504 R(swing time)69.336 516 Q(..................................\ +.......................................................................\ +....................................124, 151).33 E -1.61(syllable .....\ +.......................................................................\ +.......................................................................\ +.....5,)69.336 528 R(43)2.5 E -1.9(sylposition ........................\ +.......................................................................\ +................................................49,)69.336 540 R(124)2.5 +E -.49(tablature ......................................................\ +.......................................................................\ +...............50,)69.336 552 R(79, 121)2.5 E -.22(tag ................\ +.......................................................................\ +..................................................21,)69.336 564 R +(23, 39, 84, 135)2.5 E -.5(tempo ......................................\ +.......................................................................\ +.............................1,)69.336 576 R(14, 151, 152)2.5 E(te) +69.336 588 Q(xt strings)-.15 E(........................................\ +.............14, 22, 22, 22, 40, 40, 44, 67, 72, 80, 86, 95, 107, 110, \ +112, 121).48 E -.5(tie ................................................\ +.......................................................................\ +.................................19,)69.336 600 R(26, 52)2.5 E -1.34(ti\ +l .....................................................................\ +.......................................................................\ +.........................73)69.336 612 R -.78(time ....................\ +.................................................................2,) +69.336 624 R(15, 21, 32, 33, 43, 63, 71, 72, 85, 105, 116, 125)2.5 E +(time signature)69.336 636 Q(..........................................\ +............................3, 8, 15, 17, 39, 40, 41, 72, 85, 121, 125,\ + 138, 150).06 E -1.34(timeunit ........................................\ +.......................................................................\ +....................................16,)69.336 648 R(125)2.5 E -1.06(ti\ +tle ...................................................................\ +.......................................................................\ +........5,)69.336 660 R(13, 14, 86)2.5 E -.22(toe. ....................\ +.......................................................................\ +.....................................................................14\ +8)69.336 672 R -.78 +(top ...............................................13,)69.336 684 R(14\ +, 43, 71, 72, 73, 82, 84, 84, 89, 93, 103, 106, 110, 121, 123, 126, 150) +2.5 E(topmar)69.336 696 Q -1.43(gin ...................................\ +.......................................................................\ +............................................126)-.18 F -.77(transpose .\ +.......................................................................\ +.....................................50,)69.336 708 R +(54, 75, 102, 121, 126, 143)2.5 E -.49(track ..........................\ +.......................................................................\ +.............................................................150)69.336 +720 R -2.45(trill .....................................................\ +.......................................................................\ +...........................64,)69.336 732 R(77, 90)2.5 E EP +%%Page: 166 172 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 10/Times-Roman@0 SF 2.5(-1)272.006 48 S(66 -)-2.5 E -1.88(triplets \ +.......................................................................\ +.......................................................................\ +\(see)69.336 96 R(tuplets\))2.5 E -2.17(tuplets .......................\ +.......................................................................\ +........................................................33,)69.336 108 R +(135)2.5 E -1.61(turn .................................................\ +.......................................................................\ +..........................................64)69.336 120 R +(uncollapseable space)69.336 132 Q(....................................\ +.......................................................................\ +............................16).36 E -.77(undef .......................\ +.......................................................................\ +.................................................................96) +69.336 144 R -.77(underline ...........................................\ +.......................................................................\ +.......................................69)69.336 156 R -1.87(underscore\ + ......................................................................\ +...........................................................8,)69.336 168 +R(45, 69, 76, 95)2.5 E -2.45(units ....................................\ +.......................................................................\ +....................................................126)69.336 180 R +-.49(UNIX .............................................................\ +.......................................................................\ +......................8,)69.336 192 R(11)2.5 E -.15(ve)69.336 204 S -.07 +(locity ...............................................................\ +.......................................................................\ +...................152).15 F -.15(ve)69.336 216 S -1.45(rse ...........\ +.......................................................................\ +............................................................5,).15 F +(44, 69, 145)2.5 E -2.17(visible ......................................\ +..........................................................8,)69.336 228 +R(8, 8, 43, 50, 71, 84, 103, 110, 122, 127)2.5 E -.2(vo)69.336 240 S +-1.96(ice .............................................................\ +.................................4,).2 F +(14, 15, 15, 78, 82, 90, 102, 128, 135, 150)2.5 E -.78(with ...........\ +.......................................................................\ +.......................................................................\ +..22,)69.336 252 R(54)2.5 E -.15(ve)69.336 264 S(rtical motion).15 E(..\ +.......................................................................\ +.......................................................................\ +69)1.32 E -.49(vscheme ................................................\ +.......................................................................\ +...........................78,)69.336 276 R(128)2.5 E -.1(wa)69.336 288 +S(vy lines)-.1 E(......................................................\ +.......................................................................\ +....................76, 90)1.75 E -1.33(west ..........................\ +.......................................................................\ +................................................................84) +69.336 300 R(X-shaped notes)69.336 312 Q(..............................\ +.......................................................................\ +...............................21, 52, 64).07 E 69.336 324 EBEGIN +%-marker2- +EEND EP +%%Trailer +end +%%EOF diff --git a/mup/docs/uguide/adjust.html b/mup/docs/uguide/adjust.html new file mode 100644 index 0000000..0eec931 --- /dev/null +++ b/mup/docs/uguide/adjust.html @@ -0,0 +1,74 @@ + + +Adjusting Mup output + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Adjusting Output +

+

+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. +

+

+The "newscore" or "newpage" commands +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. +

+

+If you want to get a little more or less on each page, it is usually best +to start with changing the +scale, +staffscale, +packfact, +and/or +packexp +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: +scorepad, +scoresep, +staffpad, +and +staffsep. +

+

+The +dist, +dyndist, +and +chorddist +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. +

+

+The appearance of lyrics can be adjusted using the +lyricsfont, +lyricsfontfamily, +lyricssize, +and +lyricsalign +parameters. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/altinp.html b/mup/docs/uguide/altinp.html new file mode 100644 index 0000000..7bb143e --- /dev/null +++ b/mup/docs/uguide/altinp.html @@ -0,0 +1,177 @@ + + +Chord-at-a-time input style + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Chord-at-a-time input style +

+

+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. +

+

+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 +

+// 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 ]
+

+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. +

+

+Since voice 1 is, as always, the default, this could be written more +compactly as just: +

+[ 2; 2; 1; 1 ]
+

+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: +
+// Soprano
+//    Alto
+//       Tenor
+//          Bass
+[  1; 1; 2; 2 ]
+

+If you wanted to use two separate voices on each staff (going +back to bottom-to-top order), you could specify: +
+// 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  ]
+

+

+

+Now let's put these mappings with music data. +

+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
+

+Picture of Mup output
+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. +

+

+It is also possible to use rests or spaces for some of the voices. +

+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
+

+Picture of Mup output
+

+

+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. +

+[1 2; 1 1] : [cue; xnote; len 6] b-e; [with > ] ce& slur; dg~; c?g;
+

+Picture of Mup output
+

+

+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. +

+[ 1-3 1  &  1 2;  2-3 2 ] : ec;fd;ge;af;
+

+Picture of Mup output
+

+

+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. +

+// 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+;
+

+Picture of Mup output
+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. +

+

+Since the mapping specifications can get rather complex, +and they may be used many times during a song, +it is usually best to define +macros +for them, and possibly even put the macro definitions in +an "include" file. +

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/bars.html b/mup/docs/uguide/bars.html new file mode 100644 index 0000000..b674bca --- /dev/null +++ b/mup/docs/uguide/bars.html @@ -0,0 +1,348 @@ + + +Bar Lines + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Bar lines +

+

+Each measure must be ended with a "bar" of some kind. There are several kinds: + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Keyword Meaning
bar ordinary bar line
dblbar double bar
repeatstart beginning of repeated section
repeatboth end of one repeated section and beginning of another
repeatend end of repeated section
endbar heavy double bar line used at end of song
invisbar no bar line printed
restart end staffs and begin anew
+ +

+

+In addition, the bar and dblbar types can be preceded +by the word "dashed" or "dotted" to produce dashed or dotted bar lines. +

+

+

+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
+

+Picture of Mup output
+

+

+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: +

+(dblbar) repeatstart
+

+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. +

+

+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. +

+

+The restart is a special kind of bar. It follows immediately after another +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. +

+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
+

+Picture of Mup output
+

+

+There are several optional directives that can follow the bar line keyword. +They can be specified in any order and are described below. +

+

+Bar line padding +

+

+One optional directive is padding. +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: +

+dblbar pad 3
+

+would add 3 stepsizes of padding. +

+

+Bar line location tag +

+

+It is also possible to associate a +location tag +with a bar line. +For example: +

+// 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
+

+

+

+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. +

+

+Endings +

+

+First and second endings, etc. can be designated at bar lines. +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: +

+bar ending "1."
+repeatend ending "2-3"
+endbar endending
+

+

+

+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. +

+

+The "endingstyle" parameter +controls where endings are placed. +Endings cannot start at or cross over a restart bar. +

+

+Rehearsal marks +

+

+Rehearsal letters or numbers +can be specified on any bar line. There are four formats: +
+rehearsal let +
+rehearsal num +
+rehearsal mnum +
+rehearsal "label" +

+

+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: +

+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
+

+Picture of Mup output
+

+

+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 +clef, +key signature, +and +time signature. +The "endingstyle" parameter +is used to determine which staffs get rehearsal marks. +The "rehstyle" parameter +specifies whether to put rehearsal marks inside a box or a circle +or leave them plain. +

+

+The rehearsal keyword may be followed by a specification for fontfamily, +font, and/or (size). +Once specified, these remain in effect +for any future rehearsal marks, until explictly changed. Some examples: +

+bar rehearsal helvetica bold (14) let
+repeatend reh newcentury num
+invisbar reh rom (10) mnum
+

+

+

+After all the options listed above, you may specify "dist N" where +N is some number of stepsizes. This will override the +dist parameter +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. +

+rehearsal num dist 5     // at least 5 stepsizes away
+reh bold "A1" dist 2 !   // exactly 2 stepsizes away
+

+

+

+Setting the measure number +

+

+Mup keeps track of +measure numbers +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=number on a bar line, +which will set the current measure number to the given number. +

+// Set the current measure number to 50
+dblbar mnum=50
+

+

+

+Setting rehearsal letter or number +

+

+If you are using the "rehearsal let" or "rehearsal num" styles, +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. +

+

+The rehearsal number can be set on any bar line using num=N, where +N is a number, typically 1. +

+bar num=1
+

+The rehearsal letter can be set in a similar way, using let="X" where +X is either a single upper case letter, A to Z, or two upper case +letters, AA to ZZ. +
+dblbar let="A" reh let
+

+

+

+Hiding time/key signature and clef changes +

+

+Generally in printed music, when a +time signature +or key signature +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. +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/basics.html b/mup/docs/uguide/basics.html new file mode 100644 index 0000000..29981b6 --- /dev/null +++ b/mup/docs/uguide/basics.html @@ -0,0 +1,315 @@ + + +"Mup Basics" + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+MUP BASICS +

+

+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. +

+

+Notes and chords +

+

+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: +

+1:    4e; 4d; 2c;
+

+Picture of Mup output
+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. +

+

+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. +

+

+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. +

+

+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 +chord. +

+

+At the end of each measure, we have to tell Mup what kind of +bar line +to draw. The standard bar line is just called "bar." So a complete +description of the first measure would be: +

+1:    4e; 4d; 2c;
+bar
+

+

+

+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. +

+

+The same sort of idea works with pitches. The third measure of "Three Blind +Mice" could be stated like this: +

+1: 4g;8f;;2e;
+bar
+

+Picture of Mup output
+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. +

+

+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. +

+

+Parameters +

+

+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. +

+

+There is a long +list of "parameters" that can be set. +Things like clef +and key signature are among them. Parameters can be changed with a line of the +form: +

+parameter_name=value
+

+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: +
+score
+  time=6/8
+  key=2#
+
+music
+  1: 4d;8e;4f;8d;
+  bar
+

+Picture of Mup output
+

+

+Note that in this example, the key was specified as two sharps. +You can also specify the key by name: +

+  key = d major
+

+

+

+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 +"context." +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. +

+

+Here is a more complicated example: +

+score
+	staffs=2
+	key=3&
+	time=2/4
+
+music
+1: ceg;;
+2: 2c;
+bar
+

+Picture of Mup output
+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. +

+

+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. +

+

+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. +

+

+Some parameters can be set on a per-staff basis as well as for the entire +score. Mup also allows for +up to three independent voices on each staff, +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: +

+score
+	staffs=3
+	key=1&
+staff 2
+	key=2&
+	clef=bass
+music
+1: 2f;a;
+2: 2c;f;
+3: 1f;
+bar
+

+Picture of Mup output
+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). +The complete list of Mup parameters +includes +information about whether they can be set for an individual staff +or voice, or just for the score as a whole. +

+

+Page headers and footers +

+

+Mup allows you to specify a +header and/or footer +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 +"title" command +that can be used to create a canned format title. For example: +

+title "Three Blind Mice"
+

+will create a centered title. You can also get left and right justified titles. +

+

+Lyrics +

+

+You can specify +lyrics +for as many verses as you like. They are specified +somewhat like notes. As an example: +

+1: 4e;d;2c;
+lyrics 1: 4;;2; "Three blind mice,";
+bar
+

+Picture of Mup output
+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. +

+

+Miscellaneous +

+

+Mup provides a way to +print arbitrary text +(like "allegro") and +musical symbols +(like a fermata). It can also print +phrase marks, +piano pedal marks, +etc. The placement of these items is specified in terms +of "counts" into the measure. For example: +

+boldital below 1: 3 "mf";
+

+Picture of Mup output
+tells Mup to print "mf" in bold-italics below staff 1, at count 3 of the +measure. +You can also print +marks associated with specific chords. +All of these facilities are described in detail in following sections. +

+

+Displaying, printing, and playing music +

+

+Once you have an input file, you can run Mup on it to get the printed +version of the music. Entering: +

+mup myfile
+

+from a command line prompt or selecting Run > Display from Mupmate +will cause Mup to read myfile, which should contain text in the Mup +input language. If there are no errors in myfile, PostScript output +will be produced, which can be displayed on the screen or printed via +Mupmate or other programs. Mup can also produce +MIDI output, +which can then be played on your speakers. +

+

+If you are using Ghostscript, but without Mupmate, +two utility programs are included with Mup +for +displaying and printing music +using Ghostscript. +These are described in more detail in the next section. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/brackmac.html b/mup/docs/uguide/brackmac.html new file mode 100644 index 0000000..e1b8c60 --- /dev/null +++ b/mup/docs/uguide/brackmac.html @@ -0,0 +1,71 @@ + + +Bracketing notes across staffs + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Bracketing notes across staffs +

+

+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. +

+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
+

+Picture of Mup output
+

+

+Note that Mup supports +cross-staff stems, which is another way to notate a chord that is split +across two staffs, and may often be a better choice. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/breathmk.html b/mup/docs/uguide/breathmk.html new file mode 100644 index 0000000..5665ac1 --- /dev/null +++ b/mup/docs/uguide/breathmk.html @@ -0,0 +1,32 @@ + + +Breath marks + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Breath marks +

+

+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. +

+1: c;d;2e;
+rom (24) above all dist 0: 4.5 ",";
+bar
+
+1: e;d;2c;
+bar
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/cadenza.html b/mup/docs/uguide/cadenza.html new file mode 100644 index 0000000..8fb814a --- /dev/null +++ b/mup/docs/uguide/cadenza.html @@ -0,0 +1,35 @@ + + +Cadenzas + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Cadenzas +

+

+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 +tuplet +with the appropriate number of notes. +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/chant.html b/mup/docs/uguide/chant.html new file mode 100644 index 0000000..16a68c1 --- /dev/null +++ b/mup/docs/uguide/chant.html @@ -0,0 +1,92 @@ + + +Chant + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Chant +

+

+Here is an example that shows some techniques you might use when +writing chant. +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/chordinp.html b/mup/docs/uguide/chordinp.html new file mode 100644 index 0000000..5ad1a46 --- /dev/null +++ b/mup/docs/uguide/chordinp.html @@ -0,0 +1,393 @@ + + +Specifying chords + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Specifying chords +

+

+Staff and voice +

+

+The description of the music for one voice begins with the staff and voice +number, followed by a colon. For example: +

+3 1:
+

+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 +
+3:
+

+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: +
+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
+

+

+

+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: +

+1 1 & 3 2:
+

+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: +
+// 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:
+

+

+

+It is possible to have up to +40 +staffs +and up to +three voices per staff. +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 +tweak placement +when necessary. +

+

+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 +later. +

+

+Chord duration information +

+

+The rest of the line contains a list of chords, with a semicolon at the +end of each chord. Each chord has a +time value. +The time values of all +the chords in the line must add up to the +time signature. +Time values are given as follows: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Input Meaning
1/4 quadruple whole (not valid for notes)
1/2 double whole
1 whole
2 half
4 quarter
8 eighth
16 sixteenth
32 thirty-second
64 sixty-fourth
128 128th
256 256th
+ +

+

+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. +

+

+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. +

+

+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 +"timeunit" parameter +as described in the +"Parameters" section. +If that parameter is not set, the default is the denominator (bottom +number) of the +time signature. +For chords after the first, if a time value is not specified, the time +value for the previous chord is used. +

+

+Notes, rests, or spaces +

+

+There are three kinds of "chords." +The first type consists of one or more +pitches, given by the letters "a" through "g". +Parentheses +can be placed around the pitch if you want +the note to be printed in parentheses. +(If the pitch is modified by an +accidental +or +octave, +which will be +discussed later, those must also be included inside the parentheses.) +The second is a rest, which +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: +

+// a pickup measure
+1: 2.s;8.c;16d;
+bar
+1: e;g;e;c;
+endbar
+

+Picture of Mup output
+

+

+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. +

+

+If a given voice is omitted for a particular measure, +Mup defaults to a measure of space. +

+

+Measure duration +

+

+There is a special duration of "m," which means an entire measure. +It can only be used with a rest, space, or "rpt" (repeat). For example: +

+1 1: mr;
+1 2: ms;
+

+

+

+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. +

+4mr;   // use a quarter rest symbol
+1/4mr;  // use a quadruple whole rest symbol
+2.. mr;  // use a double-dotted half rest
+

+

+

+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 +numbermrpt parameter +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. +

+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
+

+Picture of Mup output
+

+

+Accidentals +

+

+Each pitch letter in a chord may be followed by an accidental. +Valid accidentals are: + + + + + + + + + + + + + + + + + + + +
Input Meaning
# sharp
& flat
x double sharp
&& double flat
n natural
+ +

+

+The accidental can be placed inside +parentheses if you want it to be printed +within parentheses. +

+

+Octave +

+

+An octave indicator may be specified after the pitch letter +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: +

+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
+

+

+

+The default octave can be set using the +"defoct" parameter, +which is described in the +"Parameters" section. +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 +clef. +In other words, the default octaves are: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Clef Octave
frenchviolin 5
8treble 5
treble 4
soprano 4
mezzosoprano 4
alto 4
treble8 3
tenor 3
baritone 3
bass 3
+ +

+

+Shorthand notations +

+

+If a chord is omitted, the values for the previous chord are reused. This +works for pitches, rests, and spaces. For normal, +5-line staffs, +the pitches for the first chord of every measure +must always be specified, since there is no previous chord. +

+

+Putting all these things together, here are some examples: +

+// 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+;
+

+Picture of Mup output
+

+

+For +1-line staffs, +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 +MIDI output. +If you don't specify a pitch, it is arbitrarily set to middle C. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/chrdattr.html b/mup/docs/uguide/chrdattr.html new file mode 100644 index 0000000..a6b76b1 --- /dev/null +++ b/mup/docs/uguide/chrdattr.html @@ -0,0 +1,392 @@ + + +Chord attributes + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Chord attributes +

+

+There are optional attributes that are associated with an entire chord +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: +

+

+

+Each class of information is +separated from the other by a semicolon. All classes are optional, and can +occur in any order. +

+

+Chord style +

+

+Several chord styles can be specified. +Grace note chords are designated by the word "grace," or cue note chords by "cue." +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 "prebend" in guitar music. +(Actually, you can force a stem if you want, by specifying a +len, as is described later.) +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. +

+

+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: +

+[grace]
+
+[xnote] +
+[cue; xnote] +
+[diam] +

+

+

+Head shape +

+

+If you want to have the +note heads in a chord +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 +section on shaped notes, +so only the basics are covered here. The xnote and diam +described above +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. +

+1: [hs "righttri"]cf; [hs "slash"]fa;
+

+

+

+The +section on shaped notes +lists all the builtin head shape names, +and explains how you can define your own. +

+

+Symbols to be printed with a chord +

+

+It is possible to specify one or more musical symbols or text strings to be printed with a chord. +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: + + + + + + + + + + + + + + + + +
Symbol Meaning
. staccato
- legato
> accent
^ accent
+ +

+

+A quoted string +can also be specified (e.g., "ff", "adagio", etc.). +This will be printed in the font and size specified by the +"fontfamily," +"font," +and +"size" +parameters. Any of the +special music characters can be printed by using the usual convention, +e.g., \(ferm) for a fermata. +(This is described in a +later section.) +However, it is usually preferable to use the printing of +text strings relative to beats. +

+

+Here are some examples: +

+[with ., -]
+[with ^, "\(ferm)"]
+[with "sfz"; cue]
+

+

+

+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. +

+

+Slashes +

+

+Diagonal lines to be drawn through the stem of the group +can be specified using +

+slash N
+

+where N is the number of slashes to draw. In the case of +grace notes, +N can only be 1, which will produce a grace note with a slash through it. +In the case of other notes, N can be 1 or greater, and is used to +specify tremolo or repetition of the note group. Examples: +
+[slash 2]
+[grace; slash 1]
+

+

+

+Stem direction +

+

+The chord stem direction can be specified as "up" or "down". +Normally Mup chooses the stem direction, but once in a while you +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 +alternation pair +(described later) +must have the same stem direction. +Examples: +

+[up]
+[down]
+

+

+

+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. +

+

+Stem len +

+

+Normally, Mup sets stem lengths as appropriate, but sometimes you might +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: +

+[ len 14 ]
+[ len 7; up ]
+

+

+

+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. +

+

+There is a +stemlen parameter +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. +

+

+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 +stemshorten parameter +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. +

+

+Padding +

+

+Sometimes it may be desirable to space notes somewhat differently than +Mup would normally place them. +It is possible to specify "padding" before any note group. +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: +

+[ pad 2.5 ]
+

+

+

+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. +

+

+Chord location tag +

+

+It is possible to set a location tag +which is +associated with an entire chord +rather than an individual note. This +tag +is specified like +location tags for notes, +with an "=" followed by a name, but is inside +the square brackets rather than after a note. +

+3: 2cf; [=h] egc+;
+1: [cue; with >; =_ch] fa;
+

+

+

+Horizontal offset +

+

+A horizontal offset can be applied to a chord by specifying "ho" followed +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. +

+

+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. +

+

+Here is an example of the use of horizontal offset and stem direction +on voice 3. +

+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
+

+Picture of Mup output
+

+

+Rest distance +

+

+Usually Mup's placement of rests is satisfactory, but once in a while +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 +transposed, +the placement of the rest symbol will be adjusted accordingly. +

+// 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
+

+Picture of Mup output
+

+

+Repeated attributes +

+

+If two or more chords in a row have the same bracketed attributes, +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: +

+1: [cue] 4c;[]d;[grace; slash 1] 8f;2e;
+bar
+
+1: d; [with .,-]d; []e; []f;
+bar
+

+Picture of Mup output
+

+

+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. +

+// 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
+

+Picture of Mup output
+

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/cmdargs.html b/mup/docs/uguide/cmdargs.html new file mode 100644 index 0000000..0e9c601 --- /dev/null +++ b/mup/docs/uguide/cmdargs.html @@ -0,0 +1,409 @@ + + +Mup Options + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Mup Options +

+

+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: +


+Command line:  +-c N +
+Mupmate:       +Run > Set Options > Enable Auto Multirest and Min Measures to Combine +
  
+ +Combine consecutive measures of all rests or spaces into +multirests +(multiple measures of rest printed as a single measure, +usually with the number of +measures of rest printed +above the staff). +Any time there +are N 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 +text +or +musical symbols +after the first beat of the measure, +or when there are +parameter changes +on a visible staff or in score context that +change +clef, +key, +or +time signature, +or when there is a +bar line +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 +the -s option +and the +"visible" parameter +below. +This option overrides the +restcombine parameter. +
+Command line:  +-C +
+Mupmate:       +Option not available (only used for debugging). +
  
+ +This option is only used in connection with +the -E option. +It specifies that comments +are to be passed through rather than deleted. +
+Command line:  +-d N +
+Mupmate:       +Option not available (only used for debugging). +
  
+ +Print debugging information. N 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, N would be 6 (because 2+4=6). +
+
1 +
+input syntax/grammar analysis tracing +
2 +
+high level parse phase tracing +
4 +
+low level parse phase tracing +
8 +
+reserved +
16 +
+high level placement phase tracing +
32 +
+low level placement phase tracing +
64 +
+reserved +
128 +
+contents of the main internal list +
256 +
+high level print or MIDI phase tracing +
512 +
+low level print or MIDI phase tracing +
+N 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. +
+Command line:  +-D MACRO[=macro-def] +
+Mupmate:       +Run > Set Options > Macro Definitions +
  
+ +Define +the +macro +MACRO. The macro name must consist of +upper case letters, digits, and underscores, beginning +with an upper case letter. The macro_def 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. +
+Command line:  +-e errfile +
+Mupmate:       +Option not needed. Mupmate automatically saves and displays error output. +
  
+ +Place the error message output into errfile instead of writing it to +the standard error output stream. +
+Command line:  +-E +
+Mupmate:       +Option not needed (only used for debugging). +
  
+ +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. +
+Command line:  +-f outfile +
+Mupmate:       +Option not needed. Mupmate automatically creates appropriate output file. +
  
+ +Place the PostScript output into outfile instead of writing to +the standard output. +
+Command line:  +-F +
+Mupmate:       +Run > Write PostScript File +
  
+ +This is like the -f 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. +
+Command line:  +-m midifile +
+Mupmate:       +Option not needed. Mupmate automatically creates appropriate output file. +
  
+ +Instead of generating PostScript output, +generate standard +MIDI (Musical Instrument Digital Interface) output, +and put it in midifile. +This option also causes the +macro +"MIDI" to become defined. +
+Command line:  +-M +
+Mupmate:       +Run > Write MIDI File +
  
+ +This is like the -m 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. +
+Command line:  +-o pagelist +
+Mupmate:       +Run > Set Options > Pages to Display +
  
+ +Print only the pages +given in pagelist. The pagelist 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 pagelist 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 +panelsperpage parameter. +
+Command line:  +-p N +
+Mupmate:       +Run > Set Options > First Page's Page Number +
  
+ +Start numbering pages +at N instead of at 1. +This can be set inside the Mup input file +with +the "firstpage" parameter, +but the command line option will override the parameter. +If -o and -p are used together, the page numbers given in the +-opagelist 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. +
+Command line:  +-r +
+Mupmate:       +Config > Registration Form +
  
+ +Print a copy of the +Mup shareware registration form +to standard output. +
+Command line:  +-s stafflist +
+Mupmate:       +Run > Set Options > Staffs to Display/Play +
  
+ +Only print the staffs that are included in stafflist. +The stafflist 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 +MIDI output, +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 v1 or v2 or v3 +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". +See also the "visible" parameter. +
+Command line:  +-v +
+Mupmate:       +Help > About Mupmate +
  
+ +Print the Mup version number. When invoked from command line, +Mup will then exit. This document is for version 5.3. +
+Command line:  +-xM,N +
+Mupmate:       +Run > Set Options > Extract Measures +
  
+ +Extract measures M through N 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. +
+

+

+When invoked from command line, the options, if any, +can be followed by one or more files in the format +described in this User's Guide. If no files are specified, +standard input is read. +If several files 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. +

+

+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 +

+    mup -f outfile.ps infile.mup
+

+Or on Unix, Linux or MS-DOS command window, +you could redirect the output into a +file using the > character, as in: +
+    mup infile.mup > outfile.ps
+

+

+

+For more debugging, in addition to the +-d option, +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 +mupdisp, +which is covered below), these boxes will be in color. +
+


+* UNIX is a registered trademark of X/Open Company Limited +
+MS-DOS and Windows are registered trademarks of Microsoft Corporation +
+PostScript is a trademark of Adobe Systems Incorporated +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/contexts.html b/mup/docs/uguide/contexts.html new file mode 100644 index 0000000..2a145c7 --- /dev/null +++ b/mup/docs/uguide/contexts.html @@ -0,0 +1,135 @@ + + +Mup Contexts + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Contexts +

+

+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: +

+
+header +
+to define what goes at the top of the first page, typically +the title, composer, etc. +
+footer +
+to define what goes at the bottom of the first page, +typically a copyright notice, performance notes, etc. +
+header2 +
+to define what is to be printed on the top of pages after the first page. +
+footer2 +
+to define what is to be printed on the bottom of pages after the first page. +
+top +
+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. +
+bottom +
+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. +
+top2 +
+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. +
+bottom2 +
+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. +
+block +
+to define a block that contains text rather than music. +
+score +
+to define +parameters +that apply to the entire score. +
+staff S +
+to define +parameters +to be used for staff S, +where S is a number from 1 to 40. +
+voice S V +
+to define +parameters +for a particular voice V on staff S. +The voice V can be either 1, 2, or 3. +S is a staff number from 1 to 40. +
+grids +
+to define grids (typically for guitar) +
+headshapes +
+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 +shaped notes. +
+music +
+to define everything else. This includes +notes, +lyrics, +bar lines, +phrase marks, +tempo and dynamic marks, etc. +
+

+

+Most contexts are optional. An input file +just needs to contain either at least one measure of music +or at least one +block. +The \fBheader, footer, header2,\fP and \fBfooter2\fP +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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/cres.html b/mup/docs/uguide/cres.html new file mode 100644 index 0000000..df494d6 --- /dev/null +++ b/mup/docs/uguide/cres.html @@ -0,0 +1,45 @@ + + +Crescendo and decrescendo marks + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Crescendo and decrescendo marks +

+

+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: +

+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
+

+Picture of Mup output
+

+

+The placement of crescendo and decrescendo marks can be controlled +by setting the +dyndist parameter. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/crossbar.html b/mup/docs/uguide/crossbar.html new file mode 100644 index 0000000..dbe709c --- /dev/null +++ b/mup/docs/uguide/crossbar.html @@ -0,0 +1,73 @@ + + +Cross-bar beaming + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Cross-bar beaming +

+

+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 +stem lengths +such that all the beams in the various measures will lie on the same line. +You can then use the +line command +to fill in the gaps in the beams across the bar lines. +

+

+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. +

+// 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)
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/crossst.html b/mup/docs/uguide/crossst.html new file mode 100644 index 0000000..8e32ac4 --- /dev/null +++ b/mup/docs/uguide/crossst.html @@ -0,0 +1,63 @@ + + +Cross-staff stems + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Cross-staff stems +

+

+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: +

+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
+

+Picture of Mup output
+

+

+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 all 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 +horizontal offset +that was described earlier. +

+

+For +MIDI +purposes, only the normal staff's key signature and accidentals are +considered, so if the other staff has a different +key signature +or accidentals that should really apply to these notes, you will have +to supply accidentals explicitly. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/debug.html b/mup/docs/uguide/debug.html new file mode 100644 index 0000000..bf675b8 --- /dev/null +++ b/mup/docs/uguide/debug.html @@ -0,0 +1,37 @@ + + +Mup debugging + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Debugging +

+

+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. +

+

+Often listening to +MIDI output +is much more effective at spotting things like wrong notes and missing +accidentals than trying to find them by eye. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/fontfile.html b/mup/docs/uguide/fontfile.html new file mode 100644 index 0000000..1d18585 --- /dev/null +++ b/mup/docs/uguide/fontfile.html @@ -0,0 +1,39 @@ + + +Mup font files + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Installing other fonts +

+

+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. +The "mkmupfnt" program +that is distributed with Mup +can be used to generate a font description file. You can then use +

+	fontfile "file"
+

+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. +

+

+Mup searches for fontfiles via the MUPPATH mechanism, just like for +included files. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/gensyn.html b/mup/docs/uguide/gensyn.html new file mode 100644 index 0000000..d5e78b8 --- /dev/null +++ b/mup/docs/uguide/gensyn.html @@ -0,0 +1,137 @@ + + +Mup General Syntax + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+MUP FILE STRUCTURE +

+

+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: +

+//!Mup-Arkkra
+

+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: +
+//!Mup-Arkkra-5.3
+

+

+

+Mup General Syntax +

+

+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. +

+

+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: +

+// Note: in some early manuscripts, this chord had an accent
+

+

+

+Staffs are numbered from top to bottom, starting at staff 1. +

+

+Several different units are used for distances. One is inches or +centimeters. (There is a +units parameter +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 +time signature +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. +

+

+Upper and lower case letters are not interchangeable. Thus, for example, +"SCORE" is not the same as "score." +

+

+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.* +


+* The commands on which the ending semicolon is optional are: +bar, +multirest, +setting of parameters, +print, left, right, center, title, +newscore, newpage, +line, and curve. +Semicolons are not allowed after commands that indicate entering a new +context (header, footer, music, staff, grids, etc.). +A newline after those commands is optional, +although often a good idea for readability. +

+

+In +music context, +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 +grids context +and +headshape context, +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. +

+

+Mup supports +macros and conditionals (like 'if' and 'ifdef') +that can be placed anywhere in input, except in the middle of words, +numbers, or strings; they needn't be on separate lines. +

+

+In a number of statements, Mup expects a text string. All strings must be +enclosed in double quotes. For example: +

+"This is a string."
+"Allegro"
+

+

+

+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 +the chapter on text strings. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/headfoot.html b/mup/docs/uguide/headfoot.html new file mode 100644 index 0000000..697a5f5 --- /dev/null +++ b/mup/docs/uguide/headfoot.html @@ -0,0 +1,199 @@ + + +Mup header and footers + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Headers and footers +

+

+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. +

+

+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) +

+

+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. +

+

+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: +

+top
+    title "Here is the Title"
+

+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. +

+

+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. +

+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"
+

+Again, in this simple example, +you could use "header" and "footer" rather than "top" and "bottom." +

+

+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: +

+top2
+  title "Here is the Title - \%"
+

+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. +Another special marker +is \#, which will be replaced by the page number of the final page. +This could be useful for doing something like "page \% of \#." +

+

+As a variation, perhaps you'd prefer the information at the bottom of +the page. +

+bottom2
+   title "This is the title"  "Page \%"
+

+In this variation, two separate text strings are specified, +so the first string will be left justified and the second will be +right justified. +

+

+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. +

+

+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: +

+header
+   title "My Favorite Songs"
+header2
+   title "My Favorite Songs"
+footer2
+   title "\%"
+

+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: +
+top
+   title (18) "This is the Song Title"
+top2
+   title "This is the Song Title"
+

+

+

+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. +

+

+These contexts are conceptually in a separate coordinate space, +which will be overlaid on each page coordinate space. +When in these contexts, +the _win special tag +applies to +the header or footer window rather than the space between the header and +footer as it does in the music context. +

+

+Since headers or footers will expand as necessary, the +value of _win.s and _win.y +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). +

+

+In addition to the "title" commands used in the examples above, +you can also use +the "print," "left," "right," or "center" commands. +In most +cases you will want to use "nl" for the location on those commands +to place things. If you don't specify a location 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 +font, +fontfamily, +and +size +parameters. +These parameter values will be used until the end of the context or until +set again to some other value. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/heeltoe.html b/mup/docs/uguide/heeltoe.html new file mode 100644 index 0000000..11eed09 --- /dev/null +++ b/mup/docs/uguide/heeltoe.html @@ -0,0 +1,40 @@ + + +Organ pedal heel/toe marks + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Organ pedal heel and toe marks +

+

+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. +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/ichdattr.html b/mup/docs/uguide/ichdattr.html new file mode 100644 index 0000000..010e0bf --- /dev/null +++ b/mup/docs/uguide/ichdattr.html @@ -0,0 +1,382 @@ + + +Inter-chord attributes + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Inter-chord attributes +

+

+In addition to the +chord attributes +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: +

+

+

+If several of these are specified on a single chord, they may be in any +order, separated by commas. +

+

+Chord ties +

+

+If all notes in a chord are to be tied to the following chord, +the keyword "tie" +can be placed at the end of the chord. As was mentioned earlier, +individual notes can be tied using a "~" symbol. +Thus: +

+ceg tie;
+

+is equivalent to +
+c~e~g~;
+

+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. +

+

+You can also produce the effect of tying chords by using additive time +values. For example, the following lines produce the same output: +

+1: 2ceg tie;8;;4;  // explicit tie
+
+1: 2+8ceg;8;4;	// tie implied by added time values
+

+

+

+Chord slurs +

+

+The keyword "slur" can be placed at the end of a chord to indicate +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: +

+1: 2f<d> a<b> c+<d+>; dbd+;
+bar
+
+1: 2fac+ slur; dbd+;
+bar
+

+Picture of Mup output
+

+

+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. +

+

+Custom beaming +

+

+Normally, notes of eighth or shorter duration are automatically beamed +according to the specification of +the "beamstyle" parameter. +Occasionally, you may wish to +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: +

+// 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
+

+Picture of Mup output
+

+

+In the absence of custom beaming, Mup will beam notes together +using the +beamstyle parameter, +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. +

+// 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
+

+Picture of Mup output
+

+

+The value of the beamstyle parameter is remembered for +any later changes back to the same time signature. +For example, suppose you set +

+time=4/4
+beamstyle=4,4,4,4
+

+then later in the piece switched to +
+time=3/4
+beamstyle=4,4,4
+

+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. +

+

+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. +

+

+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. +

+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
+

+Picture of Mup output
+

+

+Cross-staff beams +

+

+In keyboard music, +sometimes notes on adjacent staffs are beamed together. +Mup will do this with a variation on +custom beaming. +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 +beamstyle parameter, +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. +

+

+Some examples: +

+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
+

+Picture of Mup output
+

+

+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 +stem direction. +You can also adjust the appearance of the beam by giving +stems lengths +for the first and last chords in the beam. +

+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
+

+Picture of Mup output
+

+

+If a cross-staff beam includes +tuplets, +the tuplet numbers will not +be printed. You would have to print them yourself using either +a "print" statement +or +a "boldital" statement. +

+

+It is possible for cross-staff beams to collide with other items, such as +dynamic marks. +In these cases, you may need to move the other items. Another +thing you might try is +specifying stem lengths +to alter where the beams get placed, or +printing +a blank string between the staffs to cause them to get placed further apart. +If you specify a +slope, +you have to specify it on the staff having notes in the first chord, +not the staff with space. +Slashes +are not allowed on cross-staff beams. +

+

+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 +section on "Special uses of invisbar" +for more details. +

+

+You may want to also look at the section on +cross-staff stems, +for an alternate way to handles some cases where you might +use cross-staff beams. +

+

+Alternation +

+

+Alternation pairs +can be specified using "alt N" where N +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 N 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: +

+// 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
+

+Picture of Mup output
+

+

+Alternation is not allowed on cross-staff beams. +

+

+Slope +

+

+On the first chord of a set of chords that are beamed together, +you can specify a +beam angle from -45 to 45 degrees. +This will override whatever angle Mup would have used. +

+1: 8g slope 11; b; g slope 0; b;  g slope -5.75; b;
+bar
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/ifclause.html b/mup/docs/uguide/ifclause.html new file mode 100644 index 0000000..2a9ca72 --- /dev/null +++ b/mup/docs/uguide/ifclause.html @@ -0,0 +1,249 @@ + + +Generalized conditionals + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Generalized conditionals +

+

+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. +

+

+The general form is +

+if condition then Mup statements else Mup statements endif
+

+As with the "ifdef," the "else" and second set of Mup statements is optional. +

+

+One form of "if" is really just a variation of ifdef. It uses the +keyword "defined" followed by a macro name. So +

+  ifdef DUET
+

+could also be written +
+  if defined DUET then
+

+You may put a set of parentheses around the macro name for clarity +if you wish: +
+  if defined(DUET) then
+

+

+

+The ! is used to mean "not," so +

+  ifndef TRIO
+

+could also be written as +
+  if ! defined(TRIO) then
+

+

+

+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: +

+ if defined(FULL_SCORE) && defined(TRANSPOSE_UP) && ! defined(MIDI) then
+

+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 +
+ if defined(CELLO) || defined(STRINGBASS)
+

+would be true as long as at least one of the macros was defined. +

+

+The condition can also include numbers and macros used as numeric values +in arithmetic and comparisons. For example, +

+  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
+

+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: + + + + + + + + + + + + + + + + + + + +
< less than
> greater than
<= less than or equal
>= greater than or equal
== equal
!= not equal
+ +

+

+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 +Mup parameters. +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. +

+

+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). +

+

+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. +

+

+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: +

+   5 + 3 * 8
+

+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 +
+   5 + (3 * 8)
+

+so we would first multiply 3 by 8, getting 24, and then add 5 and 24, +obtaining a final answer of 29. +

+

+If you really intended the 64 meaning, that could be shown by parentheses, +indicating you want the addition to be done first: +

+   (5 + 3) * 8
+

+

+

+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 +

+  10 - 6 - 1
+

+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! +

+

+Since the "not" operator and unary minus associate right to left, +in the expression +

+  ! - (5)
+

+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. +

+

+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. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
operators operations associativity
( ) grouping left to right
! ~ - + not, one's complement, unary minus, unary plus right to left
* / % multiply, divide, modulo left to right
+ - add, subtract left to right
<< >> left shift, right shift left to right
< <= > >= less than, less or equal, greater than, greater or equal left to right
== != equal, not equal left to right
& bitwise AND left to right
^ bitwise XOR left to right
| bitwise OR left to right
&& logical AND left to right
|| logical OR left to right
? : interrogation right to left
+ +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/include.html b/mup/docs/uguide/include.html new file mode 100644 index 0000000..6a8c19a --- /dev/null +++ b/mup/docs/uguide/include.html @@ -0,0 +1,39 @@ + + +Mup include files + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Include +

+

+The "include" statement can be used to include the contents of one file +inside another. +

+include "filename"
+

+causes input to be read from the specified filename. When the end +of that file is reached, reading of input resumes from the original file +after the include statement. +

+

+If the filename 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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/index.html b/mup/docs/uguide/index.html new file mode 100644 index 0000000..b71dc9b --- /dev/null +++ b/mup/docs/uguide/index.html @@ -0,0 +1,257 @@ + + +Mup User's Guide + + + +

+This is the on-line version of the Mup User's Guide, giving information +about how to use the Mup Music Publication program. +

+

+Mup Background Information +

+Introduction to Mup +
+Quick tutorial on Mup basics +
+Running Mup +
+Mup Options +
+Mup utility programs for displaying and printing music +
+Mup General syntax information +
+Mup contexts +
+
+

+Basic Standard Music Notation +

+Specifying Mup music input +
+Chords (pitch, duration, and other attributes) +
+ +
+Chord-at-a-time input style +
+Bar lines +
+ +Multirests +
+Lyrics +
+

+Tablature +

+Tablature notation +
+

+Shaped notes +

+Shaped notes +
+

+Text Strings +

+Mup text strings +
+

+Tempo, dynamic marks, ornaments, etc. +

+General Information +
+Text +
+Guitar grids +
+Music symbols +
+Phrase marks +
+Crescendo and decrescendo marks +
+Octave marks +
+Piano pedal marks +
+Rolls +
+

+Tags, printing text, lines and curves +

+Location tags +
+Printing text +
+Lines and curves +
+

+Miscellaneous Mup features +

+Newscore and newpage +
+Page headers and footers +
+Macros +
+Generalized if clauses +
+Include files +
+Installing other fonts +
+
+

+Mup Parameters +

+Mup parameters +
+

+Hints +

+Debugging +
+Adjusting output +
+Special uses of invisible bars +
+Chant +
+Forcing shared note heads +
+Manually placed tuplet numbers +
+Manual placement of notes +
+Bracketing notes across staffs +
+Cross-bar beaming +
+Mixed time signatures +
+Different margins for odd/even pages +
+Transposition +
+Marking complicated tempo changes +
+Placing several songs on one page +
+Cadenzas +
+Placing verses below the scores +
+Automatic piano reduction +
+Diagonal slash marks +
+Breath marks +
+Organ pedal heel and toe marks +
+Generating blank staff paper +
+Converting Mup files to other formats +
+

+MIDI output +

+MIDI output +
+
+
+Arkkra Enterprises +
+P. O. Box 315 +
+Warrenville, IL 60555 +
+support@arkkra.com +
+http://www.arkkra.com +
+
+
+Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises +

+    next page --> +

+ diff --git a/mup/docs/uguide/intro.html b/mup/docs/uguide/intro.html new file mode 100644 index 0000000..6a698a4 --- /dev/null +++ b/mup/docs/uguide/intro.html @@ -0,0 +1,63 @@ + + +Introduction to Mup + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+INTRODUCTION +

+

+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. +

+

+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 +learning just the basics, +then learn the more complicated features as you need them. +Mup also has an option to produce +output in the standard Musical Instrument Digital Interface (MIDI) format. +

+

+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 +registration form, +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. +
+


+* PostScript is a trademark of Adobe Systems Incorporated +
+** MS-DOS and Windows are trademarks of Microsoft Corporation +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/invisbar.html b/mup/docs/uguide/invisbar.html new file mode 100644 index 0000000..b41402f --- /dev/null +++ b/mup/docs/uguide/invisbar.html @@ -0,0 +1,81 @@ + + +Special uses of invisbar + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Special uses of invisbar +

+

+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 +rehearsal letter +in the middle of a measure. This could be accomplished as follows: +

+// 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
+

+Picture of Mup output
+

+

+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. +

+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
+

+Picture of Mup output
+

+

+You can use a similar technique to insert time signatures, clefs, etc. +at unusual places. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/linecurv.html b/mup/docs/uguide/linecurv.html new file mode 100644 index 0000000..fda9187 --- /dev/null +++ b/mup/docs/uguide/linecurv.html @@ -0,0 +1,134 @@ + + +Lines and curves + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Lines and curves +

+

+The "line" statement is used for drawing lines. Its format is: +

+linetype line (X1, Y1) to (X2, Y2)
+

+The linetype 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 +roll +and +mussym +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. +

+

+The X and Y coordinates are specified as was described +in the section on +"Location tags." +

+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
+

+Picture of Mup output
+

+

+It is possible to print a text string by the line by adding +

+with fontfamily font (size) "string"
+

+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 +fontfamily, +font, +and +size +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. +
+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
+

+Picture of Mup output
+

+

+Arbitrary curves can be drawn using the "curve" statement: +

+linetype curve (X1,Y1) to (X2,Y2) to (X3,Y3) ...
+

+When using this form of the "curve" statement, +at least three coordinates must be specified; more are permitted. +The linetype can be "medium," "wide," "dashed," +or "dotted," or omitted. +A curve will be drawn through the specified points in the specified order. +
+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
+

+Picture of Mup output
+

+

+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 n 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 +n stepsizes. +A positive n will cause the curve to bulge +to the left as you move from the start point to the end point, +while a negative n 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. +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/lyrics.html b/mup/docs/uguide/lyrics.html new file mode 100644 index 0000000..682a81c --- /dev/null +++ b/mup/docs/uguide/lyrics.html @@ -0,0 +1,399 @@ + + +Lyrics + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Lyrics +

+

+Lyrics are specified in a somewhat similar manner to +note groups. +Lyrics for each staff are specified with the word "lyrics" +optionally followed by a place, +followed by the staff number, followed by a colon, then the timing and +syllable information. +

+

+The place, 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. +

+

+The staff number 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. +

+

+The place can also be specified as "between M&N" +where M and N are numbers. +This will cause the lyrics to printed approximately halfway between staff +M and staff N. N must be exactly one greater than M. +

+lyrics 1:
+lyrics above 2,3:
+lyrics between 1&2, 3&4:
+

+

+

+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: +

+lyrics above 1,3 ; below 2,4 ; between 5&6 :
+

+

+

+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. +

+

+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: +

+
+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";
+

+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. +

+

+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. +

+

+Verse numbers need not be consecutive. +The staff number and verse number can be given as lists or ranges. +Another example: +

+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
+

+Picture of Mup output
+

+

+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. +

+

+You can also specify a verse number of "c" which means the verse is +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. +

+1: c;;e;;
+lyrics 1: ;;2s; [1] "verse one"; [2] "verse two";
+lyrics 1: 2s;4;; [c] "The refrain";	// centered lyrics
+bar
+

+Picture of Mup output
+

+

+The lyrics string is followed by a semicolon. +There must normally be one syllable in the lyrics string for each time value. +(There is one exception, +discussed later.) +Syllables are separated in the lyrics string by white space, +a dash, or an underscore. +

+

+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. +

+

+Here are some examples: +

+// 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
+

+Picture of Mup output
+
+// examples of above lyrics with dash and underscore
+1: 4d<>;e;8g;b;4a;
+lyrics above 1: "now_ or nev-er";
+bar
+

+Picture of Mup output
+

+

+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 +described a bit later. +However, if they are used by themselves with nothing between them, +they essentially mean a syllable with no text. +

+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
+

+Picture of Mup output
+

+

+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: +

+1: b;a;2g;
+lyrics 1: ;;2; "man-y~a day";
+bar
+

+Picture of Mup output
+If you don't want the curved line, +you can use the special character name "\(space)" instead of a +literal space. +That special space character +is printed like a normal space on output, +but is not considered a space for the purposes of determining syllable +boundaries. Alternately, +a technique using angle brackets, +described later, can be used. +

+

+If several verses use the same time values, you can specify them all on +one input line. +For example: +

+1: d;f;a;g;
+lyrics 1: [1] "this is verse one"; \
+       [2] "this is verse two";
+bar
+

+Picture of Mup output
+

+

+In this example, +because of the \ at the end of the first line, both verses are effectively +on the same input line. +

+

+Occasionally, lyrics may occur during only part of a measure. +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: +

+1: 2r;g;
+lyrics 1: 2s;; [1] "Now";
+bar
+

+Picture of Mup output
+

+

+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. +

+

+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. +

+

+Occasionally, you may want to print something within a lyric string +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 "<". +

+

+Some examples: +

+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
+

+Picture of Mup output
+

+

+The < > construct can also be used to fine-tune the placement of syllables. +The placement of syllables is governed in general by the +lyricsalign parameter. +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. +

+1: c;d;e;f;
+lyrics 1: "This strength not moved."; \
+        "This <str>ength was moved.";
+bar
+

+Picture of Mup output
+

+

+Angle brackets may also be useful for entering +chant, where many words +are to be associated with a single note. For example: +

+lyrics 1: "All<^ these words will be treated like one syllable.>";
+

+

+

+The font and size to use for lyrics is initially determined +from the +"lyricsfontfamily," +"lyricsfont" +and +"lyricssize" +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 +change these values +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 +"lyricsfontfamily," +"lyricsfont" +or +"lyricssize" +parameters will reset the values for +all verses of the staff (if set in +staff context), +or the entire score (if set in +score context). +

+

+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 +sylposition parameter. +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. +

+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
+

+Picture of Mup output
+

+

+A few more examples of lyrics: +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/macros.html b/mup/docs/uguide/macros.html new file mode 100644 index 0000000..4274b8d --- /dev/null +++ b/mup/docs/uguide/macros.html @@ -0,0 +1,211 @@ + + +Mup macros + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Macros +

+

+Simple Macros (without parameters) +

+

+Macros can be defined to avoid retyping or to give mnemonic names to +things. A macro is defined with the following syntax: +

+define  macro_name macro_text @
+

+

+

+The macro_name consists of one or more upper case letters, digits, +and underscores, with the first character being a letter. +The macro_text 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 macro_text by preceding it with a backslash. +If you want a literal backslash in the macro_text, it also must +be preceded by a backslash. +

+

+A macro is called by stating the macro_name in the input. The +macro_name is replaced by the macro_text. +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 macro_name +can be redefined as many times as desired, with each new definition +overwriting the previous definition. +

+

+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: +

+define OBOE 5: @
+

+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. +

+

+Another common use of macros might be if a musical motif occurs several +times. You could define a macro for the motive: +

+define SCALE 8c;d;e;f;g;a;b;c+; @
+

+then do something like: +
+OBOE SCALE
+

+

+

+It is possible to remove the definition of a macro using the "undef" +statement: +

+undef OBOE
+

+

+

+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. +

+

+The ifdefs can be sprinkled between other items in the input; +they need not be on separate lines. They can be nested. Examples: +

+// 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
+

+

+

+Macros can also be set from the command line using the -D option. +Only ordinary macros can be defined using the -D option, +not macros with parameters. +

+

+Macros with parameters +

+

+Macros defined within Mup input can be defined to have "parameters." +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. +

+

+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: +

+boldital below 1-4: 1 "ff";
+boldital between 5&6: 1 "ff";
+

+but if you needed to do this lots of times, it could get tedious. +So let's define a macro with parameters: +
+define DYN( COUNT, VOLUME )
+boldital below 1-4: COUNT VOLUME;
+boldital between 5&6: COUNT VOLUME;
+@
+

+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, +
+DYN(1,"ff")
+

+would give a VOLUME of "ff" at COUNT 1, whereas +
+DYN(3.5,"mp")
+

+would give a VOLUME of "mp" at COUNT 3.5. +

+

+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 +

+MAC(\\\,\))
+

+has one parameter, the text of which is 3 characters long: a backslash, +comma, and closing parenthesis. +

+

+If in a macro definition a parameter is used inside backticks, +as in `NAME`, the value of the parameter will be placed +inside double quotes. Thus, another way to do the example above would be: +

+define DYN( COUNT, VOLUME )
+boldital below 1-4: COUNT `VOLUME`;
+boldital between 5&6: COUNT `VOLUME`;
+@
+
+DYN(1,ff)
+DYN(3.5,mp)
+

+

+

+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: +

+// 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"
+

+

+

+Sometimes it can be a little tricky to get the number of backslashes right, +or other details like that. +The -E Mup command line option +shows how macros will expand, which may help you figure out what to do. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/mantup.html b/mup/docs/uguide/mantup.html new file mode 100644 index 0000000..823284c --- /dev/null +++ b/mup/docs/uguide/mantup.html @@ -0,0 +1,47 @@ + + +Manually placed tuplet numbers + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Manually placed tuplet numbers +

+

+Generally, Mup will place +tuplet +numbers for you. +However, you do need to print them yourself on +cross-staff beams. +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 +macro +something like this: +

+define TUPNUM(NUM) "\f(NX)\s(11)" +`NUM` @
+1: { 8c; d; e; } 3n; 2.us;         
+rom above 1 dist0: 1.34 TUPNUM(3);
+bar
+

+Or another approach would be something like this: +
+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
+

+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/manual.html b/mup/docs/uguide/manual.html new file mode 100644 index 0000000..190c9e4 --- /dev/null +++ b/mup/docs/uguide/manual.html @@ -0,0 +1,92 @@ + + +Manual placement of notes + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Manual placement of notes +

+

+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 +MIDI output. +

+

+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 +padding to the chord. +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 +location tag +on one of the notes +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 +print statement +using one of the special +music characters, +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: +

+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
+

+Picture of Mup output
+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). +

+

+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: +

+print (h.w - 5, h.y + 3) "\(flat)"
+

+Picture of Mup output
+to place a flat sign in front of the c. +

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/midi.html b/mup/docs/uguide/midi.html new file mode 100644 index 0000000..93731d8 --- /dev/null +++ b/mup/docs/uguide/midi.html @@ -0,0 +1,333 @@ + + +Mup MIDI output + + +

+   <-- previous page + +     Table of Contents +

+MIDI OUTPUT +

+

+Mup will optionally produce MIDI output +(using the -m command line argument). +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. +

+

+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. +

+

+Each +voice +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. +

+

+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. +

+

+Mup MIDI output will handle +repeats +and +first and second endings, +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 +macros. +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: +

+// 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
+

+

+

+Mup mainly just outputs the note information. +Mup will recognize +octave marks, +and move notes up or down appropriately. +It recognizes +piano pedal marks. +It does not attempt to interpret tempo or dynamics marks +specified by +"rom," "boldital," etc. or ornaments in +"mussym" statement. +It does interpret +rehearsal marks +as cue points. +It handles +grace notes, +rolls, +slashes, +and +alternation groups. +You can control how legato the music is by using +the Mup "release" parameter. +

+

+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 +swingunit +parameter can be used to get Mup MIDI output to automatically follow +that performance convention. +

+

+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: +

+midi S V: begintime "keyword=value";
+

+The S and V 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 +
+midi all: begintime "keyword=value";
+

+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. +

+

+The begintime, 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 +begintime, first all "note off" commands are generated, then the "midi" +command events, then "note on" commands. +

+

+The keyword=value gives specific information of +what MIDI output to generate. The following keywords are currently supported: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
keyword values meaning midi S V midi all
program 0-127 program change (new instrument) yes no
parameter 0-127,0-127 parameter yes yes
channel 1-16 channel yes no
chanpressure 0-127 channel pressure (after touch) yes yes
tempo 10-1000 tempo, quarter notes per minute no yes
seqnum 0-65535 sequence number yes yes
text text text meta event yes yes
copyright text copyright notice yes yes
name text sequence/track name yes yes
instrument text instrument name yes yes
marker text marker meta event yes yes
cue text cue point yes yes
port 0-127 MIDI port yes yes
onvelocity 1-127 note on velocity yes no
offvelocity 0-127 note off velocity yes no
hex hex data arbitrary MIDI data yes yes
+ +

+

+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. +

+

+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: +

+midi 3 2: 0 "parameter=7,90";
+

+

+

+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 +

+midi 1: 1 "onvelocity=76, 60";
+

+which would cause the top note to have a velocity of 76 and all other +notes to have a velocity of 60. +

+

+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. +

+

+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. +

+

+Here are some examples: +

+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";
+

+

+

+Here is a more extensive example of how midi commands might be used +in a song: +

+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
+

+

+
+

+   <-- previous page +     Table of Contents

+ diff --git a/mup/docs/uguide/midmeas.html b/mup/docs/uguide/midmeas.html new file mode 100644 index 0000000..78472c9 --- /dev/null +++ b/mup/docs/uguide/midmeas.html @@ -0,0 +1,59 @@ + + +Mid-measure parameter changes + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Mid-measure parameter changes +

+

+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 +clef +in the middle of a measure. There are two +other parameters that can also be changed here: +defoct +and +release. +The change is enclosed in double angle brackets. +After the opening angle bracket is the +context +to which the changes applies (score, staff, or voice), +followed by one or more parameter changes. +

+1: c; e; <<score clef=bass>> 2g;
+bar
+

+Picture of Mup output
+If there is more than one parameter listed, they are separated by semicolons. +
+<< staff clef = tenor ; defoct = 4 >>
+

+

+

+If you wish to change parameters in more than one context, multiple +angle-bracketed items can be given: +

+2-3 2: 2c; <<score release=100>><<staff clef=alto>><<voice defoct=3>> c;
+

+

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/mixtsig.html b/mup/docs/uguide/mixtsig.html new file mode 100644 index 0000000..a8b497a --- /dev/null +++ b/mup/docs/uguide/mixtsig.html @@ -0,0 +1,71 @@ + + +Mixed time signatures + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Mixed time signatures +

+

+Once in a while, music is written with different +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: +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/mugex10.gif b/mup/docs/uguide/mugex10.gif new file mode 100644 index 0000000..25b774a Binary files /dev/null and b/mup/docs/uguide/mugex10.gif differ diff --git a/mup/docs/uguide/mugex100.gif b/mup/docs/uguide/mugex100.gif new file mode 100644 index 0000000..75da3aa Binary files /dev/null and b/mup/docs/uguide/mugex100.gif differ diff --git a/mup/docs/uguide/mugex101.gif b/mup/docs/uguide/mugex101.gif new file mode 100644 index 0000000..fd5b6e5 Binary files /dev/null and b/mup/docs/uguide/mugex101.gif differ diff --git a/mup/docs/uguide/mugex11.gif b/mup/docs/uguide/mugex11.gif new file mode 100644 index 0000000..04e7a16 Binary files /dev/null and b/mup/docs/uguide/mugex11.gif differ diff --git a/mup/docs/uguide/mugex12.gif b/mup/docs/uguide/mugex12.gif new file mode 100644 index 0000000..a7317ca Binary files /dev/null and b/mup/docs/uguide/mugex12.gif differ diff --git a/mup/docs/uguide/mugex13.gif b/mup/docs/uguide/mugex13.gif new file mode 100644 index 0000000..497ba22 Binary files /dev/null and b/mup/docs/uguide/mugex13.gif differ diff --git a/mup/docs/uguide/mugex14.gif b/mup/docs/uguide/mugex14.gif new file mode 100644 index 0000000..572d27a Binary files /dev/null and b/mup/docs/uguide/mugex14.gif differ diff --git a/mup/docs/uguide/mugex15.gif b/mup/docs/uguide/mugex15.gif new file mode 100644 index 0000000..1d87b78 Binary files /dev/null and b/mup/docs/uguide/mugex15.gif differ diff --git a/mup/docs/uguide/mugex16.gif b/mup/docs/uguide/mugex16.gif new file mode 100644 index 0000000..c5230c6 Binary files /dev/null and b/mup/docs/uguide/mugex16.gif differ diff --git a/mup/docs/uguide/mugex17.gif b/mup/docs/uguide/mugex17.gif new file mode 100644 index 0000000..3c31175 Binary files /dev/null and b/mup/docs/uguide/mugex17.gif differ diff --git a/mup/docs/uguide/mugex18.gif b/mup/docs/uguide/mugex18.gif new file mode 100644 index 0000000..4e088d8 Binary files /dev/null and b/mup/docs/uguide/mugex18.gif differ diff --git a/mup/docs/uguide/mugex19.gif b/mup/docs/uguide/mugex19.gif new file mode 100644 index 0000000..6d00e06 Binary files /dev/null and b/mup/docs/uguide/mugex19.gif differ diff --git a/mup/docs/uguide/mugex2.gif b/mup/docs/uguide/mugex2.gif new file mode 100644 index 0000000..2b11833 Binary files /dev/null and b/mup/docs/uguide/mugex2.gif differ diff --git a/mup/docs/uguide/mugex20.gif b/mup/docs/uguide/mugex20.gif new file mode 100644 index 0000000..26d095a Binary files /dev/null and b/mup/docs/uguide/mugex20.gif differ diff --git a/mup/docs/uguide/mugex21.gif b/mup/docs/uguide/mugex21.gif new file mode 100644 index 0000000..a80ef39 Binary files /dev/null and b/mup/docs/uguide/mugex21.gif differ diff --git a/mup/docs/uguide/mugex22.gif b/mup/docs/uguide/mugex22.gif new file mode 100644 index 0000000..5a460c2 Binary files /dev/null and b/mup/docs/uguide/mugex22.gif differ diff --git a/mup/docs/uguide/mugex23.gif b/mup/docs/uguide/mugex23.gif new file mode 100644 index 0000000..c79f1c6 Binary files /dev/null and b/mup/docs/uguide/mugex23.gif differ diff --git a/mup/docs/uguide/mugex24.gif b/mup/docs/uguide/mugex24.gif new file mode 100644 index 0000000..f8ff821 Binary files /dev/null and b/mup/docs/uguide/mugex24.gif differ diff --git a/mup/docs/uguide/mugex25.gif b/mup/docs/uguide/mugex25.gif new file mode 100644 index 0000000..59e1b3c Binary files /dev/null and b/mup/docs/uguide/mugex25.gif differ diff --git a/mup/docs/uguide/mugex26.gif b/mup/docs/uguide/mugex26.gif new file mode 100644 index 0000000..baf0d85 Binary files /dev/null and b/mup/docs/uguide/mugex26.gif differ diff --git a/mup/docs/uguide/mugex27.gif b/mup/docs/uguide/mugex27.gif new file mode 100644 index 0000000..fd3dd93 Binary files /dev/null and b/mup/docs/uguide/mugex27.gif differ diff --git a/mup/docs/uguide/mugex28.gif b/mup/docs/uguide/mugex28.gif new file mode 100644 index 0000000..206edd9 Binary files /dev/null and b/mup/docs/uguide/mugex28.gif differ diff --git a/mup/docs/uguide/mugex29.gif b/mup/docs/uguide/mugex29.gif new file mode 100644 index 0000000..b6ae0a8 Binary files /dev/null and b/mup/docs/uguide/mugex29.gif differ diff --git a/mup/docs/uguide/mugex3.gif b/mup/docs/uguide/mugex3.gif new file mode 100644 index 0000000..7d22267 Binary files /dev/null and b/mup/docs/uguide/mugex3.gif differ diff --git a/mup/docs/uguide/mugex30.gif b/mup/docs/uguide/mugex30.gif new file mode 100644 index 0000000..54bf03e Binary files /dev/null and b/mup/docs/uguide/mugex30.gif differ diff --git a/mup/docs/uguide/mugex31.gif b/mup/docs/uguide/mugex31.gif new file mode 100644 index 0000000..8b714dd Binary files /dev/null and b/mup/docs/uguide/mugex31.gif differ diff --git a/mup/docs/uguide/mugex32.gif b/mup/docs/uguide/mugex32.gif new file mode 100644 index 0000000..018356f Binary files /dev/null and b/mup/docs/uguide/mugex32.gif differ diff --git a/mup/docs/uguide/mugex33.gif b/mup/docs/uguide/mugex33.gif new file mode 100644 index 0000000..c002a52 Binary files /dev/null and b/mup/docs/uguide/mugex33.gif differ diff --git a/mup/docs/uguide/mugex34.gif b/mup/docs/uguide/mugex34.gif new file mode 100644 index 0000000..21ffd3c Binary files /dev/null and b/mup/docs/uguide/mugex34.gif differ diff --git a/mup/docs/uguide/mugex35.gif b/mup/docs/uguide/mugex35.gif new file mode 100644 index 0000000..84fba74 Binary files /dev/null and b/mup/docs/uguide/mugex35.gif differ diff --git a/mup/docs/uguide/mugex36.gif b/mup/docs/uguide/mugex36.gif new file mode 100644 index 0000000..147a891 Binary files /dev/null and b/mup/docs/uguide/mugex36.gif differ diff --git a/mup/docs/uguide/mugex37.gif b/mup/docs/uguide/mugex37.gif new file mode 100644 index 0000000..14e7cd6 Binary files /dev/null and b/mup/docs/uguide/mugex37.gif differ diff --git a/mup/docs/uguide/mugex38.gif b/mup/docs/uguide/mugex38.gif new file mode 100644 index 0000000..35eb394 Binary files /dev/null and b/mup/docs/uguide/mugex38.gif differ diff --git a/mup/docs/uguide/mugex39.gif b/mup/docs/uguide/mugex39.gif new file mode 100644 index 0000000..5dac9e1 Binary files /dev/null and b/mup/docs/uguide/mugex39.gif differ diff --git a/mup/docs/uguide/mugex4.gif b/mup/docs/uguide/mugex4.gif new file mode 100644 index 0000000..999df8f Binary files /dev/null and b/mup/docs/uguide/mugex4.gif differ diff --git a/mup/docs/uguide/mugex40.gif b/mup/docs/uguide/mugex40.gif new file mode 100644 index 0000000..cbe8765 Binary files /dev/null and b/mup/docs/uguide/mugex40.gif differ diff --git a/mup/docs/uguide/mugex41.gif b/mup/docs/uguide/mugex41.gif new file mode 100644 index 0000000..cce5d00 Binary files /dev/null and b/mup/docs/uguide/mugex41.gif differ diff --git a/mup/docs/uguide/mugex42.gif b/mup/docs/uguide/mugex42.gif new file mode 100644 index 0000000..4e82014 Binary files /dev/null and b/mup/docs/uguide/mugex42.gif differ diff --git a/mup/docs/uguide/mugex43.gif b/mup/docs/uguide/mugex43.gif new file mode 100644 index 0000000..facfa4b Binary files /dev/null and b/mup/docs/uguide/mugex43.gif differ diff --git a/mup/docs/uguide/mugex44.gif b/mup/docs/uguide/mugex44.gif new file mode 100644 index 0000000..dff64a1 Binary files /dev/null and b/mup/docs/uguide/mugex44.gif differ diff --git a/mup/docs/uguide/mugex45.gif b/mup/docs/uguide/mugex45.gif new file mode 100644 index 0000000..c4fa2d3 Binary files /dev/null and b/mup/docs/uguide/mugex45.gif differ diff --git a/mup/docs/uguide/mugex46.gif b/mup/docs/uguide/mugex46.gif new file mode 100644 index 0000000..d3c0a02 Binary files /dev/null and b/mup/docs/uguide/mugex46.gif differ diff --git a/mup/docs/uguide/mugex47.gif b/mup/docs/uguide/mugex47.gif new file mode 100644 index 0000000..4ee511c Binary files /dev/null and b/mup/docs/uguide/mugex47.gif differ diff --git a/mup/docs/uguide/mugex48.gif b/mup/docs/uguide/mugex48.gif new file mode 100644 index 0000000..71f93a6 Binary files /dev/null and b/mup/docs/uguide/mugex48.gif differ diff --git a/mup/docs/uguide/mugex49.gif b/mup/docs/uguide/mugex49.gif new file mode 100644 index 0000000..714cd77 Binary files /dev/null and b/mup/docs/uguide/mugex49.gif differ diff --git a/mup/docs/uguide/mugex5.gif b/mup/docs/uguide/mugex5.gif new file mode 100644 index 0000000..c55796c Binary files /dev/null and b/mup/docs/uguide/mugex5.gif differ diff --git a/mup/docs/uguide/mugex50.gif b/mup/docs/uguide/mugex50.gif new file mode 100644 index 0000000..8c4ee4e Binary files /dev/null and b/mup/docs/uguide/mugex50.gif differ diff --git a/mup/docs/uguide/mugex51.gif b/mup/docs/uguide/mugex51.gif new file mode 100644 index 0000000..95019fa Binary files /dev/null and b/mup/docs/uguide/mugex51.gif differ diff --git a/mup/docs/uguide/mugex52.gif b/mup/docs/uguide/mugex52.gif new file mode 100644 index 0000000..a7f0342 Binary files /dev/null and b/mup/docs/uguide/mugex52.gif differ diff --git a/mup/docs/uguide/mugex53.gif b/mup/docs/uguide/mugex53.gif new file mode 100644 index 0000000..a432951 Binary files /dev/null and b/mup/docs/uguide/mugex53.gif differ diff --git a/mup/docs/uguide/mugex54.gif b/mup/docs/uguide/mugex54.gif new file mode 100644 index 0000000..78862fa Binary files /dev/null and b/mup/docs/uguide/mugex54.gif differ diff --git a/mup/docs/uguide/mugex55.gif b/mup/docs/uguide/mugex55.gif new file mode 100644 index 0000000..f1a59d9 Binary files /dev/null and b/mup/docs/uguide/mugex55.gif differ diff --git a/mup/docs/uguide/mugex56.gif b/mup/docs/uguide/mugex56.gif new file mode 100644 index 0000000..6445bd6 Binary files /dev/null and b/mup/docs/uguide/mugex56.gif differ diff --git a/mup/docs/uguide/mugex57.gif b/mup/docs/uguide/mugex57.gif new file mode 100644 index 0000000..de05080 Binary files /dev/null and b/mup/docs/uguide/mugex57.gif differ diff --git a/mup/docs/uguide/mugex58.gif b/mup/docs/uguide/mugex58.gif new file mode 100644 index 0000000..9dcd15c Binary files /dev/null and b/mup/docs/uguide/mugex58.gif differ diff --git a/mup/docs/uguide/mugex59.gif b/mup/docs/uguide/mugex59.gif new file mode 100644 index 0000000..accb040 Binary files /dev/null and b/mup/docs/uguide/mugex59.gif differ diff --git a/mup/docs/uguide/mugex6.gif b/mup/docs/uguide/mugex6.gif new file mode 100644 index 0000000..8acd4c3 Binary files /dev/null and b/mup/docs/uguide/mugex6.gif differ diff --git a/mup/docs/uguide/mugex60.gif b/mup/docs/uguide/mugex60.gif new file mode 100644 index 0000000..a4c16b2 Binary files /dev/null and b/mup/docs/uguide/mugex60.gif differ diff --git a/mup/docs/uguide/mugex61.gif b/mup/docs/uguide/mugex61.gif new file mode 100644 index 0000000..2344c63 Binary files /dev/null and b/mup/docs/uguide/mugex61.gif differ diff --git a/mup/docs/uguide/mugex62.gif b/mup/docs/uguide/mugex62.gif new file mode 100644 index 0000000..044bbc3 Binary files /dev/null and b/mup/docs/uguide/mugex62.gif differ diff --git a/mup/docs/uguide/mugex63.gif b/mup/docs/uguide/mugex63.gif new file mode 100644 index 0000000..4e08e3d Binary files /dev/null and b/mup/docs/uguide/mugex63.gif differ diff --git a/mup/docs/uguide/mugex64.gif b/mup/docs/uguide/mugex64.gif new file mode 100644 index 0000000..4b1de48 Binary files /dev/null and b/mup/docs/uguide/mugex64.gif differ diff --git a/mup/docs/uguide/mugex65.gif b/mup/docs/uguide/mugex65.gif new file mode 100644 index 0000000..17b0818 Binary files /dev/null and b/mup/docs/uguide/mugex65.gif differ diff --git a/mup/docs/uguide/mugex66.gif b/mup/docs/uguide/mugex66.gif new file mode 100644 index 0000000..c07a8d9 Binary files /dev/null and b/mup/docs/uguide/mugex66.gif differ diff --git a/mup/docs/uguide/mugex67.gif b/mup/docs/uguide/mugex67.gif new file mode 100644 index 0000000..aa7f5c0 Binary files /dev/null and b/mup/docs/uguide/mugex67.gif differ diff --git a/mup/docs/uguide/mugex68.gif b/mup/docs/uguide/mugex68.gif new file mode 100644 index 0000000..f32f6bf Binary files /dev/null and b/mup/docs/uguide/mugex68.gif differ diff --git a/mup/docs/uguide/mugex69.gif b/mup/docs/uguide/mugex69.gif new file mode 100644 index 0000000..8291cde Binary files /dev/null and b/mup/docs/uguide/mugex69.gif differ diff --git a/mup/docs/uguide/mugex7.gif b/mup/docs/uguide/mugex7.gif new file mode 100644 index 0000000..a4743db Binary files /dev/null and b/mup/docs/uguide/mugex7.gif differ diff --git a/mup/docs/uguide/mugex70.gif b/mup/docs/uguide/mugex70.gif new file mode 100644 index 0000000..bb4e597 Binary files /dev/null and b/mup/docs/uguide/mugex70.gif differ diff --git a/mup/docs/uguide/mugex71.gif b/mup/docs/uguide/mugex71.gif new file mode 100644 index 0000000..db27d78 Binary files /dev/null and b/mup/docs/uguide/mugex71.gif differ diff --git a/mup/docs/uguide/mugex72.gif b/mup/docs/uguide/mugex72.gif new file mode 100644 index 0000000..cf5ed15 Binary files /dev/null and b/mup/docs/uguide/mugex72.gif differ diff --git a/mup/docs/uguide/mugex73.gif b/mup/docs/uguide/mugex73.gif new file mode 100644 index 0000000..116c464 Binary files /dev/null and b/mup/docs/uguide/mugex73.gif differ diff --git a/mup/docs/uguide/mugex74.gif b/mup/docs/uguide/mugex74.gif new file mode 100644 index 0000000..7cd9332 Binary files /dev/null and b/mup/docs/uguide/mugex74.gif differ diff --git a/mup/docs/uguide/mugex75.gif b/mup/docs/uguide/mugex75.gif new file mode 100644 index 0000000..de843fa Binary files /dev/null and b/mup/docs/uguide/mugex75.gif differ diff --git a/mup/docs/uguide/mugex76.gif b/mup/docs/uguide/mugex76.gif new file mode 100644 index 0000000..ef18e30 Binary files /dev/null and b/mup/docs/uguide/mugex76.gif differ diff --git a/mup/docs/uguide/mugex77.gif b/mup/docs/uguide/mugex77.gif new file mode 100644 index 0000000..39a7a71 Binary files /dev/null and b/mup/docs/uguide/mugex77.gif differ diff --git a/mup/docs/uguide/mugex78.gif b/mup/docs/uguide/mugex78.gif new file mode 100644 index 0000000..1fa1521 Binary files /dev/null and b/mup/docs/uguide/mugex78.gif differ diff --git a/mup/docs/uguide/mugex79.gif b/mup/docs/uguide/mugex79.gif new file mode 100644 index 0000000..6d654b5 Binary files /dev/null and b/mup/docs/uguide/mugex79.gif differ diff --git a/mup/docs/uguide/mugex8.gif b/mup/docs/uguide/mugex8.gif new file mode 100644 index 0000000..7146ac6 Binary files /dev/null and b/mup/docs/uguide/mugex8.gif differ diff --git a/mup/docs/uguide/mugex80.gif b/mup/docs/uguide/mugex80.gif new file mode 100644 index 0000000..6b54ff7 Binary files /dev/null and b/mup/docs/uguide/mugex80.gif differ diff --git a/mup/docs/uguide/mugex81.gif b/mup/docs/uguide/mugex81.gif new file mode 100644 index 0000000..252382b Binary files /dev/null and b/mup/docs/uguide/mugex81.gif differ diff --git a/mup/docs/uguide/mugex82.gif b/mup/docs/uguide/mugex82.gif new file mode 100644 index 0000000..23dcf7e Binary files /dev/null and b/mup/docs/uguide/mugex82.gif differ diff --git a/mup/docs/uguide/mugex83.gif b/mup/docs/uguide/mugex83.gif new file mode 100644 index 0000000..404fcf4 Binary files /dev/null and b/mup/docs/uguide/mugex83.gif differ diff --git a/mup/docs/uguide/mugex84.gif b/mup/docs/uguide/mugex84.gif new file mode 100644 index 0000000..8c3b935 Binary files /dev/null and b/mup/docs/uguide/mugex84.gif differ diff --git a/mup/docs/uguide/mugex85.gif b/mup/docs/uguide/mugex85.gif new file mode 100644 index 0000000..d310dab Binary files /dev/null and b/mup/docs/uguide/mugex85.gif differ diff --git a/mup/docs/uguide/mugex86.gif b/mup/docs/uguide/mugex86.gif new file mode 100644 index 0000000..0368a73 Binary files /dev/null and b/mup/docs/uguide/mugex86.gif differ diff --git a/mup/docs/uguide/mugex87.gif b/mup/docs/uguide/mugex87.gif new file mode 100644 index 0000000..3cea34f Binary files /dev/null and b/mup/docs/uguide/mugex87.gif differ diff --git a/mup/docs/uguide/mugex88.gif b/mup/docs/uguide/mugex88.gif new file mode 100644 index 0000000..11dda78 Binary files /dev/null and b/mup/docs/uguide/mugex88.gif differ diff --git a/mup/docs/uguide/mugex89.gif b/mup/docs/uguide/mugex89.gif new file mode 100644 index 0000000..c528645 Binary files /dev/null and b/mup/docs/uguide/mugex89.gif differ diff --git a/mup/docs/uguide/mugex9.gif b/mup/docs/uguide/mugex9.gif new file mode 100644 index 0000000..788df31 Binary files /dev/null and b/mup/docs/uguide/mugex9.gif differ diff --git a/mup/docs/uguide/mugex90.gif b/mup/docs/uguide/mugex90.gif new file mode 100644 index 0000000..3ea7da1 Binary files /dev/null and b/mup/docs/uguide/mugex90.gif differ diff --git a/mup/docs/uguide/mugex91.gif b/mup/docs/uguide/mugex91.gif new file mode 100644 index 0000000..0a8da55 Binary files /dev/null and b/mup/docs/uguide/mugex91.gif differ diff --git a/mup/docs/uguide/mugex92.gif b/mup/docs/uguide/mugex92.gif new file mode 100644 index 0000000..326114d Binary files /dev/null and b/mup/docs/uguide/mugex92.gif differ diff --git a/mup/docs/uguide/mugex93.gif b/mup/docs/uguide/mugex93.gif new file mode 100644 index 0000000..08d59f9 Binary files /dev/null and b/mup/docs/uguide/mugex93.gif differ diff --git a/mup/docs/uguide/mugex94.gif b/mup/docs/uguide/mugex94.gif new file mode 100644 index 0000000..7e41431 Binary files /dev/null and b/mup/docs/uguide/mugex94.gif differ diff --git a/mup/docs/uguide/mugex95.gif b/mup/docs/uguide/mugex95.gif new file mode 100644 index 0000000..758249f Binary files /dev/null and b/mup/docs/uguide/mugex95.gif differ diff --git a/mup/docs/uguide/mugex96.gif b/mup/docs/uguide/mugex96.gif new file mode 100644 index 0000000..67b0082 Binary files /dev/null and b/mup/docs/uguide/mugex96.gif differ diff --git a/mup/docs/uguide/mugex97.gif b/mup/docs/uguide/mugex97.gif new file mode 100644 index 0000000..87b27f9 Binary files /dev/null and b/mup/docs/uguide/mugex97.gif differ diff --git a/mup/docs/uguide/mugex98.gif b/mup/docs/uguide/mugex98.gif new file mode 100644 index 0000000..b4930fb Binary files /dev/null and b/mup/docs/uguide/mugex98.gif differ diff --git a/mup/docs/uguide/mugex99.gif b/mup/docs/uguide/mugex99.gif new file mode 100644 index 0000000..342d554 Binary files /dev/null and b/mup/docs/uguide/mugex99.gif differ diff --git a/mup/docs/uguide/multirst.html b/mup/docs/uguide/multirst.html new file mode 100644 index 0000000..6fcd571 --- /dev/null +++ b/mup/docs/uguide/multirst.html @@ -0,0 +1,50 @@ + + +Multirests + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Multirest +

+

+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: +

+multirest 15
+bar
+1: 2c;4;;
+bar
+1: 2.c;4r;
+bar
+multirest 5
+bar
+

+Picture of Mup output
+

+

+See also +the -c command line option, +and +the restcombine parameter. +

+

+Normally, the number of measures of rest is printed, but +it is possible to turn this off using +the printmultnum parameter. +An alternate notation can be specified using +the restsymmult parameter. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/multsong.html b/mup/docs/uguide/multsong.html new file mode 100644 index 0000000..66078f8 --- /dev/null +++ b/mup/docs/uguide/multsong.html @@ -0,0 +1,82 @@ + + +Placing several songs on one page + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Placing several songs on one page +

+

+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 +use a "block" +for printing the titles +for the second song. +Here is an example: +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/muschar.gif b/mup/docs/uguide/muschar.gif new file mode 100644 index 0000000..6e31f15 Binary files /dev/null and b/mup/docs/uguide/muschar.gif differ diff --git a/mup/docs/uguide/music.html b/mup/docs/uguide/music.html new file mode 100644 index 0000000..58de85d --- /dev/null +++ b/mup/docs/uguide/music.html @@ -0,0 +1,39 @@ + + +Mup music context + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+BASIC STANDARD MUSIC NOTATION +

+

+Music data is given in the +"music" context. +For each measure, there is usually +one line of input for each voice. +At the end of the measure, the kind of +bar line +to be used to end the measure is specified. +This section describes the input for generating standard music notation. +Mup can also generate +tablature notation, +and that is covered in the next section. +
+Chords +
+Bar lines +
+Multirests +
+Lyrics +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/muspaper.html b/mup/docs/uguide/muspaper.html new file mode 100644 index 0000000..c7a474a --- /dev/null +++ b/mup/docs/uguide/muspaper.html @@ -0,0 +1,65 @@ + + +Generating blank staff paper + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Generating blank staff paper +

+

+It is possible to use Mup to generate +blank music staff paper. +You simply use an input file that contains +measure spaces, +each ending with an +invisbar. +You can control whether you want +clefs, +time signatures, +braces, +etc., and can control the spacing of staffs using +the scoresep parameter. +Here is a simple input that will generate a page with 8 completely +blank staffs. +

+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
+

+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/mussym.html b/mup/docs/uguide/mussym.html new file mode 100644 index 0000000..e8fdf3c --- /dev/null +++ b/mup/docs/uguide/mussym.html @@ -0,0 +1,51 @@ + + +Music symbols + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Mussym +

+

+While it is possible to place musical symbols +such as fermatas and coda signs using +text statements, +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: +

+rom above 1: 1 "\(ferm)";
+mussym above 1: 1 "ferm";
+

+

+

+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. +

+1: 2e;g;
+mussym above 1: 1 "tr" til 2; 3 "ferm";
+endbar
+

+Picture of Mup output
+

+

+A size can optionally be specified, inside parentheses: +

+mussym (15) above 2: "turn";
+

+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/newscore.html b/mup/docs/uguide/newscore.html new file mode 100644 index 0000000..aaf66fa --- /dev/null +++ b/mup/docs/uguide/newscore.html @@ -0,0 +1,59 @@ + + +Newscore and newpage + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Newscore and newpage +

+

+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: +

+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
+

+

+

+You can temporarily change the indent for the new score +by specifying "leftmargin=num," where num is a floating point +number of inches or centimeters (depending on the current setting of +the units parameter.) +The new score will then be indented by that much, overriding the value +of +the leftmargin parameter. +

+

+In a similar way, you can specify "rightmargin=num," which +will affect +the right margin +on the previous score. This might +be used, for example, if you want a piece to end with a +shorter than normal score. +

+newscore leftmargin=1.2 rightmargin=2.7
+

+The equals sign is optional in these margin overrides. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/noteattr.html b/mup/docs/uguide/noteattr.html new file mode 100644 index 0000000..d88e8d1 --- /dev/null +++ b/mup/docs/uguide/noteattr.html @@ -0,0 +1,196 @@ + + +Note attributes + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Note attributes +

+

+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 +letter, +accidental, +and +octave specifications. +They include: +

+

+

+Small note head +

+

+A note specification can be followed by 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, +the "cue" construct, described later, +may be preferable.) +

+

+Examples: +

+// print the "e" as a small note
+1: 1c e? g;
+bar
+
+// make the second note small
+1: f; ?; g; ;
+bar
+

+Picture of Mup output
+

+

+Note tie +

+

+A "~" can be used to indicate the note is to be tied +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, +the "tie" construct +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. +

+

+Examples +

+1: d~; 8; e~; ; f;
+bar
+
+// tie the g (which also happens
+// to be a "small" note)
+1: 2g+g?~; 4eg?;
+bar
+

+Picture of Mup output
+

+

+Slurs +

+

+A note can also be followed by a list of notes to be slurred to, +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 +accidentals +are specified, even if the note to be slurred +to has an accidental. Examples: +

+// 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
+

+Picture of Mup output
+

+

+If there is only one note in the following chord, it isn't necessary to +explicitly state it within the angle brackets; "<>" will suffice. +

+// slur from c to d, and f to g
+1: c<>; d; f<>; g;
+bar
+

+Picture of Mup output
+

+

+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. +

+

+There are four special "slurs" which are really slides to/from an +indefinite note. They are most commonly used on +tablature staffs, +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 +

+1: 2c</n><d>;d;
+

+

+

+Head shape +

+

+Sometimes you may want to mix head shapes on a single stem. +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 +section on head shapes, +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. +

+1: 2e e+ hs "diam";g;
+

+

+

+Note location tag +

+

+Finally, a +"location tag" +can be associated with a note. This would +enable you to draw things relative to the note. +A note location tag +is set by using an "=" followed by a name. The name can be either: +

    +
  • +a single lower case letter +
  • +an underscore followed by one or more +letters, numbers, and underscores in any combination. +
+The name is arbitrary, and is used as +a tag that can be referred to later. Examples: +
+// associate tag p with note e&
+3: 2c; e& =p g;
+
+// associate tag _end with note f
+2: 1f =_end;
+

+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/octave.html b/mup/docs/uguide/octave.html new file mode 100644 index 0000000..16f3ec4 --- /dev/null +++ b/mup/docs/uguide/octave.html @@ -0,0 +1,47 @@ + + +Octave marks + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Octave marks +

+

+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: +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/oddeven.html b/mup/docs/uguide/oddeven.html new file mode 100644 index 0000000..32114bb --- /dev/null +++ b/mup/docs/uguide/oddeven.html @@ -0,0 +1,62 @@ + + +Different margins for odd/even pages + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Different margins for odd/even pages +

+

+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. +

+

+In the Mup input file, put something like this: +

+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
+

+

+

+Then when printing, print in two passes. First print the odd pages: +

+mupprnt -oodd -DWIDELEFT file.mup
+

+Then turn the paper over and print the even pages: +
+mupprnt -oeven -DWIDERIGHT file.mup
+

+

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/param.html b/mup/docs/uguide/param.html new file mode 100644 index 0000000..7e0e925 --- /dev/null +++ b/mup/docs/uguide/param.html @@ -0,0 +1,2848 @@ + + +Mup Parameters + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+PARAMETERS +

+

+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. +

+

+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 +contexts, +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 +header, footer, and similiar contexts. +

+

+Parameters are set by the following syntax: +

+parameter_name=value
+

+

+

+Several parameters can be set on a single line by separating them with +a semicolon. For example: +

+staffs=2 ; key=2& ; time=2/4
+

+

+

+Parameters can be unset in staff or voice context using +

+unset parameter_name
+

+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. +

+

+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. +

+

Index of parameters

+A B C D E F G K L M N O P R S T U V W

A


+aboveorder
+addtranspose
+

B


+barstyle
+beamslope
+beamstyle
+beloworder
+betweenorder
+bottommargin
+brace
+bracket
+

C


+cancelkey
+chorddist
+clef
+crescdist
+

D


+defoct
+dist
+division
+dyndist
+

E


+endingstyle
+

F


+firstpage
+font
+fontfamily
+

G


+gridfret
+gridsatend
+gridscale
+gridswhereused
+

K


+key
+

L


+label
+label2
+leftmargin
+lyricsalign
+lyricsfont
+lyricsfontfamily
+lyricssize
+

M


+measnum
+measnumfont
+measnumfontfamily
+measnumsize
+

N


+noteheads
+numbermrpt
+

O


+ontheline
+

P


+packexp
+packfact
+pad
+pageheight
+pagesize
+pagewidth
+panelsperpage
+pedstyle
+printmultnum
+

R


+rehstyle
+release
+restcombine
+restsymmult
+rightmargin
+

S


+scale
+scorepad
+scoresep
+size
+stafflines
+staffpad
+staffs
+staffscale
+staffsep
+stemlen
+stemshorten
+swingunit
+sylposition
+

T


+tabwhitebox
+time
+timeunit
+topmargin
+transpose
+

U


+units
+

V


+vcombine
+visible
+vscheme
+

W


+warn
+ +
+

+aboveorder +

+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. +

+

Value: +mussym, +octave, +dyn, othertext, chord, +lyrics, +ending, +reh +

+

Default value: +mussym, octave, dyn & othertext & chord, lyrics, ending, reh +

+

Context: +score, staff +

+

Example:
+aboveorder = mussym, lyrics, dyn, octave, othertext, chord, ending, reh +

+

Related parameters: +beloworder, +betweenorder, +chorddist, +dist, +dyndist +

+
+

+addtranspose +

+specify by what additional interval to transpose the music data. +There is another parameter called just +transpose. +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. +

+

Value: +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 +section on transposition +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. +

+

Default value: +up perfect 1 (i.e., no transposition) +

+

Context: +score, staff +

+

Examples:
+addtranspose = down major 3 +
+addtranspose = up perfect 5 +

+

Related parameters: +key, +transpose +

+
+

+barstyle +

+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. +

+

Value: +a comma-separated list of staff numbers and/or ranges of staff numbers. +Staff numbers can be from 1 to the value of the +"staffs" parameter. +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. +

+

Default value: +each visible staff barred individually +

+

Context: +score +

+

Example:
+barstyle = 1-2, 5-8 +

+

Related parameters: +staffs, +visible +

+
+

+beamslope +

+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. +Cross-staff beams that are between staffs +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 +slope as an interchord attribute +on the first chord of the beamed set. +

+

Value: +0.0 to 1.0 for the factor, and 0.0 to 45.0 for the maximum angle +

+

Default value: +1.0, 20.0 +

+

Context: +score, staff, voice +

+

Example:
+beamslope=0.8,20 +

+
+

+beamstyle +

+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 +Custom Beaming +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 +time parameter +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. +

+

Value: +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. +

+

Default value: +no beams; each note of eighth or shorter duration is individually flagged. +

+

Context: +score, staff, and voice +

+

Examples:
+beamstyle = 4,4,4,4 +
+beamstyle = 2. +
+beamstyle=4+16, 4+16 +
+beamstyle = 2, 2 rs // beam across rests and spaces +
+beamstyle = (4., 4., 4.) // one outer beam per measure, +
+ // with inner beams broken at each dotted quarter duration +
+beamstyle = // turn off beaming +

+
+

+beloworder +

+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. +

+

Value: +mussym, +octave, +dyn, othertext, chord, +lyrics, +pedal +

+

Default value: +mussym, octave, dyn & othertext & chord, lyrics, pedal +

+

Context: +score, staff +

+

Example:
+beloworder = mussym, lyrics, dyn, octave, othertext, chord, pedal +

+

Related parameters: +aboveorder, +betweenorder, +chorddist, +dist, +dyndist +

+
+

+betweenorder +

+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. +

+

Value: +mussym, +dyn, othertext, chord, +lyrics, +

+

Default value: +mussym, dyn & othertext & chord, lyrics +

+

Context: +score, staff +

+

Example:
+betweenorder = mussym, lyrics, dyn & othertext, chord +

+

Related parameters: +aboveorder, +beloworder, +chorddist, +dist, +dyndist +

+
+

+bottommargin +

+sets the amount of white space margin to put at the bottom of each page. +It is specified in inches if the +units parameter +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 +the "scale" parameter. +The parameter name can be abbreviated to just "botmargin" if you wish. +

+

Value: +0.0 to pageheight minus 0.5 inches +

+

Default value: +0.5 inches +

+

Context: +score +

+

Example:
+bottommargin = 0.8 +

+

Related parameters: +leftmargin, +rightmargin, +topmargin +pageheight +units +

+
+

+brace +

+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. +

+

Value: +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 +the "staffs" parameter. +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. +

+

Default value: +no staffs are grouped by braces. +

+

Context: +score +

+

Examples:
+brace = 3-4 +
+brace = 1, 2-3, 4, 5-6 +
+brace = 1-2 ("piano"), 3 ("cello") +
+brace = 1-2 ("Primo", "I") +
+brace = // no braces at all (the default) +

+

Related parameters: +bracket, +label, +label2, +staffs +

+
+

+bracket +

+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. +

+

Value: +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 +the "staffs" parameter. +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. +

+

Default value: +no staffs are grouped by brackets. +

+

Context: +score +

+

Examples:
+bracket = 6-7 +
+bracket = 17, 21-23 +
+bracket = 8-9 ("SATB") +
+bracket = 10-12 ("Strings", "Str") +
+bracket = // no brackets at all (the default) +

+

Related parameters: +brace, +label, +label2, +staffs +

+
+

+cancelkey +

+When set to y, 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 n, the naturals will only be printed if the new key has no +sharps or flats. +

+

Value: +y or n +

+

Default value: +n +

+

Context: +score, staff +

+

Example:
+cancelkey=y +

+

Related parameters: +key +

+
+

+chorddist +

+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 +tempo, dynamic marks, ornaments, etc. +gives details on how to do this. +

+

Value: +a whole number between 0 and 50 inclusive, given in stepsizes. +

+

Default value: +3 +

+

Context: +score, staff +

+

Example:
+chorddist = 4 +

+

Related parameters: +dyndist, +dist, +scorepad, +scoresep +

+
+

+clef +

+sets the clef to use. +Changing a clef may also change the default octave +(see the "defoct" parameter below). +

+

Value: +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 +stafflines parameter +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 +the middle of a measure +using a construct like <<staff clef=bass>> before a note group. +

+

Default value: +treble +

+

Context: +score, staff +

+

Example:
+clef = alto +

+

Related parameters: +defoct, +stafflines +

+
+

+crescdist +

+This parameter is obsolete; it has been replaced by +the dyndist parameter. +

+
+

+defoct +

+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 +the middle of a measure +using a construct like <<staff defoct=5>> before a note group. +

+

Value: +a number from 0 to 9 inclusive. Octave 4 is the octave beginning at middle C. +

+

Default value: +the octave containing the note represented by the middle line of the staff +given the current +clef. +(Octave 5 for frenchviolin and 8treble; +octave 4 for treble, soprano, mezzosoprano, and +alto clefs; octave 3 for treble8, tenor, baritone and bass clefs). +

+

Context: +score, staff, voice +

+

Example:
+defoct = 3 +

+
+

+dist +

+sets minimum distance from staff to place +rom, bold, ital, and boldital items, +and +rehearsal marks. +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, +the chorddist parameter +will be used instead of dist. +This parameter may be overridden on specific items. The sections on +tempo, dynamic marks, ornaments, etc. +and on +rehearsal marks +give details on how to do this. +

+

Value: +a whole number between 0 and 50 inclusive, given in stepsizes. +

+

Default value: +2 +

+

Context: +score, staff +

+

Example:
+dist = 6 +

+

Related parameters: +chorddist, +dyndist, +scorepad, +scoresep +

+
+

+division +

+sets +MIDI +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. +

+

Value: +1 to 1536 +

+

Default value: +192 +

+

Context: +score +

+

Example:
+division = 384 +

+
+

+dyndist +

+sets minimum distance from staff to place +crescendo and decrescendo marks. +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 +tempo, dynamic marks, ornaments, etc. +gives details on how to do this. +

+

Value: +a whole number between 0 and 50 inclusive, given in stepsizes. +

+

Default value: +2 +

+

Context: +score, staff +

+

Example:
+dyndist = 4 +

+

Related parameters: +chorddist, +dist, +scorepad, +scoresep +

+
+

+endingstyle +

+controls how +first and second endings +are placed. +This parameter also controls where +measure numbers +and +rehearsal marks are placed. +A value of "top" means that the endings and similar marks +will be shown only above the top +visible staff. +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. +(See the "barstyle" parameter above.) +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 +brace +or +bracket. +In all cases, at least the top visible staff will +have endings shown above it. +

+

Value: +top, barred, or grouped +

+

Default value: +top +

+

Context: +score +

+

Example:
+endingstyle = grouped +

+

Related parameters: +barstyle, +brace, +bracket, +measnum, +rehstyle, +visible +

+
+

+firstpage +

+specifies what to number the first page. +This value can be overridden by the +-p command line option. +This parameter can only be set before any music or block input. +

+

Value: +1 to 5000 +

+

Default value: +1 +

+

Context: +score +

+

Example:
+firstpage = 12 +

+
+

+font +

+specifies which font to use for +print, left, right, center, and title statements, +and +"with" lists (i.e., strings that are associated with a particular chord). +

+

Value: +rom, ital, bold, or boldital +

+

Default value: +rom +

+

Context: +score, staff, header, footer, header2, footer2, top, bottom, top2, bottom2, block +

+

Example:
+font = boldital +

+

Related parameters: +fontfamily, +lyricsfont, +lyricsfontfamily, +size +

+
+

+fontfamily +

+specifies what font family to use for +print, left, right, center, and title statements +and +"with" lists (i.e., strings that are associated with a particular chord). +

+

Value: +avantgarde, bookman, courier, helvetica, newcentury, palatino, times +

+

Default value: +times +

+

Context: +score, staff, header, footer, header2, footer2, top, bottom, top2, bottom2, block +

+

Example:
+fontfamily=palatino +

+

Related parameters: +font, +lyricsfont, +lyricsfontfamily +

+
+

+gridfret +

+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. +

+

Value: +2 to 99, or not set +

+

Default value: +4 +

+

Context: +score, staff +

+

Example:
+gridfret = 3 +
+gridfret = +

+

Related parameters: +gridsatend, +gridscale, +gridswhereused, +

+
+

+gridsatend +

+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. +

+

Value: +y or n +

+

Default value: +n +

+

Context: +score +

+

Example:
+gridsatend = y +

+

Related parameters: +gridfret, +gridscale, +gridswhereused +

+
+

+gridscale +

+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 +(the gridsatend parameter) +is larger than the default size for those printed with the music +(the gridswhereused parameter). +

+

Value: +0.1 to 10.0 +

+

Default value: +1.0 +

+

Context: +score, staff +

+

Example:
+gridscale = 0.5 +

+

Related parameters: +gridsatend, +gridfret, +gridswhereused, +scale, +staffscale +

+
+

+gridswhereused +

+specifies whether to print guitar grids along with chords +where they appear in the song. If set to "y" each +text item with the chord modifier +will have a grid printed below its name. +

+

Value: +y or n +

+

Default value: +n +

+

Context: +score, staff +

+

Example:
+gridswhereused = y +

+

Related parameters: +gridfret, +gridsatend, +gridscale +

+
+

+key +

+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. +

+

Value: +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 +MIDI file +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. +

+

Default value: +c major +

+

Context: +score, staff +

+

Example:
+key = 3& +
+key = 6# +
+key = c# minor +
+key = d major +

+

Related parameters: +stafflines, +transpose, +addtranspose +

+
+

+label +

+specify a label to be printed to the left of the staff on the next +score. If there is also a +brace +or +bracket +label, that label will +be to the left of this label. +There is a +label2 +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" +

+

Value: +a text string +enclosed in double quotes. +

+

Default value: +enough spaces to produce an indent of 1/2 inch +

+

Context: +score, staff +

+

Example:
+label = "oboe" +

+

Related parameters: +brace, +bracket, +label2 +

+
+

+label2 +

+specify a label to be printed to the left of the staff on all scores after +the first. If there is also a +brace +or +bracket +label, that label will be to the left of this label. +If both the +label +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. +

+

Value: +a text string +enclosed in double quotes +

+

Default value: +no label +

+

Context: +score, staff +

+

Example:
+label2 = "Solo" +

+

Related parameters: +brace, +bracket, +label +

+
+

+leftmargin +

+sets the amount of white space margin to put at the left side of each page. +It is specified in inches if the +units parameter +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 +the "scale" parameter. +

+

Value: +0.0 to pagewidth minus 0.5 inches +

+

Default value: +0.5 inches +

+

Context: +score +

+

Example:
+leftmargin = 0.3 +

+

Related parameters: +bottommargin, +rightmargin, +topmargin, +pagewidth, +units +

+
+

+lyricsalign +

+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. +

+

Value: +0.0 to 1.0 +

+

Default value: +0.25 +

+

Context: +score, staff +

+

Example:
+lyricsalign = 0.1 +

+

Related parameters: +sylposition +

+
+

+lyricsfont +

+sets which font to use for +lyrics. +

+

Value: +rom, ital, bold, boldital +

+

Default value: +rom +

+

Context: +score, staff +

+

Example:
+lyricsfont = ital +

+

Related parameters: +font, +lyricssize +

+
+

+lyricsfontfamily +

+specifies what font family to use for +lyrics. +

+

Value: +avantgarde, bookman, courier, helvetica, newcentury, palatino, times +

+

Default value: +times +

+

Context: +score, staff +

+

Example:
+lyricsfontfamily=helvetica +

+

Related parameters: +font, +fontfamily, +lyricsfont +

+
+

+lyricssize +

+sets point size to use for +lyrics. +

+

Value: +a number from 1 to 100 +

+

Default value: +12 +

+

Context: +score, staff +

+

Example:
+lyricssize = 10 +

+

Related parameters: +lyricsfont, +lyricsfontfamily, +size +

+
+

+measnum +

+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 +(see "endingstyle" parameter). +If set to "n," no measure numbers will be printed. +This parameter does not affect +rehearsal numbers, which are equal to measure numbers when "mnum" is used. +

+

Value: +y or n +

+

Default value: +n +

+

Context: +score +

+

Example:
+measnum = y +

+

Related parameters: +endingstyle, +measnumfont, +measnumfontfamily, +measnumsize, +rehstyle +

+
+

+measnumfont +

+This specifies which font type to use for the automatic measure numbers, +if they are turned on via the +measnum parameter. +

+

Value: +rom, ital, bold, or boldital +

+

Default value: +rom +

+

Context: +score +

+

Example:
+measnumfont=boldital +

+

Related parameters: +measnum, +measnumfontfamily, +measnumsize +

+
+

+measnumfontfamily +

+This specifies which font family to use for the automatic measure numbers, +if they are turned on via the +measnum parameter. +

+

Value: +avantegarde, bookman, courier, helvetica, newcentry, palatino, or times +

+

Default value: +times +

+

Context: +score +

+

Example:
+measnumfontfamily=helvetica +

+

Related parameters: +measnum, +measnumfont, +measnumsize +

+
+

+measnumsize +

+This specifies what size to use for the automatic measure numbers, +in points, if they are turned on via the +measnum parameter. +

+

Value: +1 to 100 +

+

Default value: +11 +

+

Context: +score +

+

Example:
+measnumsize=15 +

+

Related parameters: +measnum, +measnumfont, +measnumfontfamily +

+
+

+noteheads +

+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 +key signature. +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 +headshapes context. +See the examples below for the most common settings for +this parameter. Head shape can be +overridden on an individual chord +by using [hs "shapename"] +before the chord. It can also be +overridden on an individual note +by putting hs "shapename" after the note. +

+

Value: +A string containing either 1 or 7 head shape names. +

+

Default value: +"norm" +

+

Context: +score, staff, voice +

+

Example:
+// This is the setting for the most common shaped note system using 4 shapes. +
+noteheads = "righttri norm rect righttri norm rect diam" +
+ +// This is the setting for a shaped notes system that uses 7 different shapes. +
+noteheads = "isostri semicirc diam righttri norm rect pie" +

+
+

+numbermrpt +

+If set to 'y' +measure repeats +are numbered; if set to 'n' they aren't. +

+

Value: +y or n +

+

Default value: +y +

+

Context: +score, staff +

+

Example:
+numbermrpt = n +

+
+

+ontheline +

+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 +5-line staffs +or +tablature staffs. +Notes for voice 3 are always placed on the line on 1-line staffs, +regardless of the value of this parameter. +

+

Value: +y or n +

+

Default value: +y +

+

Context: +score, staff, voice +

+

Example:
+ontheline=n +

+

Related parameters: +stafflines +

+
+

+packexp +

+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. +

+

Value: +a number from 0.0 to 1.0 inclusive +

+

Default value: +0.8 +

+

Context: +score +

+

Example:
+packexp = 0.95 +

+

Related parameters: +packfact, +pad +

+
+

+packfact +

+specifies how tightly to pack notes together on output. The smaller +the value, the more tightly notes are packed together. +

+

Value: +a number from 0.0 to 10.0 +

+

Default value: +1.0 +

+

Context: +score +

+

Example:
+packfact = 1.4 +

+

Related parameters: +packexp, +pad +

+
+

+pad +

+specifies the amount of padding to be added to notes. +This can be used to control how tightly things are packed together. +Especially if +packexp +and +packfact +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 +the "pad" value that can be specified for individual note groups, +except that it applies to all groups. +

+

Value: +a floating point number of stepsizes, -5.0 to 50.0 +

+

Default value: +0.3333 +

+

Context: +score, staff, voice +

+

Example:
+pad = 1.76 +

+

Related parameters: +packexp, +packfact +

+
+

+pageheight +

+Set the page height. If the +units parameter +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 +pagewidth +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. +

+

Value: +2.0 to 24.0 inches or 5.0 to 61.0 cm +

+

Default value: +11.0 inches +

+

Context: +score +

+

Example:
+pageheight = 9 +

+

Related parameters: +pagewidth, +bottommargin +topmargin, +units +

+
+

+pagesize +

+Set the page size. This is just an alternate way of specifying +pageheight +and +pagewidth +using the common names for paper sizes rather than specifying in +inches or cm. +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. +

+

Value: +letter, legal, flsa, halfletter, a4, a5, a6; optionally followed by +portrait or landscape. +

+

Default value: +letter +

+

Context: +score +

+

Example:
+pagesize = a4 +
+pagesize = legal landscape +

+

Related parameters: +pageheight, +pagewidth, +panelsperpage +

+
+

+pagewidth +

+Set the page width. If the +units parameter +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 +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. +

+

Value: +2.0 to 24.0 inches or 5.0 to 61.0 cm +

+

Default value: +8.5 inches +

+

Context: +score +

+

Example:
+pagewidth = 6.5 +

+

Related parameters: +pageheight, +leftmargin, +rightmargin, +units +

+
+

+panelsperpage +

+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 +pageheight +and +pagewidth +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 +-o command line option +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. +

+

Value: +1 or 2 +

+

Default value: +1 +

+

Context: +score +

+

Example:
+panelsperpage=2 +

+

Related parameters: +pageheight, +pagewidth +

+
+

+pedstyle +

+Specifies whether to display +piano pedal marks +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. +

+

Value: +line, pedstar, or alt pedstar +

+

Default value: +line +

+

Context: +score, staff +

+

Example:
+pedstyle = pedstar +

+
+

+printmultnum +

+If set to 'y' +multirests +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. +

+

Value: +y or n +

+

Default value: +y +

+

Context: +score, staff +

+

Example:
+printmultnum = n +

+
+

+rehstyle +

+Specifies whether to enclose +rehearsal marks +inside box, inside a circle, or just as plain text. +

+

Value: +boxed, circled, or plain +

+

Default value: +boxed +

+

Context: +score, staff +

+

Example:
+rehstyle = circled +

+

Related parameters: +endingstyle +

+
+

+release +

+Specifies how soon (in milliseconds) before the full time value of note +to release the note when generating +MIDI output. +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 +the middle of a measure +using a construct like <<score release=50>> before a note group. +

+

Value: +0 to 500 +

+

Default value: +20 +

+

Context: +score, staff, voice +

+

Example:
+release = 40 +

+
+

+restcombine +

+If the given number of measures of rest occur in a row, +they will be replaced by a +multirest. +This parameter can be overridden by the +-c command line option. +See the +description of the -c option +for more complete information on how the combining is done. +

+

Value: +2 to 1000 or nothing +

+

Default value: +not set +

+

Context: +score +

+

Example:
+restcombine = 5 +
+restcombine = // turn off combining +

+
+

+restsymmult +

+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. +

+

Value: +y or n +

+

Default value: +n +

+

Context: +score, staff +

+

Example:
+restsymmult = y +

+

Related parameters: +printmultnum +

+
+

+rightmargin +

+sets the amount of white space margin to put at the right side of each page. +It is specified in inches if the +units parameter +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 +the "scale" parameter. +

+

Value: +0.0 to pagewidth minus 0.5 inches +

+

Default value: +0.5 inches +

+

Context: +score +

+

Example:
+rightmargin = 0.3 +

+

Related parameters: +bottommargin, +leftmargin, +topmargin, +pagewidth, +units +

+
+

+scale +

+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. +

+

Value: +A number between 0.1 and 10.0 +

+

Default value: +1.0 +

+

Context: +score +

+

Example:
+scale=0.95 +

+

Related parameters: +packfact, +packexp, +staffscale +

+
+

+scorepad +

+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 +scoresep parameter, +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. +

+

Value: +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. +

+

Default value: +2,2 +

+

Context: +score +

+

Example:
+scorepad = 5 +
+scorepad = -1 +
+scorepad = 3,10 +

+

Related parameters: +scoresep, +staffpad, +staffsep +

+
+

+scoresep +

+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 +scorepad parameter, +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 "newpage" command +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. +

+

Value: +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. +

+

Default value: +12,20 +

+

Context: +score +

+

Examples:
+scoresep = 25 +
+scoresep = 9,15 +

+

Related parameters: +scorepad, +staffpad, +staffsep +

+
+

+size +

+specifies what point size to use for text in +print, title, left, right, and center statements, +and +"with" lists (i.e., strings that are associated with a particular chord). +

+

Value: +a number from 1 to 100 inclusive +

+

Default value: +12 +

+

Context: +score, staff, header, footer, header2, footer2, top, bottom, top2, bottom2, block +

+

Example:
+size = 9 +

+

Related parameters: +font, +fontfamily, +lyricssize +

+
+

+stafflines +

+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 +clef +and +key signature +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 +MIDI output. +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 +clef parameter +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. +

+

Value: +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: +key, +transpose, +addtranspose, +clef, +beamstyle, +and +defoct. +

+

Default value: +5 +

+

Context: +score, staff +

+

Examples:
+stafflines=1 +
+stafflines=5n +
+stafflines = tab // standard guitar tablature staff +
+stafflines = tab ( g3 d3 a2 e2 ) // standard bass guitar +
+stafflines = tab (d# g b3 g'3) +

+

Related parameters: +clef, +key, +transpose, +addtranspose +

+
+

+staffpad +

+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 +staffsep parameter. +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. +

+

Value: +a whole number between negative the height of the page +and the height of a page, in stepsizes. +

+

Default value: +0 +

+

Context: +score, staff +

+

Example:
+staffpad = -2 +

+

Related parameters: +scorepad, +scoresep, +staffsep +

+
+

+staffs +

+specifies the number of staffs. It is possible that not all of these staffs +will be printed (see +the "visible" parameter +below and +the -s command line argument). +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 +the "visible" parameter +when you want to change which staffs are actually printed, +rather than changing the number of staffs. +

+

Value: +a number between 1 and 40 inclusive. +

+

Default value: +1 +

+

Context: +score +

+

Example:
+staffs = 12 +

+

Related parameters: +visible +

+
+

+staffscale +

+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 +headers and footers, +unaffected. +

+

Value: +0.1 to 10.0 +

+

Default value: +1.0 +

+

Context: +score, staff +

+

Example:
+staffscale=0.75 +

+

Related parameters: +scale +

+
+

+staffsep +

+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. +

+

Value: +a number from 6 to the height of the page in stepsizes +

+

Default value: +10 +

+

Context: +score, staff +

+

Example:
+staffsep = 14 +

+

Related parameters: +scorepad, +scoresep, +staffpad +

+
+

+stemlen +

+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 +the len attribute in backets before the chord. +

+

Value: +0.0 to 100.0 +

+

Default value: +7.0 +

+

Context: +score, staff, voice +

+

Example:
+stemlen = 0 // to make all notes stemless +

+
+

+stemshorten +

+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. +

+

Value: +0.0 to 2.0 +

+

Default value: +1.0 +

+

Context: +score, staff, voice +

+

Example:
+stemshorten = 0 // never shorten any stems +

+
+

+swingunit +

+This parameter only affects +MIDI output. +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 +time signature +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. +

+

Value: +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. +

+

Default value: +not set +

+

Context: +score, staff, voice +

+

Example:
+swingunit = 4 +
+swingunit = // turn off swing +

+

Related parameters: +timeunit +

+
+

+sylposition +

+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 +lyricsalign parameter, +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. +

+

Value: +-100 to 100 +

+

Default value: +-5 +

+

Context: +score, staff +

+

Example:
+sylposition = -4 +

+

Related parameters: +lyricsalign +

+
+

+tabwhitebox +

+says whether or not to put a small white box behind each fret number on +tablature staffs. +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. +

+

Value: +y or n +

+

Default value: +n +

+

Context: +score, staff, voice +

+

Examples:
+tabwhitebox = y +

+

Related parameters: +stafflines +

+
+

+time +

+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 +the timeunit parameter +and +the beamstyle parameter +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). +

+

Value: +either a ratio of the form N/D or the word "cut" or "common." If the ratio +form is used, N must be between 1 and 99 inclusive, +and D 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. +

+

Default value: +4/4 +

+

Context: +score +

+

Examples:
+time = 6/8 +
+time = cut +
+time = 13/16n +
+time = 2+3+4 / 8 // additive numerator +
+time = 3/4 + 4/4 // fractions added together +
+time = 4/4 3/4 // alternating +
+time = 3/4 6/8 y // alternating, printing time sig on every measure +

+

Related parameters: +timeunit +

+
+

+timeunit +

+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 +time signature +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. +

+

Value: +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 +the time parameter. +Setting the time parameter will set the timeunit to the value +used most recently for that time signature. +

+

Default value: +The denominator (bottom number) of the time signature +

+

Context: +score, staff, voice +

+

Examples:
+timeunit = 2 +
+timeunit = 4. +
+timeunit = 2 + 8 +

+

Related parameters: +swingunit, +time +

+
+

+topmargin +

+sets the amount of white space margin to put at the top of each page. +It is specified in inches if the +units parameter +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 +the "scale" parameter. +

+

Value: +0.0 to pageheight minus 0.5 inches +

+

Default value: +0.5 inches +

+

Context: +score +

+

Example:
+topmargin = 0.8 +

+

Related parameters: +bottommargin, +leftmargin, +rightmargin, +pageheight, +units +

+
+

+transpose +

+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. +

+

Value: +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 +section on transposition +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 +addtranspose. +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. +

+

Default value: +up perfect 1 (i.e., no transposition) +

+

Context: +score, staff +

+

Examples:
+transpose = up minor 3 +
+transpose = down perfect 4 +

+

Related parameters: +addtranspose, +key +

+
+

+units +

+Specifies whether margin and page size parameters are specified +in inches or in centimeters. +

+

Value: +inches or cm +

+

Default value: +inches +

+

Context: +score +

+

Example:
+units = cm +

+

Related parameters: +topmargin, +bottommargin +leftmargin, +rightmargin, +pageheight, +pagewidth +

+
+

+vcombine +

+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 +MIDI +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 +1,2 or 1-3 or 2-3. +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 +vscheme parameter +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. +

+

Value: +comma-separated list of voices or voice ranges, or nothing, +optionally followed by nooverlap, shareone, or overlap. +

+

Default value: +not set +

+

Context: +score, staff +

+

Example:
+vcombine=3,1-2 shareone +
+vcombine= // turn off combining +

+

Related parameters: +vscheme +

+
+

+visible +

+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 +tempo, dynamics, and similar marks +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 +MIDI output +is generated, this parameter controls whether the staff or voice +is audible, so you can control which voices are played. +The -s command line argument can also be used +to control which staffs are printed or played. +

+

Value: +y, n, or whereused +

+

Default value: +y +

+

Context: +score, staff, voice +

+

Example:
+visible = n +

+

Related parameters: +brace, +bracket, +endingstyle, +staffs +

+
+

+vscheme +

+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 +explicitly forced +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 +stem direction +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. +

+

Value: +1, 2o, 2f, 3o, or 3f +

+

Default value: +1 +

+

Context: +score, staff +

+

Example:
+vscheme = 2f +

+

Related parameters: +vcombine +

+
+

+warn +

+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. +

+

Value: +y or n +

+

Default value: +y +

+

Context: +score +

+

Example:
+warn = n +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/pedal.html b/mup/docs/uguide/pedal.html new file mode 100644 index 0000000..44824c1 --- /dev/null +++ b/mup/docs/uguide/pedal.html @@ -0,0 +1,50 @@ + + +Piano pedal marks + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Piano pedal marks +

+

+Piano pedal marks are somewhat different than +other similar Mup statements. +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. +

+

+Some examples may help: +

+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
+

+Picture of Mup output
+

+

+See also the "pedstyle" parameter. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/phrase.html b/mup/docs/uguide/phrase.html new file mode 100644 index 0000000..2c20466 --- /dev/null +++ b/mup/docs/uguide/phrase.html @@ -0,0 +1,89 @@ + + +Phrase marks + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Phrase marks +

+

+If there is only one voice, specifying place for a phrase just tells +Mup where to draw the phrase mark. If there are +two or more voices, +and a place 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. +

+

+If no place 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. +

+

+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). +

+

+Some examples: +

+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
+

+Picture of Mup output
+

+

+Phrase marks are sometimes used on +tablature staffs in conjunction with slides. +

+score staffs=2
+staff 2 stafflines=tab
+music
+
+2: a3<>;a4;e4<>;e2;
+phrase above 2: 1 til 2; 3 til 4;
+bar
+

+Picture of Mup output
+

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/pianored.html b/mup/docs/uguide/pianored.html new file mode 100644 index 0000000..ce385e1 --- /dev/null +++ b/mup/docs/uguide/pianored.html @@ -0,0 +1,73 @@ + + +Automatic piano reduction + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Automatic piano reduction +

+

+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: +

+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
+

+Picture of Mup output
+

+

+This can also be done using +chord-at-a-time input style: +

+// 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
+

+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/prnttext.html b/mup/docs/uguide/prnttext.html new file mode 100644 index 0000000..2d0d3d9 --- /dev/null +++ b/mup/docs/uguide/prnttext.html @@ -0,0 +1,277 @@ + + +"Mup commands for printing text + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Printing commands +

+

+There are several commands for printing text. +There are four commands that have similar formats, +differing only in how they justify text. +

+print location "text"
+left location "text"
+right location "text"
+center location "text"
+

+

+

+The location is optional. If the location is omitted, the "print" +command will cause the text 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. +

+

+The location 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 text is printed on that line with the given justification style. +

+

+The other way to specify a location 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: +

+right (25, 4) "something"
+

+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. +

+

+Here are some other examples: +

+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"
+

+

+

+Another type of print command +is "title." The full format of this command is: +

+title fontfamily font size  "text1"  "text2"  "text3"
+

+However, only the word "title" and one quoted text string are required. +The fontfamily, if specified, has one of the values valid for +the "fontfamily" parameter +(avantgarde, bookman, courier, helvetica, +newcentury, palatino, or times). The default is the value of the "fontfamily" +parameter. +The font, if specified, has one of the values valid for the "font" +parameter (rom, bold, ital, or boldital). If no font is specified +the default is the value of +the "font" parameter. +The optional size is a point size within parentheses. +If not specified, the default is the value of +the "size" parameter. +

+

+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. +

+

+Some samples: +

+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"
+

+

+

+The final command for printing text is +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 +fontfamily, +font, +and +size +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: +
+ justify_type paragraph fontfamily font (size) "string" +
+Only the keyword "paragraph" and the string are required. +Here are some example paragraphs: +

+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."
+

+Picture of Mup output
+

+

+Sometimes you may want to mix +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 +font, +size, +and +fontfamily, +which will affect the appearance of +the following text. A block can also contain +"newscore" or "newpage" commands. +Using "newscore" will cause vertical space to be added, +as would be used to separate scores. The amount of space is affected +by the +scoresep +and +scorepad +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. +

+

+Here is an example of a block. +

+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
+

+Picture of Mup output
+

+

+The printing commands may occur in the +header, footer, header2, footer2, top, bottom, top2, bottom2, +block, +and +music +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. +

+

+Including raw PostScript +

+

+There is another command that looks a lot like the printing commands, +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 +

+postscript optional_location "raw PostScript"
+

+As with the other print commands, if the location is omitted, +the current location is used. +

+

+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. +

+

+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. +

+

+As a simple example, you might include an Encapsulated PostScript file +near the lower left corner of the current page using +

+postscript "50 50 translate (file.eps) run"
+

+

+

+Or you could print a message in red italics +near the bottom of the page like this: +

+postscript (70, 20) "
+              1 0 0 setrgbcolor
+              /NewCenturySchlbk-Italic findfont
+              16 scalefont setfont
+              (Photocopying prohibited) show
+              "
+

+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/pstools.html b/mup/docs/uguide/pstools.html new file mode 100644 index 0000000..916037e --- /dev/null +++ b/mup/docs/uguide/pstools.html @@ -0,0 +1,40 @@ + + +Converting Mup files to other formats + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Converting Mup files to other formats +

+

+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. +

+

+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 +panelsperpage parameter, +and "psselect" which prints a subset of pages. +

+

+You can check the +user donated programs page on Arkkra's web site +for other programs for processing Mup input or output. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/register.html b/mup/docs/uguide/register.html new file mode 100644 index 0000000..dbec127 --- /dev/null +++ b/mup/docs/uguide/register.html @@ -0,0 +1,39 @@ + + + +Mup shareware registration form + + + +
+Mup is SHAREWARE.  You can try out a copy for free, but if you decide
+to keep and use it, you must register by filling out the form below
+and sending the form and cash, check, or money order to:
+                Arkkra Enterprises
+                P. O. Box 315
+                Warrenville, IL  60555    USA
+
+Name______________________________________________________________
+
+Address___________________________________________________________
+
+City_____________________________ State/Province__________________
+
+Zip code/Postal code_____________________ Country_________________
+
+Email address (please print clearly)______________________________
+
+How did you find out about Mup?___________________________________
+
+__________________________________________________________________
+
+___Linux  ___ Windows/MS-DOS  ___Mac  ___Other____________________
+
+Would you like to join the Mup users mailing list? ___ Yes  ___ No
+
+___ Mup Version 5.3 Registrations.........................$29 each
+			(Illinois residents, add $2.18 sales tax)
+(For credit card payment, see http://www.arkkra.com/doc/credtcrd.html)
+
+ + diff --git a/mup/docs/uguide/roll.html b/mup/docs/uguide/roll.html new file mode 100644 index 0000000..11716b3 --- /dev/null +++ b/mup/docs/uguide/roll.html @@ -0,0 +1,81 @@ + + +Rolls + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Rolls +

+

+Rolls can be specified with the "roll" statement, which has a format: +

+roll staff voice : timeval;
+

+

+

+A simple example would be: +

+roll 2 1: 3;
+

+which indicates that a roll is to be placed on the chord at count 3 of +staff 2 voice 1. +As usual, if the voice is omitted, voice 1 is assumed. +

+

+Multiple rolls in a measure can be listed on a single statement if they are +associated with the same voice. For example: +

+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
+

+Picture of Mup output
+would produce rolls on the chords on counts 1, 2, and 3. +

+

+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: +

+1: 4.r;8g+b+d++ tie;2;
+2-3: 4.ceg;8gbd+ tie;2;
+roll 1 1 to 3 1: 2.5;
+bar
+

+Picture of Mup output
+The roll would extend from voice 1 of staff 1 to voice 1 of staff 3. +

+

+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. +

+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
+

+Picture of Mup output
+

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/running.html b/mup/docs/uguide/running.html new file mode 100644 index 0000000..2d415d8 --- /dev/null +++ b/mup/docs/uguide/running.html @@ -0,0 +1,90 @@ + + +Running Mup + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+RUNNING MUP +

+

+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. +

+

+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. +

+

+Mupmate +

+

+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. +

+

+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". +

+

+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. +

+

+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. +

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/shaped.html b/mup/docs/uguide/shaped.html new file mode 100644 index 0000000..7a45842 --- /dev/null +++ b/mup/docs/uguide/shaped.html @@ -0,0 +1,390 @@ + + +Shaped notes + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+SHAPED NOTES +

+

+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. +

+

+Headshapes context +

+

+The headshapes context +is used in conjuction with the +noteheads parameter +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 +noteheads parameter +to access them. However, it is still important to understand +what the headshapes context can contain, +to understand how the builtin values work. +

+

+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. +

+

+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.) +

+

+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 +notehead parameter +and for +overriding chord +and +note shapes. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
"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"
"slash" "fillslashhead slashhead slashhead dwhslashhead"
"allslash" "fillslashhead fillslashhead fillslashhead fillslashhead"
+ +

+

+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: +
+

+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
+
+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. +

+

+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: +

+headshapes
+	"x" "xnote xnote diamond diamond"
+

+

+

+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. +

+

+Noteheads parameter +

+

+The noteheads parameter +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 +

+noteheads = "norm"
+

+

+

+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 +key signature. +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. +

+

+You can get the most common shaped note system using 4 shapes using: +

+noteheads = "righttri norm rect righttri norm rect diam"
+

+There are several shaped notes systems using 7 different shapes. +One such system is specified by: +
+noteheads = "isostri semicirc diam righttri norm rect pie"
+

+

+

+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. +

+

+

+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
+

+Picture of Mup output
+

+

+Overriding chord note heads +

+

+It is possible to override what note shape to use for a chord, +by giving "hs" followed by a head shape name from the headshapes context, +inside square brackets. +Thus +

+	[hs "righttri"]
+

+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. +

+

+The hs specification can be used along with other things that can go in the +square brackets. For example, +

+	[hs "blank"; len 0]
+

+would use blankheads and no stem, resulting in no chord being printed at all! +

+

+Overriding individual note heads +

+

+If you want to override the note head shape to be used for one specific +note in a chord, you use hs followed by the head shape name +as a string after the note. +

+1: cg e+ hs "diam"; f a hs "x" c+; 2ge+;
+bar
+

+Picture of Mup output
+

+

+Putting it all together to use shaped notes +

+

+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. +

+

+Since fret numbers are used rather than note heads on +tablature staffs, +the only head shape name that is allowed is "allx." +which is used for "muffled" notes. +

+

+Here is a simple example of shaped notes, using the common 4-shape system. +

+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
+

+Picture of Mup output
+

+

+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. +

+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
+

+Picture of Mup output
+

+

+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. +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/sharehd.html b/mup/docs/uguide/sharehd.html new file mode 100644 index 0000000..592c740 --- /dev/null +++ b/mup/docs/uguide/sharehd.html @@ -0,0 +1,25 @@ + + +Forcing shared noteheads + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Forcing shared noteheads +

+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/slashmrk.html b/mup/docs/uguide/slashmrk.html new file mode 100644 index 0000000..0036924 --- /dev/null +++ b/mup/docs/uguide/slashmrk.html @@ -0,0 +1,50 @@ + + +Diagonal slash marks + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Diagonal slash marks +

+

+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 +noteheads parameter. +

+noteheads = "allslash"
+

+or if you want to use hollow slashes for half notes and longer +
+noteheads = "slash"
+

+Usually such slash marks do not include a stem, +so you may wish to also set +
+stemlen=0
+

+

+

+If you just want specific chords to be slashes, you can use the +chord head shape override: +

+1: b;[ hs "allslash"; len 0 ]... ;;;
+bar
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/stuff.html b/mup/docs/uguide/stuff.html new file mode 100644 index 0000000..57bb1d4 --- /dev/null +++ b/mup/docs/uguide/stuff.html @@ -0,0 +1,293 @@ + + +"Tempo, dynamic marks, ornaments, etc." + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+TEMPO, DYNAMIC MARKS, ORNAMENTS, ETC. +

+

+General information +

+

+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: +

+mark_type place staff(s) distance : begintime text duration;
+

+

+

+The mark_type can be any of the following: +

+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
+
+

+

+The place is as for +lyrics: +above, below, or between. +There are some restrictions, as summarized below: +

+                       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
+
+

+

+Octave marks +must include a place of above or below. +For all the other mark_types, the place is optional. For +phrase, +if place is not specified, Mup determines it +on a case-by-case basis depending on the location of the notes. +

+

+As with musical data or lyrics, the staff 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. +

+

+The staff 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. +

+

+Here are some examples: +

+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:
+

+

+

+The +distance is optional. It is specified by the keyword "dist" followed +by a number. This number overrides the +dist, +chorddist, +or +dyndist +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. +

+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
+

+Picture of Mup output
+

+

+After the colon comes one or more items to be printed. Each item contains +at least a begintime specification. Some may also contain a +text string +and/or +a duration. Each item ends with a semicolon. A newline ends the list of items. +

+

+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 +time signature +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 +time signatures +that are the addition of two or more fractions, like 4/4 + 3/8, +a "beat" is given by the largest denominator. +

+

+Since grace notes effectively take zero time, special notation is used +to place something relative to a grace note. The begintime can be +followed by a number of grace notes to "back up" from the beat. +The number is a negative number enclosed in parentheses. +

+

+The beat time value can optionally be followed by +an offset, in stepsizes. +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: +

+rom above all: 0 [-3.5] "Allegro";
+

+which would place the "Allegro" 3.5 stepsizes left of the beginning +of the measure. +

+

+The grace note back up, if any, must occur before the +stepsize offset, if any. +For example: +

+1: c; [grace] 8d; []e; []f; 2.g;
+ital above 1: 2(-3)[+1] "cresc.";
+bar
+

+Picture of Mup output
+would find the chord at or closest to count 2, +and back up 3 grace notes from there, then move right by 1 stepsize. +

+

+For items that include a duration, the duration tells the ending point of +the item. A duration is specified by: +

+til Mm + N
+

+where M is a number of +bar lines +to cross, and N 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: +
+til 3	// until beat 3 of current measure
+til 1m+2   // until beat 2 of next measure
+til 1m   // until next bar line
+

+

+

+Whether the text and duration are allowed or required depends on the mark_type, +as summarized below: +

+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
+
+

+

+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 +aboveorder, +beloworder, +or +betweenorder +parameters. +

+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
+
+

+

+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. +
+Text +
+Music symbols +
+Phrase marks +
+Crescendo and decrescendo marks +
+Octave marks +
+Piano pedal marks +
+Rolls +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/tabstaff.html b/mup/docs/uguide/tabstaff.html new file mode 100644 index 0000000..b3f8d64 --- /dev/null +++ b/mup/docs/uguide/tabstaff.html @@ -0,0 +1,394 @@ + + +Tablature notation + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+TABLATURE NOTATION +

+

+Mup can print tablature staffs. Tablature notation is commonly used for +guitar and several other instruments. Mup supports tablature for 1 to 9 +strings. +

+

+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 +(see the "visible" parameter). +You should specify the appropriate +clef +and +key signature +for the tabnote staff, so that Mup can make the best derivation. +

+

+Specifying a tablature staff +

+

+To set up a tablature staff, you use the +stafflines parameter. +To get a standard 6-line guitar tablature staff, you can just say +

+score
+	staffs=2
+staff 2
+	stafflines = tab
+

+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 +stafflines parameter +to "tab" marks staff 2 as a tablature staff. +

+

+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: +

+stafflines = tab (e a d& g)
+

+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 +octave number +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 +
+stafflines = tab (e5 b g d a3 e'3)
+

+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, +but it also automatically +transposes +the +MIDI output +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, +
+score
+	staffs = 2
+staff 2
+	stafflines = tab
+

+is equivalent to +
+score
+	staffs=2
+staff 2
+	stafflines = tab (e5 b g d a3 e'3)
+staff 1
+	ifdef MIDI transpose = down perfect 8 endif
+

+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. +

+

+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, +

+stafflines = tab (g3 d3 a2 e2)
+

+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. +

+

+Music input on tablature staffs +

+

+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: +

+2: d4; d5a3; b0 d(5); e2(b3)g2;
+bar
+

+Picture of Mup output
+

+

+Time values +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: +

+2: 4.e5; ;8;b2;
+bar
+

+Picture of Mup output
+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. +

+

+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. +

+

+Chord attributes +

+

+Any chord on a tablature staff can be preceded by a list of +chord attributes +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 +MIDI. +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 N] +will cause N slashes to be printed below the chord on the tablature +staff, as well as +slashes +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. +

+

+Ties +

+

+From an input point of view, +ties +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. +

+

+Slides +

+

+In Mup input, +slides are shown with <>, rather like +slurs +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: +

+2: a5<>; a6; d3<>; d2;
+bar
+
+2: b4</n>; e3<\n>; a2<n/>; e'5<n\>;
+bar
+

+Picture of Mup output
+

+

+Bends +

+

+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: +

+2: e4 "full"; e "1/2"; 2e "1 1/2";
+bar
+

+Picture of Mup output
+

+

+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, +this indicates a prebend, +whereas if only a bend is specified, this indicates a normal bend. +

+

+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. +

+

+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: +

+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
+

+Picture of Mup output
+

+

+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. +

+

+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: +

+1: e ^f; f; b ^c5; c#5;
+bar
+
+1: d+^e+ g^a; e+a; g ^/; c ^/ c+^/;
+bar
+

+Picture of Mup output
+

+

+Miscellaneous +

+

+Note attributes of ~ for tie, ? for a small note, and = for a tag work the +same on tablatures staffs as on non-tablature staffs. +

+

+If bm, ebm, or esbm are given on tablature staffs they are +transferred to the tabnote staff and used for +custom beaming +there. +Items in "with" lists inside [ ] +are also copied to the tabnote staff. +In general, unless otherwise specified here, +if you want items such as +tempo and dynamic marks +to appear on both tablature and tabnote staff, you +have to specify them for both staffs. +

+

+The +"alt" inter-chord attribute +is not allowed on tablature staffs. +

+

+When there is a tablature staff, the +MIDI +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. +

+

+If a +capo is being used, it probably better to declare a +transposition +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. +The automatic MIDI octave tranposition for standard guitar +will also then still apply, on top of your transposition. +

+

+If you specify an +octave mark +(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. +

+

+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 +phrase marks +for more details. +

+

+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. +

+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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/tags.html b/mup/docs/uguide/tags.html new file mode 100644 index 0000000..0a52157 --- /dev/null +++ b/mup/docs/uguide/tags.html @@ -0,0 +1,224 @@ + + +Location Tags + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Location tags +

+

+A location tag is associated with a +note, +chord, +or +barline. +It can then be referenced in order to place a second object, like a comment +or dotted line, relative to the first object. +

+

+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: +

+c.n	// north of tag c
+_xyz.e	// east of tag _xyz
+x.x	// x coordinate of tag x
+

+

+

+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. +

+

+Tag names can be re-used. The value of a tag will always be its most +recent definition. +

+

+There are also several "pre-defined" tags. They are: +

+
+_page +
+the entire page +
+_win +
+the available part of the page +
+_cur +
+the current location +
+

+

+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. +

+

+The _win tag +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. +

+

+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. +

+

+Location tags can be referenced by a number of commands, including those +for +printing text, +or +drawing lines or curves. +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: +

+(g.x, g.y)	// x and y of tag "g"
+(_tag.w, _item.n)   // west of tag "_tag" and
+                   // north of tag "_item"
+

+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. +

+

+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. +

+(g.x + 4.5, g.y + 4.5)
+

+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: +
+(k.w - 1.3, m.n - 2)
+

+refers to a point 1.3 stepsizes to the left of the +west edge of k and 2 stepsizes below the top of m. +

+

+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: +

+(q.x + time 1, q.y + 2)
+

+If the +time signature +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. +

+

+In the case of a +tag associated with a bar line, +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. +

+

+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. +

+

+The various kinds of offsets can be combined. +

+( _pp + 1.2 - time 3.5, _zz + 2)
+

+

+

+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: +

+(10, 20)
+

+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. +

+

+It is possible to specify multiple offsets of the same type, although +this is rarely, if ever, useful. Thus the following are equivalent: +

+( f.x + 1 - 0.5 + time 1 - time 0.5, f.s + .3 - .1)
+( f.x + 0.5 + time 0.5, f.s + .2)
+

+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/tempochg.html b/mup/docs/uguide/tempochg.html new file mode 100644 index 0000000..e94ab8c --- /dev/null +++ b/mup/docs/uguide/tempochg.html @@ -0,0 +1,68 @@ + + +Marking complicated tempo changes + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Marking complicated tempo changes +

+

+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: +

+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
+

+Picture of Mup output
+

+

+Note that if you want a piece to be played in swing time, +you may also want to set the +swingunit parameter, +which will make the MIDI output use swing time. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/textmark.html b/mup/docs/uguide/textmark.html new file mode 100644 index 0000000..0b744be --- /dev/null +++ b/mup/docs/uguide/textmark.html @@ -0,0 +1,233 @@ + + +Mup Text Marks + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Text +

+

+The four forms of Mup text statements +(rom, bold, ital, and boldital) operate identically except for the font +which is used. +

+

+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 +the "fontfamily" parameter +(avantgarde, bookman, courier, helvetica, +newcentury, palatino, or times), with the default being the value of +the "fontfamily" parameter. +

+

+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 +the "size" parameter +for the given staff, or for the score if the staff is specified by "all." +

+

+Chord, analysis, figured bass, and dynamics +

+

+The final optional qualifier specifies special treatment of the text. +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 +the "chorddist" parameter. +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 place for chord and dyn is above, whereas the default +for the others is below. +

+

+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. +

+

+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. +

+

+If the +transpose +or +addtranspose +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 +music characters +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. +

+

+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 \/. +

+

+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 \:. +

+

+Here is an example showing chord, analysis, and figbass: +

+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
+

+Picture of Mup output
+

+

+If a music symbol occurs inside an ital or boldital string, +the music symbol will automatically be made italics, +to match the rest of the string. +

+

+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. +

+

+Here are some examples of text: +

+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
+

+Picture of Mup output
+

+

+Grids +

+

+If the +gridswhereused parameter +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. +

+

+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: +

+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
+

+Picture of Mup output
+

+

+If +transposition +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. +

+

+If you supply more than one grid definition for the same chord name, +Mup uses the last one. This allows you to easily +"include" a file +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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/textstr.html b/mup/docs/uguide/textstr.html new file mode 100644 index 0000000..00b5952 --- /dev/null +++ b/mup/docs/uguide/textstr.html @@ -0,0 +1,495 @@ + + +Text Strings + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+TEXT STRINGS +

+

+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: +

+"A \"word\" in quotes"
+

+

+

+If you want an actual backslash in a string, it must be entered as two +backslashes. +

+

+You can concatenate strings with a + sign. Thus the following are equivalent: +

+"this is a string"
+"this is " + "a string"
+

+

+

+Special characters +

+

+A string can also contain special +music characters. +These are specified +by \(xxx), where the xxx is a code from the following table: +

+

+Clef +

+
+gclef       G clef (treble clef)
+fclef       F clef (bass clef)
+cclef       C clef (used for alto clef, tenor clef, etc.)
+
+

+Time Signature +

+
+com         common time
+cut         cut time
+
+

+Accidentals +

+
+flat        flat
+dblflat     double flat
+sharp       sharp
+dblsharp    double sharp
+nat         natural
+
+

+Notes +

+
+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
+
+

+Noteheads +

+
+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
+
+

+Rests +

+
+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
+
+

+Pedal +

+
+begped      begin pedal mark
+endped      end pedal mark
+pedal       pedal up/down mark
+
+

+Ornaments +

+
+tr          trill
+mor         mordent
+invmor      inverted mordent
+turn        turn
+invturn     inverted turn
+
+

+Miscellaneous +

+
+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
+
+
+music characters +
+

+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. +

+

+Various non-ASCII characters +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: +

+ 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
+
+

+

+There is one additional special characters, +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 +lyrics +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. +

+

+Font and size changes +

+

+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. +

+       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
+
+Some of the +special characters +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. +

+

+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 +section on "Installing other fonts." +

+

+The point size can also be changed. (A "point" is about 1/72 of an inch.) +

+   Code                   Meaning
+
+\s(N)    change to point size N
+\s(+N)   increase point size by N points
+\s(-N)   decrease point size by N points
+\s(PV) or \s(previous)	revert to previous size
+
+
+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 +lyrics, +where font and size information is maintained separately +for each staff and verse, and carried forward from measure to measure, and +rehearsal marks, +where the information is also carried forward. +The default values can be set as +described in the "Parameters" section. The +music symbols +are affected by size changes. +If a music symbol follows italics or bolditalics characters, it will be +made italics to match. +

+

+Here are some examples of strings: +

+"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"
+

+

+

+Horizontal and vertical motion +

+

+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 +staff labels, +which you may want +to make multi-line, to keep them from becoming excessively wide. +For example: +

+"Violins\nI&II"
+

+

+

+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 +special characters, +described earlier in this section, +rather than trying to construct them using the plain letter, +a backspace, and the mark. +

+

+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_". +

+

+Vertical motion within a string +can be specified using "\v(N)" +where N 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. +

+

+Piled text, for superscripts, subscripts, etc. +

+

+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 +figured bass +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: +

+"Text\:superscript subscript\: back to normal.";
+"This pile \:has\ literal spaces\ in\ it.";
+"This pile \:h\^as align\|ment spec\^ified.";
+

+Picture of Mup output
+

+

+Slash through number +

+

+Another thing which is common in figured bass notation +is to draw a slash through a number. Again, the section on +figured bass +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: +

+	"6\/"
+	"10\/"
+

+

+

+Boxed or circled text +

+

+You can cause the text to be +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 +lyrics. +

+ "\[This is in a box\]"
+ "\{This is in an ellipse\}"
+

+Picture of Mup output
+
+* Times is a trademark and Helvetica is a registered trademark of Allied Corporation. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/trnspose.html b/mup/docs/uguide/trnspose.html new file mode 100644 index 0000000..5d23ebd --- /dev/null +++ b/mup/docs/uguide/trnspose.html @@ -0,0 +1,139 @@ + + +Transposition + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Transposition +

+

+The +transpose +and +addtranspose +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. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
halfsteps tranposition alternate transposition
0 perfect 1 diminished 2
1 augmented 1 minor 2
2 major 2 diminished 3
3 augmented 2 minor 3
4 major 3 diminished 4
5 augmented 3 perfect 4
6 augmented 4 diminished 5
7 perfect 5 diminished 6
8 augmented 5 minor 6
9 major 6 diminished 7
10 augmented 6 minor 7
11 major 7 diminished 8
+ +

+

+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 +transpose +and +addtranspose +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 +

+	transpose = up maj 2
+

+or +
+	transpose = up dim 3
+

+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. +

+

+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. +

+

+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: +

+define CHORD(COUNT, NAME)
+
+	bold chord all: COUNT `NAME`;     // chord for capo
+	ital(8) chord 1: COUNT `NAME`;    // real chord
+@
+

+Then, set these transpositions: +
+score   transpose = down minor 3	// transpose score for capo
+staff 1 transpose = up perfect 1	// override score transposition
+

+and similarly for any other staffs. +Then, wherever you want to print a chord, say (for example) +
+CHORD(3,Dm)
+

+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. +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/tuplets.html b/mup/docs/uguide/tuplets.html new file mode 100644 index 0000000..bfe8819 --- /dev/null +++ b/mup/docs/uguide/tuplets.html @@ -0,0 +1,98 @@ + + +Tuplets + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Tuplets +

+

+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. +

+

+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. +

+

+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. +

+

+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. +

+

+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 +slashes. +

+

+Here are some examples of tuplets: +

+// 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
+

+Picture of Mup output
+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/utilpgms.html b/mup/docs/uguide/utilpgms.html new file mode 100644 index 0000000..7175d02 --- /dev/null +++ b/mup/docs/uguide/utilpgms.html @@ -0,0 +1,112 @@ + + +Mup Utilities for displaying and printing output + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Mupdisp and Mupprnt utility programs +

+

+If you are using Ghostscript, but prefer to not use Mupmate, +there are two utility programs included with +Mup for displaying and printing music. +

+mupdisp Mup_options myfile
+

+will display music to your screen, while +
+mupprnt Mup_options myfile
+

+will print the output to your printer. +See the installation instructions for more details on configuring the +Mupprnt program for your printer. +

+

+The Mup_options can be any of the options listed in the +section on +"Command line arguments" +except -C, -E, -f, -F, -m, -M, -r, or -v, which don't +send PostScript output to the standard output. +

+

+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). +

+

+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. +

+

+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: +

+
num <Enter> +
+Go to page number num. +
+ or <space> or <control-E> or <control-F> +
+move forward on the page by about 1/8 of an inch +(partial page mode only) +
- or <backspace> or <control-Y> or <control-B> +
+move backward on the page by about 1/8 of an inch +(partial page mode only) +
b or <control-U> or <control-P> +
+move backward on the page by about an inch +(partial page mode only) +
f or <Enter> or <control-D> or <control-N> +
+move forward on the page by about an inch +(partial page mode only) +
h or ? +
+display help screen +
m +
+toggle between partial page and full page modes. +
n +
+go to next page +
p +
+go to previous page +
q or ZZ +
+quit +
r +
+Repaint the page (useful for exiting help page) +
+

+

+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. +


+UNIX is a registered trademark of X/Open Company Limited +
+MS-DOS and Windows are registered trademarks of Microsoft Corporation +

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/uguide/verses.html b/mup/docs/uguide/verses.html new file mode 100644 index 0000000..2e571d1 --- /dev/null +++ b/mup/docs/uguide/verses.html @@ -0,0 +1,73 @@ + + +Placing verses below the scores + + +

+   <-- previous page + +     Table of Contents    next page --> +

+ +

+Placing verses below the scores +

+

+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 "block." +

+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.
+"
+

+

+

+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 +size parameter +and +font parameter, +rather than by +lyricssize +and +lyricsfont. +

+

+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. +

+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.
+"
+

+

+

+   <-- previous page     Table of Contents    next page --> +

+ diff --git a/mup/docs/whatsnew.html b/mup/docs/whatsnew.html new file mode 100644 index 0000000..f86b101 --- /dev/null +++ b/mup/docs/whatsnew.html @@ -0,0 +1,700 @@ + + +New Mup Features + + +

New Mup Features

+

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. +
+

+

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 directionon 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. +
+

+

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. +
+

+

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. +
+

+

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. +
+

+

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. +
+

+

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 higher than +a normal treble clef. +
  • +Phrase marks can now have +an optional line type modifier of dotted or dashed. +
+

+

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. +
+

+

New Features in Mup Version 4.2

+

+

+

+

New Features in Mup Version 4.1

+

+

+

+

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. +
+

+

Coming Attractions

+

+We're always interested in hearing about what features you would +like to see in the next version of Mup. +What features we add will depend on your input, so +please send us a note at +support@arkkra.com. +

+ + + diff --git a/mup/docs/whatsnew.txt b/mup/docs/whatsnew.txt new file mode 100644 index 0000000..797bcdf --- /dev/null +++ b/mup/docs/whatsnew.txt @@ -0,0 +1,556 @@ + + New Mup Features + + 1. New Mup Features + + 1.1 New Features in Mup Version 5.3 + + Version 5.3 is primarily focused on ease of use + enhancements. The largest item is the additional of a + companion program, called Mupmate, that provides an + interface for editing, displaying, and playing Mup files + with the kinds of menus and windows that many people are + used to. The Help menu will take you right to the Mup User's + Guide, which has also had improvements made. If you are a + user who prefers the command line interface that Mup has + always had, don't worry; we like to use that too, and have + no intention of dropping support for it. + + Windows users now only need to download a single file and + execute it to install everything (although you still need to + get and install GSview and Ghostscript separately, if you + want to use that for viewing the PostScript files). Other + users can also just download a single file that contains + both program and documentation. + + Other new features in 5.3 include: + + - Error and warning messages have been enhanced to show + you the text of the line of input where the problem was + found. + + - There is a new pagesize parameter that lets you specify + paper size by common names like letter or a4, as an + alternate to specifying pageheight and pagewidth in + inches or cm. + + - There is a new vcombine parameter, that lets you enter + notes on separate voices, yet have them printed on a + common stem when possible. Typical uses are: + + - To have separate MIDI tracks for different voices, + yet have the voices printed on common stems. + + - For a style of printing where a single stem is + used for the two voices on a staff except when the + voices share a common note, when two opposing + stems are printed. + + - The scorepad parameter now accepts an optional maximum + value, in addition to the minimum value. + + 1.2 New Features in Mup Version 5.2 + + - There is now a generalized 'if' clause' that is much + more flexible and powerful than the simple ifdef and + ifndef. These provide capabilities somewhat similar to + the preprocessors for the C and C++ languages. + + - Complicated time signatures are now supported. This + includes a numerator with two or more numbers added + together, like 3+4 / 4, or two or more fractions added + together, like 3/4 + 3/8. Alternating time signatures, + such as when a piece continuously switches between 3/4 + and 6/8, are also supported. + + - The beamstyle and timeunit parameter values associated + with a time signature are now remembered, so that if + you later change back to the same time signature, you + don't have to also set the beamstyle and timeunit at + the same time; the value used previously for that time + signature will be restored automatically. (Note that + if you have existing Mup files that rely on the old + behavior, they may need small modifications, but that + should be rare.) + + - It is now possible to force stem direction on voices 1 + and 2 even when the other voice is not space. + + - Improvements have been made to how the angle for beams + is calculated. The "best" angle for a beam is + sometimes somewhat subjective, but in general, these + changes will result in more cases where beams are + horizontal or less sloped, + + - There are also additional ways you can control beams: + A new slope interchord attribute lets you force a + specific slope. The new stemshorten parameter lets you + determine how much a chord's stem is allowed to be + shortened when it is beamed. And the existing len + chord attribute can now be set for just one end of a + beamed set of chords as an alternative to setting it at + both ends. + + - The HTML version of the Mup User's Guide now includes + 'next page' and 'previous page' links on each page. + + 1.3 New Features in Mup Version 5.1 + + - You may specify a time value that is the summation of + several time values. This can be used to obtain + beaming, lyrics, or tuplets with durations that cannot + be represented with a single time value, like a half + note plus an eighth note. It also gives an alternate + way to specify chord ties. + + - Cross-staff stems are now supported. + + - You can now explicitly specify a direction of "up" on + rolls to get an upward arrow drawn at the top of the + roll. (Before, only a downward roll would get an + arrow.) + + - Mup will now allow you to beam across spaces as well as + rests. + + - There is a new restsymmult parameter. Setting it to y + will cause Mup to use an alternate style for multirests + of eight measures or less, which uses rest symbols. + + - There is a new string sequence that will be replaced by + the page number of the last page. This may useful to + be able to automatically get output like "Page 2 of 4 + pages." + + - There is a new option for printing of tuplet numbers, + where the number is always printed, but the bracket is + never printed. + + - If you want to have the same lyrics above some staffs + and below others, it is now possible to specify that on + a single input line, rather than requiring two. + + - Improvements have been made to how voice 3 is placed, + which will often eliminate the need to manually specify + a horizontal offset. + + 1.4 New Features in Mup Version 5.0 + + - Mup now supports the shaped notes often used in "Sacred + Harp" music, also sometimes called "fasola" notation. + New note head characters are available for the most + common system of 4 shapes, as well as a system with 7 + shapes. As part of this feature, there is a new + headshape context and a new noteheads parameter that + lets you define what shapes will be used for notes. + + - Note head shapes can also be specified on specific + chords or a specific note within a chord. This makes + it possible to do things like have both normal and X- + shaped notes on the same stem. + + - There are new "slash" note heads, often used to + indicate repeated chords, and a new "blankhead" note + head, that can be used if you just want a stem without + any note head. + + - There is a new stemlen parameter that lets you set the + default stem length. A common use for this would be to + set this parameter to 0.0, to not have any stems at all + (sometimes used for chant). + + - It is now possible to change the clef, defoct, and + release parameters in the middle of a measure. + + - You can now include raw PostScript in the input to the + copied to the output. This could be used, for example, + to include a picture or logo with your music. + + - In addition to the old way of specifying key signature, + by stating the number of sharps or flats, it is now + possible to specify the key by name, as in "a major" or + "c# minor." + + - There is a new swingunit parameter. Some styles of + music are often written with straight eighth notes or + dotted-eighth-sixteeen notations, but where the players + "know" that the composer really wants the music played + with the first note in each pair twice as long as the + second, as if it were a quarter-eighth triplet. This + parameter will make Mup's MIDI output automatically + follow that kind of performance convention. + + - It is possible to set the rehearsal letter or number to + a specific value, to override the automatic + incrementing. This might be especially useful when + there are multiple songs or movements in a single Mup + file. + + 1.5 New Features in Mup Version 4.6 + + - There are new top, bottom, top2, and bottom2 contexts + that let you define a second layer of headers and + footers. These new contexts can be changed multiple + times in a file, so you can use different headings and + footing for different songs or movements within a file. + + - There is a new "block" context, that lets you place + blocks of text in your musical scores. + + - There is a new paragraph command for printing long + sections of text that you would like to have + automatically wrapped around unto as many lines as + needed. The right margin can be justified or ragged. + + - For Linux, in addition to being available in tar.gz + format, Mup files are now available in rpm package + format, for very quick-and-easy installation. The MS- + DOS/Windows Mup files are now available as self- + extracting zip files, so you don't need to have an + unzip program to unpack them. + + - The visible parameter now accepts a value of + "whereused." With this value, when a staff has no + notes on an entire score, that staff is not printed. + This might be used, for example, to save paper on an + orchestral score by only printing staffs for + instruments when they are actually playing. + + - There are new parameters measnumfont, + measnumfontfamily, and measnumsize, to control the + appearance of automatic measure numbers. + + - It is now possible to unset parameters in voice or + staff context, to make them revert to their values in + the next more general context where they are set (staff + or score). + + - When a repeatstart gets moved to the beginning of a + score, sometimes you'd like the bar line at the end of + the previous score to be a double bar rather than + single bar. It is now possible to specify that. + + - There is a new -F option that is like the -f option, + except it derives the name of the output file based on + the name of the input file, rather than you needing to + specify an output file name. + + - The Mup input file name is given in the PostScript + output file, so that PostScript viewer programs like gv + can use it in their window title. + + - There is now a majordomo mailing list available for + registered Mup users. This is a forum for talking with + other Mup users, to discuss questions and tips on using + Mup. + + 1.6 New Features in Mup Version 4.5 + + - There is a new -x option that lets you extract a + portion of a song. This can be especially useful for + MIDI, where you might want to listen to just a few + measures in the middle or end of a piece. But it also + works in printing mode, so you can print just an + excerpt of a piece. + + - It is now possible to specify "subbeams," both with + custom beaming and via the beamstyle parameter. This + can be used when there are a lot of very short notes, + and you want to subdivide the beam groupings. + + - The drawing of phrase marks, ties, and slurs has been + re-implemented to produce more aesthetically pleasing + curves. + + - There is a new special character, called \(space), + which is printed like a normal space on output, but + which is not treated like a space when Mup is looking + for word or syllable boundaries. The most common use + for this would probably be on chant lyrics, where you + want several words to be sung to the same note. It + might also be useful in cases where Mup would normally + split a long string at a word boundary to avoid running + off the edge of a page, but for some reason you want to + prevent that splitting. + + - It is possible to print a text string centered above a + line. This is likely to be the most useful for + printing "gliss." by a wavy line for a glissando, but + it can be used on any kind of line. + + - There are some new user-donated files, including a + Windows installer, and Mup syntax files for nedit and + vim. + + 1.7 New Features in Mup Version 4.4 + + - Many of the changes in this release were to make Mup + conform more closely with established guidelines or + rules for musical notation. This mainly involved small + adjustments to cosmetic details, like how accidentals + and dots are placed. For mid-score clef changes, the + clef is now placed before the barline, as it should be, + rather than after. There is also an improved algorithm + for determining where to end the underscores on lyrics. + + - The use of labels, both labels associated with + individual staffs and labels associated with staffs + grouped by braces or brackets, has been made more + flexible. It used to be that the "label" was only used + on the very first score, with "label2" used on all + subsequent scores. Thus resetting label after the + beginning really had no effect. Now, however, whenever + a new label is specified, that label will be used for + the next score, going back to label2 for subsequent + scores. As an example, this might be useful if staff 1 + was used for just soprano at the beginning of the song, + so you wanted label="Soprano" and label2="S" for that + portion, but later soprano and alto share the staff, so + you would like label="Soprano/alto" to clearly point + out the change, but then revert to just "SA" on + subsequent staffs, to conserve space. + + - You can specify a bulge direction for note ties, note + slurs, chord ties, and chord slurs, if you wish to + override Mup's choice of direction. + + - You can now use \s(PV) or \s(previous) in a text string + to return to the previous size. + + - The 8treble clef is now supported. This is like the + treble8 clef, except the 8 is printed above the G clef + rather than below it, to show notes that sound an + octave higher than a normal treble clef. + + - Phrase marks can now have an optional line type + modifier of dotted or dashed. + + 1.8 New Features in Mup Version 4.3 + + - There is a new rehstyle parameter that controls whether + rehearsal marks are boxed, circled, or plain. + + - It is no longer necessary to specify verse numbers for + lyrics (unless you want to skip a verse). If not + specified, each succeeding set of lyrics for a given + staff and place defaults to having a verse number one + more than the previous verse. + + - There is a new way to force the position of individual + lyrics syllables that is particularly useful for + ensuring that verse numbers or the beginnings of poetic + lines align consistently on all verses. + + - There are new -E and -C options that let you see how + macros expand, which can help you in debugging very + complex macros. + + - There is a new staffpad parameter, and the value of the + scorepad parameter can now be negative. Using negative + values for these can let you jam staffs or scores + closer together in cases where Mup is spacing them + wider apart than is really necessary. + + - It is now possible to have more than one voice on + tablature staffs just like on non-tablature. + + - It is now possible to temporarily override margins on a + particular score. This can let you indent one score + differently than the others, or end a piece with a + shorter-than-normal score. + + - There is now an "alt pedstar" value for the pedstyle + parameter This is like the "pedstar" value except that + when there is a pedal "bounce," only a "Ped" is + printed, rather than a "* Ped." + + - There is a new user-donated program called Winmup which + provides a Windows front-end for the MS-DOS version of + Mup. The Visual Basic source code for Winmup is also + available. + + - Several miscellaneous changes were made to improve the + quality of printed output and to improve portability. + Current Mup users may find the layout of some songs may + change somewhat when they upgrade. + + 1.9 New Features in Mup Version 4.2 + + - A third voice per staff is now supported. + + - It is now possible to adjust the horizontal placement + of notes. + + - It is now possible to beam across rests. + + - The optional automatic measure numbers at the + beginnings of scores are now printed in a larger size. + + - The chord-at-a-time input style has been made more + versatile. Previously, if a voice was mentioned in a + pattern, that voice could not be used for voice-at-a- + time input style in that measure, even if the pattern + was never actually used. Now the restriction only + applies if the pattern is actually used. + + - Strings can be printed enclosed in a circle or elipse. + + - There is a new beamslope parameter that controls the + maximum tilt for beams. + + - There is a new pad parameter that provides an + additional way to control how close together note + groups are placed horizontally. + + - There is a new MIDI "port" keyword. This can let you + assign different tracks to different ports on multi- + port MIDI devices, allowing for more than 16 channels. + + - The minimum values for the scoresep and staffsep + parameters can now be set as low as 6, rather than the + previous minimum of 9. + + 1.10 New Features in Mup Version 4.1 + + - Guitar grids can now be printed, either where they are + used in the music, or summarized at the end of a song. + There is also a library of pre-defined grids that you + can "include" in your music. + + - Non-ASCII characters from the Latin-1 alphabet can now + be typed directly into strings in Mup input, rather + than needing to be specified by name. Shortcut names + have also been added for guillemots. + + - The maximum number of staffs has been raised to 40. + + - The stafflines and staffscale parameters can now be + changed at any bar line rather than only at the + beginning of a song. Changing either of them forces a + new score. + + - The staffsep parameter can now be set on a per-staff + basis, rather than just for the score as a whole. + + - There are new parameters that allow you to control the + order that items above, below, and between staffs are + stacked. + + - It is now possible to turn off the automatic numbering + of measure repeats and the printing of multirest + numbers. + + - It is now possible to specify the vertical placement of + a rest character, if you want to override Mup's + automatic placement. + + - It is now possible to concatenate strings. This is + likely to be most useful in macros, but can be used + anywhere strings are used. + + - There is a new firstpage parameter, which is similar to + the -p command line option, for setting the first page + number. + + - There is a new restcombine parameter, which is similar + to the -c command line option, for automatically + combining a sequences of rest measures into multirests. + + - Music symbols that occur inside ital or boldital + strings will automatically be made italics to match the + string. + + - It is possible to vertically center lyrics. This is + useful when there is a refrain with identical words for + all verses, and you only want it printed once. + + - It is now allowed to have a brace to the left of + brackets, to group a subset of staffs. (Previously, + only brackets were allowed to be nested that way.) + + 1.11 New Features in Mup Version 4.0 + + - There is now an alternate input style, in which you can + enter music a chord at a time rather than a voice at a + time. For certain kinds of music, this may be more + natural, and allow you to enter music more quickly. + The previous input style has also been made more + flexible, such that it is now possible to specify that + one line of input will go to voice 1 on one staff or + set of staffs and voice 2 on another staff or set of + staffs. These enhancements make it easier to do things + like input a vocal score and automatically get a piano + reduction. + + - It is now possible to transform a parameter passed to a + macro into a string. If you are a C programmer, you + will find this works somewhat like the # operator of + ANSI C preprocessor macros. If you're not a C + programmer, suffice it to say that this allows Mup + macros to be used to do things they couldn't do before. + + - There is a new special bar type, called restart, that + lets you end the current set of staffs and begin a new + set of staffs on the same line, as is sometimes done + for a short coda. + + - The symbols for accidentals (like # and &) are now + translated to their corresponding musical symbols + everywhere in chords, rather than only if they + immediately follow the letters A through G. You can, + however, turn off this automatic translation for + individual cases where you want them to be treated + literally. + + - Quadruple whole rests are supported. + + - It is possible to force a measure rest to be shown with + a rest symbol other than the whole rest symbol that is + usually used. + + - There is a new addtranspose parameter. This enables you + to use the transpose parameter to change the + transposition on specific staffs for transposing + instruments, then use addtranpose to transpose the + entire score into a new key. + + - There is a new warn parameter which allows you to + control whether warning messages are printed or not. + + - There is a new ontheline parameter. This allows you to + control whether notes on 1-line staffs are printed + above, below, or on the line. + + - The dist, chorddist, and crescdist parameters can be + overridden on individual items. A dist override can + also be specified on rehearsal marks. Each dist + override can also include a modifier to force items to + a specific place, even if they then overwrite other + items that Mup would normally avoid. + + - There is a new -M option which is like the -m option, + except the name of the MIDI file is derived from the + Mup input file name, rather than requiring you to + supply a name. + + - If a given input file name does not exist, Mup will try + appending .mup to the name and attempt to open that + file. + + - It is now possible to specify an uncollapseable space. + This may be useful when drawing "slash" marks and at + other times. + + - There is a new user-donated program called midi2mup, + which is a Perl script that can convert a MIDI file to + Mup input. + + - The uguide gives examples of how to places verses as + text blocks below the scores. + + 1.12 Coming Attractions + + We're always interested in hearing about what features you + would like to see in the next version of Mup. What features + we add will depend on your input, so please send us a note + at support@arkkra.com. diff --git a/mup/makefile b/mup/makefile new file mode 100644 index 0000000..8acf0d6 --- /dev/null +++ b/mup/makefile @@ -0,0 +1,222 @@ + +# Makefile for Mup (and auxiliary programs mupdisp, mkmupfnt, and mupmate). +# This is not an optimal makefile; instead it tries to be very simple, +# and easy to understand, so it can be easily modified, if needed. + +# On most Linux/Unix type systems, just doing +# make install +# as root will probably work. +# (You really only need to be root to copy the products into +# the system directories. If you change PREFIX +# to point to some other writeable area, you wouldn't need to be root.) +# If you only want the Mup program itself, you can do +# make mup/mup +# The other programs are optional: +# - mupdisp runs Mup and then runs GhostScript on the result. +# You can run Mup directly, and use gv, GSview, ghostview or any other +# PostScript viewer on the Mup output, as an alternative to mupdisp. +# - mkmupfnt is only needed if you want to use fonts beyond the basic +# standard PostScript fonts. +# - mupmate is a graphical user interface front end for Mup. +# It is not needed if you intend to only use Mup via command line interface. + +# The mupdisp and mupmate programs require X libraries and headers (www.x.org). +# The mupmate program requires FLTK libraries and headers (www.fltk.org). + +# If you want mupdisp to support Linux console mode, make sure you have +# the svgalib package installed, then find the two commented-out lines below +# related to Linux console support, and uncomment them. + + +# Lines you might conceivably want to change have comments by them, +# explaining how you might want to change them. +# Any line without any comment by it is very unlikely to ever need changing. + +#----------------------------------------------------------------------- + +# These define where to put the Mup products. +# You could change this to /usr/local or your own space if you like. +PREFIX = /usr +BINDIR = $(PREFIX)/bin +MANDIR = $(PREFIX)/man/man1 +DOCDIR = $(PREFIX)/share/doc/packages/mup + +# This is the name of your C compiler. +# cc would be another common choice. +CCOMPILER = gcc + +# This is the name of your C++ compiler. +# CC would be another common choice. +CPPCOMPILER = g++ + +# -O option turns on optimization for most C compilers. +# You can add other options, if you like, as appropriate for your C compiler. +# Another common addition would be -g to get debugging information. +CFLAGS = -O + +# You can change this if your X libraries and headers are somewhere else +# (like /usr/X11R6). +X_LOCATION = /usr/X11 + +# The FLTK header files are under $(FLTK_INCLUDE)/FL +FLTK_INCLUDE = $(X_LOCATION)/include + +# You can use fltk_jpeg or jpeg library, whichever you have +JPEGLIB = fltk_jpeg + +# You can use fltk_png or png library, whichever you have +PNGLIB = fltk_png + +# You can use fltk_z or z library, whichever you have +ZLIB = fltk_z + +#----------------------------------------------------------------------- + +MUP_SRC = \ + mup/abshorz.c \ + mup/absvert.c \ + mup/assign.c \ + mup/beaming.c \ + mup/beamstem.c \ + mup/brac.c \ + mup/charinfo.c \ + mup/check.c \ + mup/debug.c \ + mup/errors.c \ + mup/extchtbl.c \ + mup/font.c \ + mup/fontdata.c \ + mup/globals.c \ + mup/grpsyl.c \ + mup/ifgram.c \ + mup/lex.c \ + mup/locvar.c \ + mup/lyrics.c \ + mup/macros.c \ + mup/main.c \ + mup/mainlist.c \ + mup/map.c \ + mup/midi.c \ + mup/midiutil.c \ + mup/mkchords.c \ + mup/muschtbl.c \ + mup/nxtstrch.c \ + mup/parstssv.c \ + mup/parstuff.c \ + mup/phrase.c \ + mup/plutils.c \ + mup/print.c \ + mup/prntdata.c \ + mup/prntmisc.c \ + mup/prnttab.c \ + mup/prolog.c \ + mup/range.c \ + mup/rational.c \ + mup/relvert.c \ + mup/restsyl.c \ + mup/roll.c \ + mup/setgrps.c \ + mup/setnotes.c \ + mup/ssv.c \ + mup/stuff.c \ + mup/symtbl.c \ + mup/tie.c \ + mup/trantab.c \ + mup/trnspose.c \ + mup/undrscre.c \ + mup/utils.c \ + mup/ytab.c + +MUP_HDRS = \ + mup/defines.h \ + mup/extchar.h \ + mup/globals.h \ + mup/muschar.h \ + mup/rational.h \ + mup/ssvused.h \ + mup/structs.h \ + mup/ytab.h + +MUPDISP_SRC = \ + mupdisp/at386.c \ + mupdisp/do_cmd.c \ + mupdisp/dos.c \ + mupdisp/genfile.c \ + mupdisp/init.c \ + mupdisp/linvga.c \ + mupdisp/mupdisp.c \ + mupdisp/xterm.c + +MUPDISP_HDRS = mupdisp/dispttyp.h mupdisp/mupdisp.h + +MUPDISP_BITMAPS = mupdisp/help.bm mupdisp/waitmsg.bm + +MKMUPFNT_SRC = mkmupfnt/mkmupfnt.c + +MUPMATE_SRC = \ + mupmate/Config.C \ + mupmate/Edit.C \ + mupmate/File.C \ + mupmate/Help.C \ + mupmate/Main.C \ + mupmate/Preferences.C \ + mupmate/Run.C \ + mupmate/utils.C \ + mupmate/license.C \ + mupmate/regform.C \ + mupmate/template.C + +MUPMATE_HDRS = \ + mupmate/Config.H \ + mupmate/Edit.H \ + mupmate/File.H \ + mupmate/Help.H \ + mupmate/Main.H \ + mupmate/Preferences.H \ + mupmate/Run.H \ + mupmate/utils.H \ + mupmate/globals.H \ + mupmate/resource.h + +MUPMATE_OTHER_FILES = \ + mupmate/mup32.xpm +#--------------------------------------------------------------- + +all: mup/mup mupdisp/mupdisp mkmupfnt/mkmupfnt mupmate/mupmate + +mup/mup: $(MUP_HDRS) $(MUP_SRC) + $(CCOMPILER) $(CFLAGS) -o $@ $(MUP_SRC) -lm + +mupdisp/mupdisp: $(MUPDISP_HDRS) $(MUPDISP_BITMAPS) $(MUPDISP_SRC) + $(CCOMPILER) $(CFLAGS) -L$(X_LOCATION)/lib -o $@ -DNO_VGA_LIB $(MUPDISP_SRC) -lX11 + # For Linux console mode support, comment out the previous line + # and uncomment the following line + # $(CCOMPILER) $(CFLAGS) -L$(X_LOCATION)/lib -o $@ $(MUPDISP_SRC) -lvga -lX11 -lm + +mkmupfnt/mkmupfnt: $(MKMUPFNT_SRC) + $(CCOMPILER) $(CFLAGS) -o $@ $(MKMUPFNT_SRC) + +mupmate/mupmate: $(MUPMATE_SRC) $(MUPMATE_HDRS) $(MUPMATE_OTHER_FILES) + $(CPPCOMPILER) $(CFLAGS) -o $@ $(MUPMATE_SRC) \ + -I$(FLTK_INCLUDE) -Imup -L$(X_LOCATION)/lib \ + -lfltk -lfltk_images -lXext -lX11 -lXpm \ + -l$(JPEGLIB) -l$(PNGLIB) -l$(ZLIB) -lm + +install: all + mkdir -p $(BINDIR) $(MANDIR) $(DOCDIR)/uguide + cp mup/mup $(BINDIR)/mup + cp mkmupfnt/mkmupfnt $(BINDIR)/mkmupfnt + cp mupdisp/mupdisp $(BINDIR)/mupdisp + # For Linux console mode support, uncomment the following line + # chown root $(BINDIR)/mupdisp ; chmod 4755 $(BINDIR)/mupdisp + cp mupmate/mupmate $(BINDIR)/mupmate + cp mupprnt $(BINDIR)/mupprnt + cp docs/*.1 $(MANDIR) + cp docs/README* docs/*.txt docs/*.ps docs/*.mup $(DOCDIR) + cp docs/uguide/* $(DOCDIR)/uguide + +clean: + rm -f mup/*.o mupdisp/*.o mkmupfnt/*.o mupmate/*.o + +clobber: clean + rm -f mup/mup mupdisp/mupdisp mkmupfnt/mkmupfnt mupmate/mupmate diff --git a/mup/mkmupfnt/mkmupfnt.c b/mup/mkmupfnt/mkmupfnt.c new file mode 100644 index 0000000..a481e40 --- /dev/null +++ b/mup/mkmupfnt/mkmupfnt.c @@ -0,0 +1,436 @@ +char Copyright[] = + "Copyright (c) 1999, 2000 by Arkkra Enterprises\nAll rights reserved\n\n"; + +/* This program generates a Mup fontfile, that will let you override a + * Mup font with one of your own. It is done in C rather than with + * a "shell script" to be portable to systems without a Unix-like shell. + * See the "usage_message" for how to invoke this program. + * It creates a PostScript program to print each character in the font + * and print out its width, height, and ascent. + * It runs Ghostscript on that program. + */ + +#ifdef __DJGPP__ +#define __DOS__ +#endif + +#include +#include +#include +#include +#ifdef __DOS__ +#include +#else +#include +#include +#include +#endif + +#ifdef O_BINARY +#define READ_FLAGS (O_RDONLY | O_BINARY) +#define WRITE_FLAGS (O_WRONLY | O_BINARY | O_CREAT | O_TRUNC) +#else +#define READ_FLAGS (O_RDONLY) +#define WRITE_FLAGS (O_WRONLY | O_CREAT | O_TRUNC) +#endif + +/* temp file used for PostScript program */ +char *PS_script_file = "mkmupfnt.ps"; +#ifdef __DOS__ +char *GS_output = "mkmupfnt.tmp"; +#endif + +char Version[] = "5.3"; + +void usage(char *program_name); +void verify_valid_Mup_name(char *Mup_name); +int name_matches(char *namelist[], char *name, int namelength); +void run_Ghostscript(char *PostScript_name, char *Mup_name); +char * make_string(char *first_part, char *second_part); +void generate_PostScript_program(char *PS_file); +void cleanup(int exitcode); + +int +main(int argc, char **argv) +{ + char *PostScript_name; + char *Mup_name; + char *outfile; + + fprintf(stderr, "%s Version %s\n%s", argv[0], Version, Copyright); + + if (argc < 4 || argc > 5) { + usage(argv[0]); + } + + PostScript_name = argv[1]; + Mup_name = argv[2]; + outfile = argv[3]; + + verify_valid_Mup_name(Mup_name); + + if ((freopen(outfile, "w", stdout)) == (FILE *) 0) { + fprintf(stderr, "Can't open '%s'\n", outfile); + exit(1); + } + + /* Generate a PostScript program to run, and redirect that program + * into Ghostscript. */ + generate_PostScript_program(argc == 5 ? argv[4] : (char *) 0); + if ((freopen(PS_script_file, "r", stdin)) == (FILE *) 0) { + fprintf(stderr, "Can't open '%s'\n", PS_script_file); + cleanup(1); + } + run_Ghostscript(PostScript_name, Mup_name); + + /* If there is a PostScript file to add to the output, copy that */ + if (argc == 5) { + int file; + int n; + char buff[BUFSIZ]; + + if ((file = open(argv[4], READ_FLAGS)) < 0) { + fprintf(stderr, "Can't open '%s'\n", argv[4]); + cleanup(1); + } + while ((n = read(file, buff, BUFSIZ)) > 0) { + write(1, buff, n); + } + close(file); + } + + cleanup(0); + /* This line is not reached, since cleanup() exits, + * but some compilers complain if function doesn't have a + * return or exit, so the return is here to appease them. */ + return(0); +} + + +char *usage_message = + "PostScript_font_name Mup_font_name outfile [file]\n\n" + " Generates a fontfile for Mup to use, to override a Mup font.\n" + " Arguments are:\n\n" + " PostScript_font_name the name of the font you want to add to Mup,\n" + " like 'Helvetica-Narrow'\n\n" + " Mup_font_name the name of the Mup font you want to replace,\n" + " like 'HR' or 'helvetica rom'\n\n" + " outfile the generated Mup fontfile\n\n" + " file can contain PostScript to be added to Mup prolog,\n" + " if needed to use the font.\n"; + +void +usage(char *program_name) +{ + fprintf(stderr, "usage: %s %s", program_name, usage_message); + exit(1); +} + +/* verify Mup font name is a valid one, give error and exit if not */ + +char *family_names[] = { + "avantegarde", + "bookman", + "courier", + "helvetica", + "newcentury", + "palatino", + "times", + (char *) 0 +}; + +char *font_names[] = { + "rom", + "bold", + "ital", + "boldital", + (char *) 0 +}; + +void +verify_valid_Mup_name(char *Mup_name) +{ + char *space_loc; + + if (strlen(Mup_name) == 2 && strchr("ABCHNPT", Mup_name[0]) + && strchr("RBIX", Mup_name[1]) ) { + /* name is okay, an abbreviated name */ + return; + } + + /* check long names */ + if ((space_loc = strchr(Mup_name, ' ')) != 0 && + name_matches(family_names, Mup_name, space_loc - Mup_name) && + name_matches(font_names, space_loc + 1, strlen(space_loc + 1))) { + return; + } + + fprintf(stderr, "'%s' is not a valid Mup font name\n", Mup_name); + exit(1); +} + +/* verify name given matches one on the list of valid names */ + +int +name_matches(char *namelist[], char *name, int namelength) +{ + int i; + + for (i = 0; namelist[i] != (char *) 0; i++) { + if (strncmp(namelist[i], name, namelength) == 0 && + namelength == strlen(namelist[i])) { + /* matches */ + return(1); + } + } + return(0); +} + +/* Run Ghostscript to write width/ascent/descent information for all + * characters. */ + +void +run_Ghostscript(char *PostScript_name, char *Mup_name) +{ + char * PS_option; + char * Mup_option; +#ifdef __DOS__ + char * output_option; + int ret; +#endif + int status; + + /* pass the arguments on to Ghostscript */ + PS_option = make_string("-sPostScript_name=", PostScript_name); + Mup_option = make_string("-sMup_name=", Mup_name); +#ifdef __DOS__ + /* use temp file as a /dev/null */ + output_option = make_string("-sOutputFile=", GS_output); + + if ((ret = spawnlp(P_WAIT, "gs386", "gs386", "-sDEVICE=bit", + "-dQUIET", output_option, Mup_option, + PS_option, "-", (char *) 0)) != 0) { + /* try just plain 'gs' */ + ret = spawnlp(P_WAIT, "gs", "gs", "-sDEVICE=bit", + "-dQUIET", output_option, Mup_option, + PS_option, "-", (char *) 0); + } + unlink(GS_output); + if (ret != 0) { + fprintf(stderr, "failed to execute gs\n"); + cleanup(1); + } +#else + switch (fork()) { + case 0: + execlp("gs", "gs", "-sDEVICE=bit", "-dQUIET", + "-sOutputFile=/dev/null", Mup_option, + PS_option, "-", (char *) 0); + /* FALL THROUGH */ + case -1: + fprintf(stderr, "failed to execute gs\n"); + cleanup(1); + default: + wait( &status); + if (status != 0) { + fprintf(stderr, "Ghostscript failed\n"); + cleanup(1); + } + } +#endif +} + +/* given two strings, get enough space to concatenate them, + * write them into the malloc-ed string, and return it. */ + +char * +make_string(char *first_part, char *second_part) +{ + char *new_string; + + if ((new_string = (char *) malloc(strlen(first_part) + + strlen(second_part) + 1)) == 0) { + fprintf(stderr, "malloc failed\n"); + cleanup(1); + } + sprintf(new_string, "%s%s", first_part, second_part); + return(new_string); +} + +/* This is the PostScript program that actually extracts the + * font size information. It is included here and generated as needed, + * so that this can be a standalone program, and not have to search + * for another file in order to run. In Unix, we could just pipe this + * directly into Ghostscript, but on systems that don't have pipes, + * a temp file would need to be used, so we do it that way everywhere + * for consistency. + */ + +char *PostScript_program = +"%% This PostScript program generates a fontfile for use by Mup.\n" +"% PostScript_name and Mup_name must be defined as strings\n" +"% when this is called.\n" +"% PostScript_name is the font you want to add to Mup, while\n" +"% Mup_name is name of the Mup font you want to replace.\n" +"% So, for example, if you want to replace the Mup Helvetica roman\n" +"% font with the PostScript Helvetica-Narrow font, these strings would be\n" +"% (Helvetica-Narrow) and (helvetica rom).\n" +"% These can be passed in using the Ghostscript -s option.\n" +"\n" +"1 setflat % make bounding box very accurate\n" +"\n" +"/buff 50 string def % number to string conversion buffer\n" +"/character 1 string def % buffer for a character to get the bbox of\n" +"\n" +"%------------------------------------------------------------------\n" +"\n" +"\n" +"% Usage\n" +"% given a one-character string in \"character\",\n" +"% outputs its width in 1/1000ths of an inch\n" +"\n" +"/getwidth {\n" +" % get width of character\n" +" character stringwidth\n" +"\n" +" % convert x to 1/1000th of an inch\n" +" pop 1000 mul 72 div round cvi\n" +"\n" +" % print results\n" +" buff cvs (\\t) print print\n" +"} def\n" +"\n" +"%-----------------------------------\n" +"% Usage\n" +"% given a one-character string in \"character\",\n" +"% outputs its height in 1/1000ths of an inch\n" +"\n" +"/getheight {\n" +" % place character at (100, 100) and get its pathbbox\n" +" newpath\n" +" 100 100 moveto\n" +" character true charpath flattenpath pathbbox\n" +"\n" +" % save the top and bottom y coordinates of the bbox\n" +" /top exch def pop\n" +" /bot exch def pop\n" +"\n" +" % if bot is above the baseline, the height is (top - baseline)\n" +" % otherwise it is (top - bot)\n" +" bot 100 gt { top 100 sub } { top bot sub } ifelse\n" +"\n" +" % space is special, use 9 points for height\n" +" character ( ) eq { 9 add } if\n" +"\n" +" % add 2 point of padding, one for top and one for bottom white space,\n" +" % and convert to 1/1000ths of an inch\n" +" 2 add 1000 mul 72 div round cvi\n" +"\n" +" % print the results\n" +" buff cvs (\\t) print print\n" +"} def\n" +"\n" +"%----------------------------------\n" +"% Usage\n" +"% given a one-character string in \"character\",\n" +"% outputs its ascent in 1/1000ths of an inch\n" +"\n" +"/getascent {\n" +" % place character at (100, 100) and get its pathbbox\n" +" newpath\n" +" 100 100 moveto\n" +" character true charpath flattenpath pathbbox\n" +"\n" +" % save the top y coordinate of the bbox\n" +" /top exch def pop pop pop\n" +"\n" +" % ascent is top minus baseline\n" +" top 100 sub\n" +"\n" +" % space is special, use 6.8 points for ascent\n" +" character ( ) eq { 6.8 add } if\n" +"\n" +" % add 1 point of padding and convert to 1/1000ths of an inch\n" +" 1 add 1000 mul 72 div round cvi\n" +"\n" +" % print results\n" +" buff cvs (\\t) print print\n" +"} def\n" +"\n" +"\n" +"%-----------------------------------\n" +"\n" +"% generate width, height an ascent for a font.\n" +"% Usage:\n" +"% fname mupfname do_a_font\n" +"\n" +"/do_a_font {\n" +" % save arguments for later use\n" +" /mupfname exch def\n" +" /fname exch def\n" +"\n" +" % Outut heading\n" +" (# This is a Mup font file\\n) print\n" +" (Mup font name: ) print mupfname print (\\n) print\n" +" (PostScript font name: ) print fname buff cvs print (\\n) print\n" +" (Size data:\\n) print\n" +"\n" +" % Set up to use the desired font\n" +" fname findfont\n" +" 12 scalefont setfont\n" +"\n" +" % Mup uses ASCII character codes from 32 through 126\n" +" 32 1 126 {\n" +" dup buff cvs print\n" +" /val exch def character 0 val put\n" +" getwidth\n" +" getheight\n" +" getascent\n" +" (\\t# ') print character print ('\\n) print\n" +" } for\n" +"\n" +" (PostScript:\\n) print\n" +"} def\n" +"\n" +"%-----------------------------------\n" +"\n" +"% generate the output\n" +"PostScript_name cvn Mup_name do_a_font\n" +"\n" +"quit\n"; + +void +generate_PostScript_program(char *PS_file) +{ + int file; + int length; + + if ((file = open(PS_script_file, WRITE_FLAGS, 0644)) < 0) { + fprintf(stderr, "Can't generate '%s'\n", PS_script_file); + exit(1); + } + + /* If user gave a PostScript file, that probably implements the + * font, so include that in the script */ + if (PS_file != (char *) 0) { + write(file, "(", 1); + write(file, PS_file, strlen(PS_file)); + write(file, ") run\n", 6); + } + + length = strlen(PostScript_program); + if (write(file, PostScript_program, length) != length) { + fprintf(stderr, "generation of PostScript program failed\n"); + cleanup(1); + } + close(file); +} + +/* remove the temp file and exit */ + +void +cleanup(int exitcode) +{ + unlink(PS_script_file); + exit(exitcode); +} diff --git a/mup/mup/abshorz.c b/mup/mup/abshorz.c new file mode 100644 index 0000000..8d157db --- /dev/null +++ b/mup/mup/abshorz.c @@ -0,0 +1,3446 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: abshorz.c + * + * Description: This file contains functions for setting absolute + * horizontal coordinates. + */ + +#include +#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) + +/* + * 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(); +} + +/* + * 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 <>, 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); + } +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } + } + } + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } + } +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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); + } +} + +/* + * 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; + } + } +} + +/* + * 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]; + } + } +} + +/* + * 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]); +} + +/* + * 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 */ +} + +/* + * 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; + } +} + +/* + * 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; + } + } + } + } +} + +/* + * 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; + } + } +} + +/* + * 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; + } +} + +/* + * 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); +} + +/* + * 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; + } + } +} + +/* + * 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; + } +} + +/* + * 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; + } + } + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * Name: getmultinum() + * + * Abstract: Find number of measures in the next staff's multirest. + * + * Returns: The number, or 0 if next staff is not a multirest. + * + * Description: This function is given an MLL struct, and if it's not a STAFF, + * searches forward to the next STAFF. It returns as stated above. + */ + +static int +getmultinum(mll_p) + +struct MAINLL *mll_p; /* point along MLL, starts at the CLEFSIG */ + +{ + int basictime; /* of the first group in the first following staff */ + + + /* find the first staff after this clefsig */ + for ( ; mll_p != 0 && mll_p->str != S_STAFF; mll_p = mll_p->next) { + ; + } + + /* if no staff, there is no multirest */ + if (mll_p == 0) { + return (0); + } + + basictime = mll_p->u.staff_p->groups_p[0]->basictime; + return (basictime < -1 ? -basictime : 0); +} diff --git a/mup/mup/absvert.c b/mup/mup/absvert.c new file mode 100644 index 0000000..b07a2b3 --- /dev/null +++ b/mup/mup/absvert.c @@ -0,0 +1,3422 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: absvert.c + * + * Description: This file contains functions for setting all absolute + * vertical coordinates. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* + * Define the maximum number of scores that could ever fit on a page, when all + * staffs and scores are packed as tightly as possible. The 8 * STEPSIZE is + * the height of the five lines of a staff, and the other factor in the + * denominator is the minimum distance between staffs or scores, whichever is + * smaller. If a staff has less than 5 lines, it is still given as much space + * as a 5 line staff, so that's why we can use 8 * STEPSIZE here as the + * smallest possible staff size. + */ +#define MAXSCORES ( (int)(PGHEIGHT / \ + (MINSTFSCALE * STEPSIZE * (8 + MIN(MINMINSTSEP, MINMINSCSEP)))) + 1 ) + +#define FUDGE 0.001 /* fudge factor for round off error */ + +/* determine what clef, if any, will be printed on a staff */ +#define CLEF2PRINT(staffno) \ + (svpath(staffno, STAFFLINES)->printclef == SS_NORMAL ? \ + svpath(staffno, CLEF)->clef : NOCLEF) + +/* define amount of horz and vert padding between at-end grids */ +#define HPADGRID (2.0 * STEPSIZE) +#define VPADGRID (2.0 * STEPSIZE) + +/* maximum length of a chord name that we care about for sorting purposes */ +#define MAXCHNAME (100) + +static void relscore P((struct MAINLL *mllfeed_p)); +static void relstaff P((struct MAINLL *feed_p, int s1, int s2, double botoff, + double betweendist)); +static void posscores P((void)); +static void abspage P((struct MAINLL *page_p, float cursep[], float maxsep[], + float curpad[], float maxpad[], int totscores, + double remheight, double y_start)); +static void absstaff P((struct FEED *feed_p, struct STAFF *staff_p)); +static double grids_atend P((double vertavail, int firstpage, + struct FEED *mfeed_p, struct FEED *gfeed_p)); +static int compgrids P((const void *g1_p_p, const void *g2_p_p)); +static void proc_css P((void)); +static void one_css P((struct STAFF *ts_p, struct STAFF *os_p, + struct GRPSYL *tg_p, RATIONAL time)); +static void horzavoid P((void)); +static void avoidone P((struct MAINLL *mainll_p, struct GRPSYL *cssg_p, + RATIONAL time)); +static void set_csb_stems P((void)); +static void onecsb P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p)); +static int calcline P((struct GRPSYL *start1_p, struct GRPSYL *end1_p, + struct GRPSYL *start2_p, struct GRPSYL *end2_p, + struct GRPSYL *first_p, struct GRPSYL *last_p, + int topdir, int botdir, + float *b0_p, float *b1_p)); +static void samedir P((struct GRPSYL *first_p, struct GRPSYL *last_p, + struct GRPSYL *start1_p, struct GRPSYL *start2_p, + struct GRPSYL *end1_p, float *b0_p, float *b1_p, + double deflen, int one_end_forced, int slope_forced, + double forced_slope)); +static void oppodir P((struct GRPSYL *first_p, struct GRPSYL *last_p, + struct GRPSYL *start1_p, struct GRPSYL *start2_p, + float *b0_p, float *b1_p, double deflen, int one_end_forced, + int slope_forced, double forced_slope)); +static struct GRPSYL *nextcsb P((struct GRPSYL *gs_p)); +static struct GRPSYL *nxtbmnote P((struct GRPSYL *gs_p, struct GRPSYL *first_p, + struct GRPSYL *endnext_p)); + +/* + * 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(); + } +} + +/* + * 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 */ +} + +/* + * 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; + } + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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]; + } + } +} + +/* + * 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 */ +} + +/* + * 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]])); +} + +/* + * 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]; + } + } + } +} + +/* + * 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; + } + } +} + +/* + * 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); + } + } + } +} + +/* + * 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); + } +} + +/* + * 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); + } + } + } + } + } +} + +/* + * 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; + } + } + } +} + +/* + * 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); +} + +/* + * 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; +} + +/* + * 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; +} + +/* + * 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) */ +} + +/* + * Name: nxtbmnote() + * + * Abstract: Find the next note group in this CSB (this staff or the other). + * + * Returns: pointer to next note group in CSB, endnext_p if none + * + * Description: This function looks for the next group that is still in this + * CSB set (therefore nongrace), and contains notes (not a space + * or a rest), whichever staff it may be on. + */ + +static struct GRPSYL * +nxtbmnote(gs_p, first_p, endnext_p) + +struct GRPSYL *gs_p; /* current group, must be in a CSB */ +struct GRPSYL *first_p; /* first group in top staff of the CSB */ +struct GRPSYL *endnext_p; /* what to return if we hit the end */ + +{ + /* + * Keep finding the next nonspace group, until we hit the end or we + * find one that is not a rest. + */ + do { + gs_p = nxtbmgrp(gs_p, first_p, endnext_p); + } while (gs_p != endnext_p && gs_p->grpcont != GC_NOTES); + return (gs_p); +} diff --git a/mup/mup/assign.c b/mup/mup/assign.c new file mode 100644 index 0000000..9c938dd --- /dev/null +++ b/mup/mup/assign.c @@ -0,0 +1,2181 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* Assign values to internal variables in an SSV struct. The functions in + * this file are called from the parse phase. */ + + +#include +#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)); + + +/* 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; + } +} + + +/* 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); +} + + +/* 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; + } +} + + + +/* 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; + } +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* 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; +} + + +/* 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); +} + + +/* 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; +} + + +/* 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++; +} + + +/* 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; +} + + +/* 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); + } +} + + +/* 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; +} + + +/* 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++; +} + + +/* 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; +} + + +/* 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); + } +} + + +/* 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; +} + + +/* 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; +} + + +/* 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); + } +} + + +/* 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)++; +} + + +/* 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); +} + + +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; +} + + +/* 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); +} + + +/* 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 ? " " : ""); + } + } +} + + +/* 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); + } + } +} + + +/* 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"); + } +} + + +/* function to let other files get to the ADJUST2INCHES macro */ + +double +adjust2inches(value) + +double value; + +{ + ADJUST2INCHES(value); + return(value); +} diff --git a/mup/mup/beaming.c b/mup/mup/beaming.c new file mode 100644 index 0000000..482fb94 --- /dev/null +++ b/mup/mup/beaming.c @@ -0,0 +1,1082 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions called at parse time to deal with beaming. */ + + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + +static void subbeam P((struct SSV *ssv_p, RATIONAL outer_time, int obi, + struct GRPSYL *begin_gs_p, struct GRPSYL *end_gs_p)); +static struct GRPSYL *verify_crossbeam P((struct GRPSYL *gs_p, + struct GRPSYL *other_gs_p, RATIONAL start_time, RATIONAL *end_time_p, + int staffno, int size)); +static void +slopelencheck P((struct GRPSYL *first_p, struct GRPSYL *last_p, char *bmtype)); + + +/* this function will get called whenever a group is not the start or end + * of a custom beam group. This will fill in the beamloc based on past + * history. If we were most recently in a custom beam group, we still are. + * If we weren't before, we aren't now either. The non-custom beaming + * gets done later after we have collected a whole bar in do_beaming() + * which is called via do_bar(). */ + +void +setbeamloc(curr_grp_p, last_grp_p) + +struct GRPSYL *curr_grp_p; /* the group we're working on */ +struct GRPSYL *last_grp_p; /* the last group we did */ + +{ + if (curr_grp_p->grpvalue == GV_ZERO) { + /* grace notes don't get handled here */ + curr_grp_p->beamloc = NOITEM; + return; + } + + /* if the previous group is a grace group, that doesn't count. Back + * up in the list to the first non-grace or beginning of list */ + for ( ; last_grp_p != (struct GRPSYL *) 0 + && last_grp_p->grpvalue == GV_ZERO; + last_grp_p = last_grp_p->prev) { + ; + } + + if (last_grp_p != (struct GRPSYL *) 0) { + + switch (last_grp_p->beamloc) { + + case STARTITEM: + case INITEM: + curr_grp_p->beamto = last_grp_p->beamto; + /* Make sure notes are 8th or shorter. Spaces (which + * are allowed in cross-staff beams) can be longer. */ + if (curr_grp_p->basictime < 8) { + /* At this point, spaces are still + * pseudo-pitches, so have to figure out + * if this group is really notes */ + int letter; /* pitch */ + int n; /* index through notelist */ + for (n = 0; n < curr_grp_p->nnotes; n++) { + letter = curr_grp_p->notelist[n].letter; + if ((letter >= 'a' && letter <= 'g') || + letter == PP_NO_PITCH) { + yyerror("beamed notes must be 8th or shorter"); + break; + } + } + } + + /* if previous began beaming, we must be inside now */ + /* if in beam before, we still are */ + curr_grp_p->beamloc = INITEM; + break; + + case ENDITEM: + case NOITEM: + default: + /* if previous was ending beaming, or + * we weren't inside a beam, must be no beam now */ + curr_grp_p->beamloc = NOITEM; + break; + } + } + else { + /* nothing specified before, so no beam */ + curr_grp_p->beamloc = NOITEM; + } +} + + +/* 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); +} + + +/* 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; + } + } + } + } +} + + +/* 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; + } + } + } +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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; +} + + +/* User is not allowed to specify length on both ends of a beam along with + * a slope, because they could becontradictory. */ + +static void +slopelencheck(first_p, last_p, bmtype) + +struct GRPSYL *first_p; /* first beamed group */ +struct GRPSYL *last_p; /* last beamed group */ +char *bmtype; /* "beam" or "alt" */ + +{ + if (IS_STEMLEN_KNOWN(first_p->stemlen) == YES && + IS_STEMLEN_KNOWN(last_p->stemlen) == YES && + fabs(first_p->beamslope - NOBEAMANGLE) > 0.001) { + l_yyerror(last_p->inputfile, last_p->inputlineno, + "can't specify both end stem lengths and slope for %s", + bmtype); + } +} diff --git a/mup/mup/beamstem.c b/mup/mup/beamstem.c new file mode 100644 index 0000000..6ff26fc --- /dev/null +++ b/mup/mup/beamstem.c @@ -0,0 +1,2645 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: beamstem.c + * + * Description: This file contains functions for setting lengths of note + * stems, which also involves beaming considerations. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* + * Several functions need to know the value of the "stemlen" parameter, so + * instead of them all calling vvpath, define a holding place here. + */ +static float Defstemsteps; + +static void proclist P((struct MAINLL *mainll_p, int vno)); +static void proctablist P((struct MAINLL *mainll_p, int vno)); +static int stemforced P((struct GRPSYL *gs_p, struct GRPSYL *ogs_p)); +static void setbeam P((struct GRPSYL *start_p, struct GRPSYL *end_p, + struct GRPSYL *ogs_p)); +static void restore_ry P((struct GRPSYL *start_p, struct GRPSYL *end_p)); +static double embedgrace P((struct GRPSYL *start_p, double b1, double b0)); +static double embedclef P((struct GRPSYL *start_p, double b1, double b0)); +static double beamoff P((struct GRPSYL *gs_p, int side, double boundary, + struct GRPSYL *start_p)); +static void embedrest P((struct GRPSYL *start_p, struct GRPSYL *last_p, + double b1, double b0)); +static double avoidothervoice P((struct GRPSYL *start_p, struct GRPSYL *last_p, + double b1, double b0, struct GRPSYL *ogs_p)); +static void setgroupvert P((int, struct GRPSYL *, struct GRPSYL *)); +static void settuplet P((struct GRPSYL *start_p, struct STAFF *staff_p)); +static void expgroup P((struct GRPSYL *gs_p, struct GRPSYL *ogs_p)); +static void applywith P((struct GRPSYL *gs_p, int side)); + +/* + * 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); + } + } + } + } + } +} + +/* + * 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); + } +} + +/* + * 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); + } +} + +/* + * 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 */ + } +} + +/* + * 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); + } +} + +/* + * 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]; + } + } + } +} + +/* + * 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 */ +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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 */ +} + +/* + * 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; + } + } + } + } +} + +/* + * 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]; +} + +/* + * 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); +} + +/* + * Name: applywith() + * + * Abstract: Expand vertical boundaries of group, based on "with" list. + * + * Returns: void + * + * Description: This function adds to the RN coord of a group and/or subtracts + * from the RS coord, if a "with" list is present. + */ + +static void +applywith(gs_p, side) + +struct GRPSYL *gs_p; /* the group to be worked on */ +int side; /* side to put things on (1=top, -1=bottom) */ + +{ + int n; /* loop variable */ + float hi; /* height of a list item */ + + + /* + * Loop through all the "with" items, expanding the N or S coord of + * the group. Each item is allowed enough space for its height, or + * MINWITHHEIGHT, whichever is greater. In the print phase, items of + * height less than MINWITHHEIGHT will be placed so as to avoid staff + * lines as much as possible. + */ + for (n = 0; n < gs_p->nwith; n++) { + hi = strheight(gs_p->withlist[n]); + hi = MAX(hi, Staffscale * MINWITHHEIGHT); + if (side == 1) + gs_p->c[RN] += hi; + else + gs_p->c[RS] -= hi; + } +} diff --git a/mup/mup/brac.c b/mup/mup/brac.c new file mode 100644 index 0000000..44ca1f1 --- /dev/null +++ b/mup/mup/brac.c @@ -0,0 +1,1017 @@ + +/* Copyright (c) 1995, 1997, 1999, 2000, 2001, 2002, 2003, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions to deal with brace/bracket lists, to make sure they don't + * overlap, and then to place the labels to minimize the space they use. */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* padding between labels in inches. **** eventually should adjust padding + * based on size??? ***/ +#define LABELPAD 0.125 + +/* information to be able to determine overlaps in the brace/bracket lists */ +static struct BRAC_INFO { + struct STAFFSET *staffset_p; /* bracelist or bracklist item */ + int bractype; /* BRACELIST or BRACKLIST */ + struct BRAC_INFO *nested_p; /* pointer to another brace/bracket + * item, which has its top on the + * same staff, and presumably + * is nested inside this one */ + struct BRAC_INFO *nested_by_p; /* if this one is nested, pointer + * to what it is nested by, else NULL */ + short nestlevel; /* how many levels deep */ + short topvisstaff; /* top visible staff in range */ + short botvisstaff; /* bottom visible staff in range */ +} *Brac_info_p [MAXSTAFFS + 1]; + + +/* information about a label, either for a staff or group. */ +struct LABELINFO { + char *label; /* text of the label */ + float width; /* strwidth(label) */ + float west; /* relative distance of left edge of label + * from the line between the labels and the + * braces/brackets. This will be negative */ + int is_staff_label; /* YES for staff label, NO for group */ + struct LABELINFO *next;/* linked list of labels at same y location */ +}; + +/* information about all the labels that end up being printed left of a + * specific staff or between that staff and the one below it. */ +struct LABELLIST { + short staffno; /* which staff */ + struct LABELINFO *label_p; /* list of labels to be printed to + * the left of this staff */ + struct LABELINFO *btwnlabel_p; /* list of labels to be printed + * between this staff and the one + * below this staff */ + short pad; /* how many levels of labels + * have been put on this staff, either + * on the staff itself or on one or + * more other staffs that are + * grouped with this one */ +}; +static struct LABELLIST Labellist[MAXSTAFFS + 1]; + +static short Numvis; /* how many staffs currently visible */ +static short Maxlevels; /* maximum number of nesting levels */ +static float Nested_brace_adjust = 0.0; /* brace outside a bracket needs + * some extra space to look good. */ + + +/* static functions */ +static void free_brac_info P((struct BRAC_INFO *brac_info_p)); +static void set_brac_info P((struct STAFFSET *staffset_p, int bractype)); +static int check_brac_overlap P((struct BRAC_INFO *brac_info_p)); +static void setnestlevel P((struct BRAC_INFO *brac_p, + struct BRAC_INFO *nested_by_p)); +static void place_labels P((struct MAINLL *mll_p, + struct MAINLL *prev_feed_mll_p)); +static void init_labellist P((void)); +static void free_label P((struct LABELINFO *label_p)); +static struct LABELINFO *newlabelinfo P((char *label, int is_staff_label)); +static void grouplabel P((struct BRAC_INFO *brac_p, int do_nested, + struct MAINLL *mll_p, struct MAINLL *prev_feed_mll_p)); +static double west_adjust P((struct MAINLL *mll_p, + struct MAINLL *prev_feed_mll_p)); +static struct MAINLL *find_prev_feed_mll_p P((struct MAINLL *mll_p)); +static char * label4staff P((struct MAINLL *mll_p, int s, + struct MAINLL *prev_feed_mll_p)); +static char * label4group P((struct MAINLL *mll_p, struct BRAC_INFO *brac_p, + struct MAINLL *prev_feed_mll_p)); +static double dflt_label_width P((struct MAINLL *mll_p, + struct MAINLL *prev_feed_mll_p)); + + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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)); +} + + +/* 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; + } +} + + +/* + * 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); + } +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* Return width of default label if the default label is needed (for + * indent of first score. Returns 0.0 if default label should not be used. + */ + +static double +dflt_label_width(mll_p, prev_feed_mll_p) + +struct MAINLL *mll_p; /* points to FEED or proposed place + * where current FEED will be */ +struct MAINLL *prev_feed_mll_p; /* points to previous FEED, or proposed + * place where prev FEED will be */ + +{ + char dfltlabel[16]; + + + for (mll_p = mll_p->prev; mll_p != 0; mll_p = mll_p->prev) { + if (mll_p == prev_feed_mll_p) { + /* not the first; so don't use default for first */ + return(0.0); + } + + if (mll_p->str == S_SSV && mll_p->u.ssv_p->context == C_SCORE && + mll_p->u.ssv_p->used[LABEL] == YES) { + /* explicit label for first, so don't use default */ + return(0.0); + } + } + (void) sprintf(dfltlabel, "%c%c ", FONT_TR, DFLT_SIZE); + return(strwidth(dfltlabel)); +} diff --git a/mup/mup/charinfo.c b/mup/mup/charinfo.c new file mode 100644 index 0000000..7f010f4 --- /dev/null +++ b/mup/mup/charinfo.c @@ -0,0 +1,3081 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions related to characters: information about the size and shape of + * characters to be printed, to initialize the internal tables + * to tell how big each character is, etc. + */ + +#include +#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)); + + +/* 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) ); +} + + +/* 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) ); +} + + +/* 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) ); +} + + +/* 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) ); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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 + + +/* 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 + + +/* 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 + + +/* 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 + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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])); +} + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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) ] ); + } +} + + +/* 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); +} + + +/* 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') { + ; + } +} + + +/* 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); +} + + +/* 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); +} + + +/* + * 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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])); +} + + +/* Map STR_MUS_CHAR* to FONT_MUSIC* */ + +int +str2mfont(str) + +int str; /* STR_MUS_CHAR* */ + +{ + switch (str) { + case STR_MUS_CHAR: + return(FONT_MUSIC); + case STR_MUS_CHAR2: + return(FONT_MUSIC2); + default: + pfatal("impossible str 0x%x in str2mfont", str); + /*NOTREACHED*/ + return(FONT_MUSIC); + } +} + +/* Map FONT_MUSIC* to STR_MUS_CHAR* */ + +int +mfont2str(mfont) + +int mfont; /* FONT_MUSIC* */ + +{ + switch (mfont) { + case FONT_MUSIC: + return(STR_MUS_CHAR); + case FONT_MUSIC2: + return(STR_MUS_CHAR2); + default: + pfatal("impossible mfont %d in mfont2str", mfont); + /*NOTREACHED*/ + return(STR_MUS_CHAR); + } +} diff --git a/mup/mup/check.c b/mup/mup/check.c new file mode 100644 index 0000000..e329b9c --- /dev/null +++ b/mup/mup/check.c @@ -0,0 +1,1994 @@ + +/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions for checking for various classes of errors such as + * values out of range, or trying to do something in an illegal context. + * Also contains the code to combine multiple measures of rests into + * multirests. */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + +static struct MAINLL *add_pre_meas P((struct MAINLL *insert_p, int start, + int end, int add_bar)); +static int check_all_rests P((struct STAFF *staff_p, int count)); +static void do_combine P((struct MAINLL *begin_p, struct MAINLL *end_p, + int nummeas, int min_combine)); +static int valid_mark_item P((int mark, int place)); +static void mv_accs P((struct MAINLL *mll_p)); +static void move_xoct P((struct STUFF *stuff_p, struct MAINLL *newfirst_p, + int staffno, int bars, int start)); +static void addped P((struct STUFF *pedal_p, struct MAINLL *mll_p)); + + + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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"); + } +} + + +/* 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; +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); + } +} + + +/* 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; + } + } + } +} + + +/* 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); +} + + +/* 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; + } + } + } +} + + +/* 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(""); + } +} + + +/* 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); + } + } +} + + +/* 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); +} + + +/* + * 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); + } + } +} + + +/* 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. + */ + } +} + + +/* 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]; + } + } + } + } + } +} + + +/* 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); + } +} + + +/* If the passed-in pedal_p points to a pedal stuff that indicates the + * pedal state needs to be altered at the beginning of the STAFF passed in, + * then do that. This is for -x, for like when the slice begins where the + * pedal was held down from the previous measure, so we have to add a begped. + */ + +static void +addped(pedal_p, mll_p) + +struct STUFF *pedal_p; /* last pedal state of previous measures */ +struct MAINLL *mll_p; /* points to a STAFF, to add pedal to */ + +{ + int s; /* staff number */ + struct STUFF *stuff_p; /* walk through stuff list */ + struct STUFF **prev_p_p; /* This holds the address + * of the previous' next, + * which is where we will need + * to update if we need to delete + * or insert a STUFF. + */ + + s = mll_p->u.staff_p->staffno; + if (pedal_p == 0 || pedal_p->string == 0) { + /* There is no pedal carrying over into this measure, + * so no need to add anything. */ + return; + } + + /* If last pedal mark was an endped, we don't need to move one in, + * because pedal is off; otherwise we do. */ + if (pedal_p->string[4] != C_ENDPED) { + + /* Need to add a pedal STUFF at count 1 if + * there isn't already one at or before there. + * See if there's already one there. + */ + for (stuff_p = mll_p->u.staff_p->stuff_p, + prev_p_p = &(mll_p->u.staff_p->stuff_p); + stuff_p != 0; + prev_p_p = &(stuff_p->next), + stuff_p = stuff_p->next) { + if (stuff_p->stuff_type == ST_PEDAL && + stuff_p->start.count + <= 1.0) { + /* Already had a pedal at beginning of measure. + * If it's an ENDPED, + * that negates the one coming in, + * and it ought to be removed. + * If it's a PEDAL, need to change to a BEGPED. + * In any case, we don't need + * to check any more STUFFs for this STAFF. + */ + if (stuff_p->string[4] == C_ENDPED) { + /* delete it */ + *prev_p_p = stuff_p->next; + } + else if (stuff_p->string[4] == C_PEDAL) { + stuff_p->string[4] = C_BEGPED; + } + break; + } + } + if (stuff_p == 0) { + /* There wasn't a pedal at the + * beginning of the new first measure, + * so we will need to add one. + */ + struct STUFF *newped_p; + + newped_p = newSTUFF(pedal_p->string, + pedal_p->dist, + pedal_p->dist_usage, + 1.0, 0.0, 0, 0, 0.0, + ST_PEDAL, + pedal_p->modifier, + pedal_p->place, + pedal_p->inputfile, + pedal_p->inputlineno); + newped_p->string[4] = C_BEGPED; + + /* figure out where to insert it */ + for (stuff_p = mll_p->u.staff_p->stuff_p, + prev_p_p = &(mll_p->u.staff_p->stuff_p); + stuff_p != 0; + prev_p_p = &(stuff_p->next), + stuff_p = stuff_p->next) { + if (stuff_p->place == PL_ABOVE) { + /* not far enough yet */ + continue; + } + if (pedal_p->all == YES && stuff_p->all == NO){ + continue; + } + if (stuff_p->start.count < 1.0) { + continue; + } + /* found right place */ + break; + } + if (prev_p_p == 0) { + pfatal("failed to find place to insert pedal for -x"); + } + + /* insert into STUFF list */ + newped_p->next = *prev_p_p; + *prev_p_p = newped_p; + } + } +} diff --git a/mup/mup/debug.c b/mup/mup/debug.c new file mode 100644 index 0000000..101eff0 --- /dev/null +++ b/mup/mup/debug.c @@ -0,0 +1,888 @@ + +/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + + + +/* routines for printing info for debugging purposes */ +/* It would be nicer to write a program to read the header files and + * generate most of these routines from there to keep them up to date, + * but this will do for now. */ + + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + +/* for number-to-English name translations, if we fall off the bottom of + * a switch without a match, need to return something, so use "unknown" */ +static char Unknown[] = "unknown"; + + +/* static functions */ +static void print_ssv P((struct SSV *ssv_p)); +static void print_markorder P((struct SSV *ssv_p, int place)); +static void print_printdata P((struct PRINTDATA *printdata_p)); +static void print_bar P((struct BAR *bar_p)); +static void print_chhead P((struct CHORD *ch_p)); +static void print_staff P((struct STAFF *staff_p)); +static void print_grpsyl P((struct GRPSYL *g_p, char *gstype, int vno)); +static void print_slurtolist P((struct NOTE *note_p)); +static void pr_stuff P((struct STUFF *stuff_p)); +static char *xlate_place P((int place)); +static char *xlate_stufftype P((int stuff_type)); +static char * xlate_linetype P((int ltype)); +static char *xlate_gvalue P((int grpvalue)); +static char *xlate_gsize P((int grpsize)); +static char *xlate_gcont P((int gcont)); +static char *xlate_item P((int item)); +static char *xlate_dir P((int dir)); +static void print_curve P((struct CURVE *curve_p)); +static char *xlate_coordtype P((int coordtype)); + + +/* 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; + } + } +} + + +/* 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); + } +} + + +/* 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"); +} + + +/* 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); +} + + +/* 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]); + } + } +} + + +/* 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); + } + } +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* translate direction to name */ + +static char * +xlate_dir(dir) + +int dir; + +{ + switch(dir) { + case UP: + return("UP"); + case DOWN: + return("DOWN"); + default: + return("UNKNOWN"); + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); + } + } +} + + +/* 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"); + } +} + + +/* 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"); + } +} + + +/* 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"); + } +} + + +static void +print_curve(curve_p) + +struct CURVE *curve_p; + +{ + struct COORD_INFO *cinfo_p; + int n; + + if (debug_on(128) == 0) { + return; + } + + for (n = 0; n < curve_p->ncoord; n++) { + if ((cinfo_p = find_coord(curve_p->coordlist[n].hor_p)) != 0) { + debug(128, "\thor_p = 0x%lx, page = %d, score = %d, pseudo_bar_p = %lx", + curve_p->coordlist[n].hor_p, + cinfo_p->page, cinfo_p->scorenum, + cinfo_p->pseudo_bar_p); + } + debug(128, "\thtype = %s, hsteps = %f, counts = %f", + xlate_coordtype(curve_p->coordlist[n].htype), + curve_p->coordlist[n].hsteps, + curve_p->coordlist[n].counts); + if ((cinfo_p = find_coord(curve_p->coordlist[n].vert_p)) != 0) { + debug(128, "\tvert_p = 0x%lx, page = %d, score = %d, pseudo_bar_p = %lx", + curve_p->coordlist[n].vert_p, + cinfo_p->page, cinfo_p->scorenum, + cinfo_p->pseudo_bar_p); + } + debug(128, "\tvtype = %s, vsteps = %f\n", + xlate_coordtype(curve_p->coordlist[n].vtype), + curve_p->coordlist[n].vsteps); + } +} + +/* given an absolute coordinate type like AX, return its name */ + +static char +*xlate_coordtype(coordtype) + +int coordtype; + +{ + switch(coordtype) { + case AX: + return("AX"); + case AY: + return("AY"); + case AN: + return("AN"); + case AS: + return("AS"); + case AE: + return("AE"); + case AW: + return("AW"); + default: + return(Unknown); + } +} diff --git a/mup/mup/defines.h b/mup/mup/defines.h new file mode 100644 index 0000000..560516b --- /dev/null +++ b/mup/mup/defines.h @@ -0,0 +1,1327 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2006 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * defines.h + * + * This file defines the constants needed for the music publication + * program. + */ + +#include +#ifndef _DEFINES +#define _DEFINES +#include "muschar.h" + +/* + * Define the environment ============================================= + */ + +/* for all forms of DOS we've tried, make sure __DOS__ is defined */ +#if defined(__TURBOC__) || defined(__WATCOMC__) || defined(__MINGW32__) +#ifndef __DOS__ +#define __DOS__ +#endif +#endif + +/* if you are short on memory or know you'll never use the extended character + * set (with accented characters, etc) you can undefine EXTCHAR + */ +#ifndef __TURBOC__ +#define EXTCHAR +#endif +#include "extchar.h" + +/* the following is needed for the DOS port of the GNU C compiler */ +#ifdef __DJGPP__ +#define __DOS__ +#undef unix +#endif + +/* + * Based on system type, #define or don't #define various symbols, as follows: + * + * UNIX_LIKE_FILES If defined, files can be simultaneously read from and + * written to and invisibly unlinked. + * UNIX_LIKE_PATH_RULES If defined, use these rules for MUPPATH. + * DOS_LIKE_PATH_RULES If defined, use these rules for MUPPATH. + * CORE_MESSAGE If defined, then a creating core error message will be + * printed in debug mode. + * NEED_GETOPT If defined, the getopt suite is not available, + * therefore use the limited one in main.c. + * MAGIC_FILE_HOME If defined, check for magic file in $HOME. + * MAGIC_FILE_NAME Name of magic file. + * OPTION_MARKER The char which preceeds command line options. + */ +#ifdef unix +#define UNIX_LIKE_FILES +#define UNIX_LIKE_PATH_RULES +#define CORE_MESSAGE +#define MAGIC_FILE_HOME +#define MAGIC_FILE_NAME ".mup" +#define OPTION_MARKER '-' +#endif + +#ifdef VMS +#define MAGIC_FILE_HOME +#define MAGIC_FILE_NAME ".mup" +#define OPTION_MARKER '-' +#endif + +#ifdef AMIGA +#undef UNIX_LIKE_FILES +#define NEED_GETOPT +#define MAGIC_FILE_HOME +#define MAGIC_FILE_NAME ".mup" +#define OPTION_MARKER '-' +#endif + +#ifdef __DOS__ +#define DOS_LIKE_PATH_RULES +#define NEED_GETOPT +#define MAGIC_FILE_NAME "mup.ok" +#define OPTION_MARKER '/' +#endif + +#ifdef Mac_BBEdit +#undef UNIX_LIKE_FILES +#define NEED_GETOPT +/* skip length byte of Pascal string literal */ +#define MAGIC_FILE_NAME (char *)(MupRegFileName + 1); +#define OPTION_MARKER '-' +#endif + +#ifdef __EMX__ +#undef UNIX_LIKE_FILES +#define DOS_LIKE_PATH_RULES +#define MAGIC_FILE_HOME +#define MAGIC_FILE_NAME ".mup" +#define OPTION_MARKER '-' +#endif + +#ifndef OPTION_MARKER +/* use - as default if nothing has been defined for it */ +#define OPTION_MARKER '-' +#endif + +/* + * Define ranges for variables ============================================= + */ + +/* + * Define maximum value for exit code from Mup. Must be less than 128 + * to be able to distinguish from WAIT_ABANDONED value on Windows. + */ +#define MAX_ERRORS (127) + +/* text point sizes */ +#define MINSIZE (1) +#define MAXSIZE (100) + +/* key signatures */ +#define MINSHARPS (-7) +#define MAXSHARPS (7) +#define DEFSHARPS (0) + +/* octave */ +#define MINOCTAVE (0) +#define MAXOCTAVE (9) +#define DEFOCTAVE (4) + +/* staves */ +#define MINSTAFFS (1) +#define MAXSTAFFS (40) +#define DEFSTAFFS (1) + +/* voices */ +#define MINVOICES (1) +#define NORMVOICES (2) +#define MAXVOICES (3) + +/* number of lines in a tablature staff */ +#define MINTABLINES (1) +#define DEFTABLINES (6) /* see Guitar[] in globals.c */ +#define MAXTABLINES (9) + +/* number of ticks on a string designation for tablature */ +#define MINTICKS (0) +#define MAXTICKS (MAXTABLINES - 1) + +#define TABDEFOCT (4) + +/* tablature fret numbers, including pseudo fret numbers */ +#define MINFRET (0) +#define MAXFRET (99) +#define DEFFRET (0) +#define NOFRET (MAXFRET + 1) +#define IN_UPWARD (MAXFRET + 2) /* slur from nowhere, going up */ +#define IN_DOWNWARD (MAXFRET + 3) /* slur from nowhere, going down */ +#define OUT_UPWARD (MAXFRET + 4) /* slur to nowhere, going up */ +#define OUT_DOWNWARD (MAXFRET + 5) /* slur to nowhere, going down */ +#define IS_NOWHERE(fret) ((fret) >= IN_UPWARD && (fret) <= OUT_DOWNWARD) + +/* range of frets that can be printed by a chord grid */ +#define MINGRIDFRET (2) +#define MAXGRIDFRET (MAXFRET) +#define DEFGRIDFRET (4) +#define NOGRIDFRET (-1) /* must be negative so user can't enter it */ + +/* USE_DFLT_OCTAVE has to be number that is not a valid octave, nor a */ +/* valid fret number. But it has to be positive and small enough to be */ +/* able to add MAX_OCTAVE to it */ +#define USE_DFLT_OCTAVE (MAXFRET + 6) + +/* min and max numbers for bend integers, numerators, and denominators */ +#define BENDINTBITS (4) +#define MINBENDINT (0) +#define MAXBENDINT ((1 << BENDINTBITS) - 1) +#define BENDNUMBITS (6) +#define MINBENDNUM (0) +#define MAXBENDNUM ((1 << BENDNUMBITS) - 1) +#define BENDDENBITS (6) +#define MINBENDDEN (1) +#define MAXBENDDEN ((1 << BENDDENBITS) - 1) + +/* time unit */ +/* -1 means quadruple whole and 0 means double whole. Actually, less than -1 */ +/* is allowed, and it's minus the number of measures in a multirest */ +#define MINBASICTIME (-1) +#define MAXBASICTIME (256) + +/* the biggest number that is allowed on a multirest */ +#define MAXMULTINUM (1000) + +/* limits for scaling the output */ +#define MINSCALE (0.1) +#define MAXSCALE (10.0) +#define DEFSCALE (1.0) + +/* limits for scaling a staff relative to the output as a whole */ +#define MINSTFSCALE (0.1) +#define MAXSTFSCALE (10.0) +#define DEFSTFSCALE (1.0) + +#define MINGRIDSCALE (0.1) +#define MAXGRIDSCALE (10.0) +#define DEFGRIDSCALE (1.0) + +/* limits on min distance required between a chord and its staff (stepsizes) */ +#define MINCHORDDIST (0) +#define MAXCHORDDIST (50) +#define DEFCHORDDIST (3) + +/* limits on min dist required between other stuff and its staff (stepsizes) */ +#define MINDIST (0) +#define MAXDIST (50) +#define DEFDIST (2) + +/* limits on min distance required between a cresc and its staff (stepsizes) */ +#define MINDYNDIST (0) +#define MAXDYNDIST (50) +#define DEFDYNDIST (0) + +/* vertical space between staffs and scores, in units of stepsize */ +#define MINMINSTSEP (6) /* min user-specified min between staffs */ +#define DEFMINSTSEP (10) /* default min between staffs */ +#define MINMINSCSEP (6) /* min user-specified min between scores */ +#define DEFMINSCSEP (12) /* default min between scores */ +#define MINMAXSCSEP MINMINSCSEP /* min user-specified max between scores */ +#define DEFMAXSCSEP (20) /* default max between scores */ +#define MAXSEPVAL ((int)(PGHEIGHT / STEPSIZE)) /* max for either one */ +#define MINSTPAD (-MAXSEPVAL) /* min user-spec. white between staffs */ +#define MAXSTPAD (MAXSEPVAL) /* max user white between staffs */ +#define DEFSTPAD (0) /* default white between staffs */ +#define MINMINSCPAD (-MAXSEPVAL) /* min user-spec. white between scores */ +#define DEFMINSCPAD (2) /* default white between scores */ +#define MINMAXSCPAD (-MAXSEPVAL) /* min user-spec. white between scores */ +#define DEFMAXSCPAD (2) /* default white between scores */ +#define MAXPADVAL (MAXSEPVAL) /* max user white between scores */ + +/* distance from center line a rest should be forced to be */ +#define MINRESTDIST (-50) +#define MAXRESTDIST (50) +#define NORESTDIST (11111) /* this means it is not set */ + +/* number of mr needed to combine into a multirest (like -c option) */ +#define MINRESTCOMBINE (2) +#define MAXRESTCOMBINE (1000) +#define NORESTCOMBINE (-1) /* must be negative so user can't enter it */ + +/* page number to be put on the first page (like -p option) */ +#define MINFIRSTPAGE (1) +#define MAXFIRSTPAGE (5000) +#define NOFIRSTPAGE (0) /* this means it is not set */ + +/* number to multiply linear regression slope by to get beam's slope */ +#define MINBEAMFACT (0.0) +#define MAXBEAMFACT (1.0) +#define DEFBEAMFACT (1.0) + +/* maximum beam angle allowed, in degrees */ +#define MINBEAMMAX (0.0) +#define MAXBEAMMAX (45.0) +#define DEFBEAMMAX (20.0) + +/* angle of beam specified by the "slope" interchord attribute */ +#define MINBEAMANGLE (-MAXBEAMMAX) +#define MAXBEAMANGLE (MAXBEAMMAX) +#define NOBEAMANGLE (2 * MAXBEAMANGLE) /* something out of range */ + +/* padding to be applied on the left of every group (and the right of the */ +/* last group in the measure), in stepsizes */ +#define MINPAD (-5.0) +#define MAXPAD (50.0) +#define DEFPAD (0.0) + +/* for setting and testing unknown stem length */ +#define STEMLEN_UNKNOWN (-1.0) +#define IS_STEMLEN_KNOWN(x) ((x) >= 0.0) /* avoid using "==" on floats */ +#define IS_STEMLEN_UNKNOWN(x) ((x) < 0.0) /* avoid using "==" on floats */ + +/* other stem length definitions */ +#define MINSTEMLEN (0.0) +#define DEFSTEMLEN (7.0) +#define MAXSTEMLEN (100.0) +#define SM_STEMFACTOR (5.0 / 7.0) /* grace/cue factor */ + +/* number of stepsizes by which a beamed stem can be shortened */ +#define MINSTEMSHORTEN (0.0) +#define MAXSTEMSHORTEN (2.0) +#define DEFSTEMSHORTEN (1.0) + +/* what fraction of each lyrics syllable goes left of the center of chord */ +#define MINLYRICSALIGN (0.0) +#define MAXLYRICSALIGN (1.0) +#define DEFLYRICSALIGN (0.25) + +/* size of the paper */ +#define MINPAGEHEIGHT (2.0) +#define MAXPAGEHEIGHT (24.0) +#define DEFPAGEHEIGHT (11.0) +#define MINPAGEWIDTH (2.0) +#define MAXPAGEWIDTH (24.0) +#define DEFPAGEWIDTH (8.5) + +/* top and bottom margins */ +#define MINVMARGIN (0.0) +#define MAXVMARGIN (3.0) +#define DEFVMARGIN (0.5) + +/* left and right margins */ +#define MINHMARGIN (0.0) +#define MAXHMARGIN (3.0) +#define DEFHMARGIN (0.5) + +/* panels per page */ +#define MINPANELSPERPAGE (1) +#define MAXPANELSPERPAGE (2) +#define DEFPANELSPERPAGE (1) + +/* how tightly to pack the stuff horizontally (default value) */ +#define MINPACKFACT (0.0) +#define DFLTPACKFACT (1.0) +#define MAXPACKFACT (10.0) + +/* how much to expand long notes relative to short ones */ +#define MINPACKEXP (0.0) +#define DFLTPACKEXP (0.8) +#define MAXPACKEXP (1.0) + +/* time signature */ +#define MINNUMERATOR (1) +#define MAXNUMERATOR (99) + +#define MINDENOMINATOR (1) +#define MAXDENOMINATOR (64) + +#define MINDIVISION (1) +#define DEFDIVISION (192) +#define MAXDIVISION (3 * 512) + +/* define values for the "release" parameter, in milliseconds */ +#define MINRELEASE (0) +#define DEFRELEASE (20) +#define MAXRELEASE (500) + +/* define values for the "sylposition" parameter, in points */ +#define MINSYLPOSITION (-100) +#define MAXSYLPOSITION (100) +#define DEFSYLPOSITION (-5) +#define NOSYLPOSITION (11111) /* this means it is not set */ + + +/* + * Define sets of symbols which probably should have been done as enums, + * but in ANSI C enums aren't much good anyhow. ============================= + * Also define some macros for testing these enums. + */ + +/* + * To limit the number of terminal symbols so that yacc won't blow up, + * several tokens map to the same terminal symbol, and we set a variable + * (yylval) to say which particular one was actually seen. + */ +#define F_STAFFS (1) +#define F_OCTAVE (2) +#define F_LYRSIZE (3) +#define F_VERTSPACE (4) +#define F_SIZE (5) + +#define F_TOPMARGIN (6) +#define F_BOTMARGIN (7) +#define F_LEFTMARGIN (8) +#define F_RIGHTMARGIN (9) + +#define F_TIMEUNIT (10) +#define F_VSCHEME (11) + +#define F_BRACKET (12) +#define F_BRACE (13) +#define F_BARSTYLE (14) + +#define F_LABEL (15) +#define F_LABEL2 (16) + +#define F_FONT (17) +#define F_LYRFONT (18) + +#define F_VISIBLE (19) +#define F_VERSES (20) + +/* + * Define all the types of context in the input. Make each one a bit, so that + * we can also define a couple groupings of them. + */ +#define C_HEADER (0x1) /* first page header */ +#define C_FOOTER (0x2) /* first page footer */ +#define C_HEAD2 (0x4) /* later page header */ +#define C_FOOT2 (0x8) /* later page footer */ +#define C_TOP (0x10) /* initial block at top */ +#define C_BOT (0x20) /* initial block at bottom */ +#define C_TOP2 (0x40) /* later block at top */ +#define C_BOT2 (0x80) /* later block at bottom */ +#define C_BLOCK (0x100) /* other block */ +#define C_SCORE (0x200) /* the whole score */ +#define C_STAFF (0x400) /* a staff */ +#define C_VOICE (0x800) /* a voice */ +#define C_MUSIC (0x1000) /* notes, etc. */ +#define C_GRIDS (0x2000) /* chord grids */ +#define C_HEADSHAPES (0x4000) /* head shapes for notehead characters */ + +/* context classes--combining things that mostly have the same rules */ +#define C_BLOCKHEAD (C_HEADER | C_FOOTER | C_HEAD2 | C_FOOT2 | \ + C_TOP | C_BOT | C_TOP2 | C_BOT2 | C_BLOCK) +#define C_SSV (C_SCORE | C_STAFF | C_VOICE) + +/* define whether things are measured in inches or centimeters */ +#define INCHES (0) +#define CM (1) + +/* + * Define the voice schemes. V_1 means just one voice is on the staff; + * the program will decide the stem direction of each group. V_2OPSTEM + * means there are two voices with opposing stems: the first voice always + * points up, and the second one always points down. V_2FREESTEM means there + * are two voices. If, at any time, one has a space, the other one's stems + * can point either way (as with one voice). Otherwise, the first voice + * points up and the second one down. + * V_3OPSTEM and V_3FREESTEM are just like the "2" ones, except that a third + * voice is allowed to exist. Its stem direction is determined elsewhere. + */ +#define V_1 (0) +#define V_2OPSTEM (1) +#define V_2FREESTEM (2) +#define V_3OPSTEM (3) +#define V_3FREESTEM (4) + +/* + * Define the modes of the voicecombine parameter. + */ +/* bottom note of high voice must be higher than top note of low voice */ +#define VC_NOOVERLAP (0) +/* bottom note of high voice must be no lower than top note of low voice */ +#define VC_SHAREONE (1) +/* no restrictions */ +#define VC_OVERLAP (2) + +/* + * Define the staff style vis-a-vis printing of clefs, accidentals (in key + * signatures and otherwise), and tranposing. WARNING: SS_NOTHING must be + * defined to be 0 so that calloc inits the field to this. + */ +#define SS_NOTHING (0) /* no transpose; print no clef, no accidentals*/ +#define SS_NORMAL (1) /* normal printing */ +#define SS_DRUM (2) /* like SS_NOTHING, but print a "drum clef" */ + +/* + * Define the time signature types. NUMERIC is the usual two-number + * signature. INVISNUM is the same, except that it will not be printed. + * Common and cut time are noted here separately. But for all other + * purposes they are treated as 4/4 and 2/2 respectively. + */ +#define TS_NUMERIC (0) +#define TS_INVISNUM (1) +#define TS_COMMON (2) +#define TS_CUT (3) + +/* + * Special bytes used inside time signature representation. + * These values need to be outside the range of time signature numerators + * and denominators, but small enough to fit in a byte. + * Probably safer to keep them under 128 as well, to avoid any possible + * issues with negative chars. + * + * Here's how the encoding works: + * cut and common get stored as TSR_CUT and TSR_COMMON respectively. + * If a + is used between a denominator of one fraction + * and numerator of another, it is encoded as TSR_ADD. + * When a + is used inside a numerator, nothing is stored at all, + * since it is clear all numbers up to the slash + * must be components of the numerator. + * White space rather than + after a denominator + * means alternating time signatures, marked internally by TSR_ALTERNATING. + * Numbers are stored as their binary values. + * A TSR_END is placed at the end of everything to mark the end. + * A null is used for that, so one could use things like strlen or strcpy + * on a representation. + */ +#define TSR_CUT (MAXNUMERATOR + 1) +#define TSR_COMMON (MAXNUMERATOR + 2) +#define TSR_SLASH (MAXNUMERATOR + 3) +#define TSR_ADD (MAXNUMERATOR + 4) +#define TSR_ALTERNATING (MAXNUMERATOR + 5) +#define TSR_END (0) + +/* + * This is the maximum length of an internal time signature representation. + * Note that the internal form is more compact than the input form, + * so even something so ridiculously complicated that it's doubtful any + * human could keep it straight, like + * 3+1+4/16 + cut + 7+11+41/2 9+2/64 + 5+7+31+29/1 + com + * would only take 28 bytes, so 40 should be plenty! + * The maximum number of numerator components 40 bytes could accomodate + * would be 37, so maximum theoretical effective time signature + * would be thirty-seven 99's or 3663 counts. + */ +#define MAXTSLEN 40 + +/* + * Define when time signatures should be printed. "Once" means when it + * changes. "Always" makes sense only when there is an alternating time sig, + * and it means print it at each measure. + */ +#define PTS_NEVER (0) /* user input "n" */ +#define PTS_ONCE (1) /* user input nothing */ +#define PTS_ALWAYS (2) /* user input "y" */ + +/* + * Define the clefs that are allowed. The values are important, so that + * the program can conveniently figure note positions without having a + * separate case for each value. + */ +#define TREBLE_8A (-7) +#define FRENCHVIOLIN (-2) +#define TREBLE (0) +#define SOPRANO (2) +#define MEZZOSOPRANO (4) +#define ALTO (6) +#define TREBLE_8 (7) +#define TENOR (8) +#define BARITONE (10) +#define BASS (12) +#define TABCLEF (-1) /* tablature "clef" */ +#define NOCLEF (-99) /* no clef is present */ + +/* + * Define what a GRPSYL structure can represent. + */ +#define GS_GROUP (0) +#define GS_SYLLABLE (1) + +/* + * Define the different contents a group can have. + */ +#define GC_NOTES (0) +#define GC_REST (1) +#define GC_SPACE (2) + +/* + * Define the time values a group can have. Only note groups can be other than + * normal (grace notes). There are no grace rests or spaces. + */ +#define GV_NORMAL (0) +#define GV_ZERO (1) + +/* + * Define the unknown value for headshapes. The other values aren't defined + * here because they are established as headshapes are loaded at run time. + * There is a built-in set of these that are loaded, and then the user can use + * the "headshapes" context to load more. Each headshape number corresponds to + * a headshape name, such as "norm", "xnote", "rect", etc., and stands for the + * set of music characters used to print note heads of the various basictimes. + */ +#define HS_UNKNOWN (0) + +/* + * Define the size of a group. Spaces are always normal, but notes and rests + * can have different sizes. For note groups, this can vary on a per-note + * basis. + */ +#define GS_NORMAL (0) +#define GS_SMALL (1) + +/* + * Define position that you can be in relative to a list of objects. + */ +#define NOITEM (0) /* not within a list */ +#define STARTITEM (1) /* first item in a list */ +#define INITEM (2) /* interior item in a list */ +#define ENDITEM (3) /* last item in a list */ +#define LONEITEM (4) /* only item in a list */ + + +/* + * Define the directions for various items. + */ +#define UNKNOWN (0) +#define UP (1) +#define DOWN (2) + + +/* + * Define values for controlling printing of tuplet numbers and brackets. + * For PT_DEFAULT, the bracket will be printed unless all the notes of the + * tuplet (and no other notes) form a beamed set. + */ +#define PT_NEITHER (0) /* never print number or bracket */ +#define PT_DEFAULT (1) /* always print number; maybe print bracket */ +#define PT_BOTH (2) /* always print number and bracket */ +#define PT_NUMBER (3) /* always print just the number */ + + +/* + * Coordinate types that can have location variables associated with them. + */ +#define CT_BUILTIN (1) +#define CT_GRPSYL (2) +#define CT_BAR (4) +#define CT_NOTE (8) +#define CT_INVISIBLE (128) + + +/* + * Define the types of STUFF structure. "Stuff" is things that are to be + * printed other than the actual music and lyrics. + */ +#define ST_ROM (0) +#define ST_BOLD (1) +#define ST_ITAL (2) +#define ST_BOLDITAL (3) +#define ST_CRESC (4) +#define ST_DECRESC (5) +#define ST_MUSSYM (6) +#define ST_PEDAL (7) +#define ST_TIESLUR (8) +#define ST_TABSLUR (9) +#define ST_BEND (10) +#define ST_PHRASE (11) +#define ST_OCTAVE (12) +#define ST_MIDI (13) + +#define IS_TEXT(stype) ((stype) == ST_ROM || (stype) == ST_ITAL || \ + (stype) == ST_BOLD || (stype) == ST_BOLDITAL) + +/* + * Define the places where the stuff can be printed, relative to staff(s). + */ +#define PL_ABOVE (0) +#define PL_BELOW (1) +#define PL_BETWEEN (2) +#define PL_UNKNOWN (3) +#define NUM_PLACE (3) /* number of "good" places (exclude unknown) */ + +/* + * Define the ways a user can specify the horizonal offset of a group from the + * chord's X coordinate. + */ +#define HO_NONE (0) /* not specified */ +#define HO_LEFT (1) /* "-" (next to other group(s), on the left) */ +#define HO_RIGHT (2) /* "+" (next to other group(s), on the right) */ +#define HO_VALUE (3) /* "+/-N" (offset given by GRPSYL.ho_value) */ + +/* + * Define text modifiers: different flavors of rom, bold, ital, and + * boldital. TM_DYN also applies automatically to the hairpin stuffs, < and >. + */ +#define TM_NONE (0) +#define TM_CHORD (1) +#define TM_ANALYSIS (2) +#define TM_FIGBASS (3) +#define TM_DYN (4) + +#define IS_CHORDLIKE(x) ((x) == TM_CHORD || (x) == TM_ANALYSIS || \ + (x) == TM_FIGBASS) + +/* + * Define values for dist_usage in STUFF. + */ +#define SD_NONE (0) /* user did not specify */ +#define SD_MIN (1) /* user specified minimum distance */ +#define SD_FORCE (2) /* user is forcing this distance */ + +/* + * Define all the types of marks that the user can request to be stacked in + * different orders. This list is in increasing order of the default priority + * of stacking, except that by default MK_DYN, MK_OTHERTEXT, and MK_CHORD are + * of equal priority. If this list changes, make sure that Defmarkorder[] + * is updated too. For each place (above, below, between), the user can + * specify a different ordering of priority to be used. There is a restriction + * that the last ones (MK_LYRICS, MK_ENDING, MK_REHEARSAL, MK_PEDAL) must + * have a different priority from each other and any of the other ones. Also, + * MK_PEDAL is allowed only below; MK_ENDING and MK_REHEARSAL are allowed only + * above; and those three and MK_OCTAVE are not allowed between. + */ +#define MK_MUSSYM (0) /* ST_MUSSYM */ +#define MK_OCTAVE (1) /* ST_OCTAVE */ +#define MK_DYN (2) /* ST_CRESC or ST_DECRESC; or ST_ROM, */ + /* ST_ITAL, ST_BOLD, ST_BOLDITAL with "dyn" */ + /* (TM_DYN is set for these and only these) */ +#define MK_OTHERTEXT (3) /* ST_ROM, ST_ITAL, ST_BOLD, ST_BOLDITAL */ + /* without chord/analysis/figbass or dyn */ +#define MK_CHORD (4) /* ST_ROM, ST_ITAL, ST_BOLD, ST_BOLDITAL */ + /* with chord, analysis, or figbass */ + /* (TM_CHORD is set for these and only these) */ +#define MK_LYRICS (5) /* lyrics */ +#define MK_ENDING (6) /* ending mark */ +#define MK_REHEARSAL (7) /* rehearsal mark */ +#define MK_PEDAL (8) /* ST_PEDAL */ +#define NUM_MARK (9) /* this must follow the last MK */ + +/* + * While parsing, we need to temporarily store some things as pseudo-pitches. + * When the user does not specify any pitch for the first group of a measure, + * we temporarily use PP_NO_PITCH, since not specifying a pitch is legal iff it + * is for one or more 1-line staffs, but it's not easy to check on that until + * later. We also need to save rest, space, and rpt as pseudo notes until we + * later map them to groups. + */ +#define PP_NO_PITCH 'h' +#define PP_REST 'r' +#define PP_SPACE 's' +#define PP_RPT 'p' + +/* + * Define the other staff that a given staff's groups are beamed or stemmed to. + */ +#define CS_SAME (0) +#define CS_ABOVE (1) +#define CS_BELOW (2) + +/* + * Define symbols for indexing coordinate arrays. The first 12 are X, Y, + * north, south, east, and west, both relative and absolute. Not all things + * that have coordinates bother to set all 12 of these. There should be + * comments in structs.h saying which things get set for what. + * + * In GRPSYL, during the time that positions of phrase marks are being + * figured out, AN and AS are used in a strange way. But later, they get + * set to their intended values. + * + * The 13th is a special number used by nongrace notes and GRPSYLs, and BARs + * only. For notes and GRPSYLs, it has the following meaning. It indicates + * how many inches of horizontal space would be allocated to this object + * if it were a whole note instead of whatever it actually is, but were + * allocated space proportionally. That is, fulltime times this number + * is the amount of space between the X coordinates of this GRPSYL and + * the next one in the measure (or the bar line if this is the last GRPSYL + * in the measure). Notice that even for notes, it's the X coordinate of + * the note's GRPSYL that count, even if the note head is on the "wrong" + * side of the stem. For BARs, this 13th number has a similiar use. If + * you pretend that a bar line is count 0 of the following measure, and + * the first GRPSYL of the measure is at count 1 (whichever type of note + * constitutes a "count"), this number is how many inches would be allocated + * to a whole note instead of the one count of space that is there. + */ +#define RX (0) +#define RY (1) +#define RN (2) +#define RS (3) +#define RE (4) +#define RW (5) +#define AX (6) +#define AY (7) +#define AN (8) +#define AS (9) +#define AE (10) +#define AW (11) +#define INCHPERWHOLE (12) +#define NUMCTYPE (13) + + +/* + * AN and AS of group coordinates are used temporarily to store the distance + * from the group to any phrase marks, to be used to make sure nesting phrases + * don't impinge on that space. But if a group has a phrase ending on it and + * another beginning on it, those won't collide. So use bitmap to keep track + * of whether the AN and AS values apply to east side, west side, or both. + * (phraseside in GRPSYL is a bit map.) + */ +#define EAST_SIDE (1 << 0) +#define WEST_SIDE (1 << 1) + + +/* + * Define the types of bar line. + */ +#define INVISBAR (0) +#define SINGLEBAR (1) +#define DOUBLEBAR (2) +#define REPEATSTART (3) +#define REPEATEND (4) +#define REPEATBOTH (5) +#define ENDBAR (6) +#define RESTART (7) + +/* + * Define the types of font, leaving 0 unused to avoid ending up having + * null characters appear in strings where this number is stored, + * and to have something convenient to use to flag an unknown font. + * WARNING: the getfontinfo.c program depends on all the font names + * beginning with "FONT_", and on MAXFONTS being at the end of the list. + */ +#define FONT_UNKNOWN (0) +#define FAMILY_DFLT (-1) + +#define BASE_TIMES (0) +#define FONT_TR (1) +#define FONT_TI (2) +#define FONT_TB (3) +#define FONT_TX (4) + +#define BASE_AVANTGARDE (FONT_TX) +#define FONT_AR (BASE_AVANTGARDE + FONT_TR) +#define FONT_AI (BASE_AVANTGARDE + FONT_TI) +#define FONT_AB (BASE_AVANTGARDE + FONT_TB) +#define FONT_AX (BASE_AVANTGARDE + FONT_TX) + +#define BASE_COURIER (FONT_AX) +#define FONT_CR (BASE_COURIER + FONT_TR) +#define FONT_CI (BASE_COURIER + FONT_TI) +#define FONT_CB (BASE_COURIER + FONT_TB) +#define FONT_CX (BASE_COURIER + FONT_TX) + +#define BASE_HELVETICA (FONT_CX) +#define FONT_HR (BASE_HELVETICA + FONT_TR) +#define FONT_HI (BASE_HELVETICA + FONT_TI) +#define FONT_HB (BASE_HELVETICA + FONT_TB) +#define FONT_HX (BASE_HELVETICA + FONT_TX) + +#define BASE_BOOKMAN (FONT_HX) +#define FONT_BR (BASE_BOOKMAN + FONT_TR) +#define FONT_BI (BASE_BOOKMAN + FONT_TI) +#define FONT_BB (BASE_BOOKMAN + FONT_TB) +#define FONT_BX (BASE_BOOKMAN + FONT_TX) + +#define BASE_NEWCENTURY (FONT_BX) +#define FONT_NR (BASE_NEWCENTURY + FONT_TR) +#define FONT_NI (BASE_NEWCENTURY + FONT_TI) +#define FONT_NB (BASE_NEWCENTURY + FONT_TB) +#define FONT_NX (BASE_NEWCENTURY + FONT_TX) + +#define BASE_PALATINO (FONT_NX) +#define FONT_PR (BASE_PALATINO + FONT_TR) +#define FONT_PI (BASE_PALATINO + FONT_TI) +#define FONT_PB (BASE_PALATINO + FONT_TB) +#define FONT_PX (BASE_PALATINO + FONT_TX) + +#ifdef EXTCHAR +/* extra fonts that contain the extended character set start here. + * They go in the same order as their corresponding standard ASCII fonts */ +#define EXT_FONT_OFFSET (FONT_PX - BASE_TIMES) + +#define FONT_XTR (FONT_TR + EXT_FONT_OFFSET) +#define FONT_XTI (FONT_TI + EXT_FONT_OFFSET) +#define FONT_XTB (FONT_TB + EXT_FONT_OFFSET) +#define FONT_XTX (FONT_TX + EXT_FONT_OFFSET) + +#define FONT_XAR (FONT_AR + EXT_FONT_OFFSET) +#define FONT_XAI (FONT_AI + EXT_FONT_OFFSET) +#define FONT_XAB (FONT_AB + EXT_FONT_OFFSET) +#define FONT_XAX (FONT_AX + EXT_FONT_OFFSET) + +#define FONT_XCR (FONT_CR + EXT_FONT_OFFSET) +#define FONT_XCI (FONT_CI + EXT_FONT_OFFSET) +#define FONT_XCB (FONT_CB + EXT_FONT_OFFSET) +#define FONT_XCX (FONT_CX + EXT_FONT_OFFSET) + +#define FONT_XHR (FONT_HR + EXT_FONT_OFFSET) +#define FONT_XHI (FONT_HI + EXT_FONT_OFFSET) +#define FONT_XHB (FONT_HB + EXT_FONT_OFFSET) +#define FONT_XHX (FONT_HX + EXT_FONT_OFFSET) + +#define FONT_XBR (FONT_BR + EXT_FONT_OFFSET) +#define FONT_XBI (FONT_BI + EXT_FONT_OFFSET) +#define FONT_XBB (FONT_BB + EXT_FONT_OFFSET) +#define FONT_XBX (FONT_BX + EXT_FONT_OFFSET) + +#define FONT_XNR (FONT_NR + EXT_FONT_OFFSET) +#define FONT_XNI (FONT_NI + EXT_FONT_OFFSET) +#define FONT_XNB (FONT_NB + EXT_FONT_OFFSET) +#define FONT_XNX (FONT_NX + EXT_FONT_OFFSET) + +#define FONT_XPR (FONT_PR + EXT_FONT_OFFSET) +#define FONT_XPI (FONT_PI + EXT_FONT_OFFSET) +#define FONT_XPB (FONT_PB + EXT_FONT_OFFSET) +#define FONT_XPX (FONT_PX + EXT_FONT_OFFSET) + +#define BASE_MISC (FONT_XPX) +#else +#define BASE_MISC (FONT_PX) +#endif +#define FONT_ZD (BASE_MISC + 1) +#define FONT_ZI (BASE_MISC + 2) +#define FONT_MUSIC (BASE_MISC + 3) +#define FONT_MUSIC2 (BASE_MISC + 4) +#define MAXFONTS (BASE_MISC + 5) + +/* number of music fonts */ +#define NUM_MFONTS (2) + +/* first printable character in a font */ +#define FIRST_CHAR (32) + +/* + * The following value plus FIRST_CHAR needs to be at least as large as + * one more than the largest value in either muschar.h or extchar.h + */ +#define CHARS_IN_FONT (96) + +/* + * Find array offset into height, width, and ascent tables. This is character + * code -FIRST_CHAR, to skip ASCII control characters. + */ +#define CHAR_INDEX(c) ((c) - FIRST_CHAR) + +/* + * Test if a font is a "music" font. + */ +#define IS_MUSIC_FONT(f) ((f) == FONT_MUSIC || (f) == FONT_MUSIC2) + +/* + * Special commands to use inside internal format of strings. + * All use high-bit==1 to indicate a command. + * Note that the low order bits of STR_MUS_CHAR* specify which music font it is. + */ +#define STR_MUS_CHAR 0x80 /* followed by 1-byte size and 1-byte \ + * music character code */ +#define STR_MUS_CHAR2 0x81 /* same rules as above */ +#define STR_FONT 0xe0 /* followed by 1-byte font number */ +#define STR_SIZE 0xe1 /* followed by 1-byte size */ +#define STR_PAGENUM 0xe2 /* followed by '%' */ +#define STR_NUMPAGES 0xe3 /* followed by '#' */ +#define STR_PRE 0xe4 /* pre-syl <--->, ignored in spacing */ +#define STR_U_PRE 0xe5 /* pre-syl <...>, used in spacing */ +#define STR_PRE_END 0xe6 /* end of pre-syllable <...> */ +#define STR_PST 0xe7 /* post-syl <...>, ignored in spacing */ +#define STR_U_PST 0xe8 /* post-syl <...>, used in spacing */ +#define STR_PST_END 0xe9 /* end of post-syllable <...> */ +/* + * Backspace is a bit strange. The amount to back up varies because of + * proportionally spaced fonts. So we save the distance in terms of the width + * in 250ths of an inch in the default size. The actual distance to back up is + * then that number times the ratio of the current actual size to the default + * size divided by 250. 250 was chosen because that means a range of 1-127 + * (to make sure it is non-zero and with high-bit of zero) + * will give a range of .004 to 0.508 inches, which should cover all + * characters we have today (the widest of which is currently just over 1/4"). + * This is done in floating point, so no reason to use a power of 2 like 256. + */ +#define STR_BACKSPACE 0xea /* followed by how much to back up */ + +#define BACKSP_FACTOR (250.0) + +/* string commands for boxed text */ +#define STR_BOX 0xeb +#define STR_BOX_END 0xec +#define IS_BOXED(string) (((string[2] & 0xff) == (STR_BOX & 0xff)) ? YES : NO) + +#define STR_VERTICAL 0xed /* vert move followed by 1-byte dist */ +#define STR_L_ALIGN 0xee /* align at left edge of next char */ +#define STR_C_ALIGN 0xef /* align at center of next char */ +#define STR_PILE 0xf0 /* toggle for piling, \: */ +#define STR_SLASH 0xf1 /* slash used by figbass, \/ */ + +/* string commands for circled text */ +#define STR_CIR 0xf2 +#define STR_CIR_END 0xf3 +#define IS_CIRCLED(string) (((string[2] & 0xff) == (STR_CIR & 0xff)) ? YES : NO) + +/* + * Define macros relating to vertical movement within a string. It is stored + * in points, offset by a bias so that the number will always be positive when + * stored in the byte after the STR_VERTICAL in a string. + */ +#define MINVERTICAL (-50) +#define MAXVERTICAL (50) +#define VERT_BIAS (1 - MINVERTICAL) +#define ENCODE_VERT(x) (x + VERT_BIAS) +#define DECODE_VERT(x) (x - VERT_BIAS) + +/* + * Macro to determine if a character in an internal-format string is a + * command character. + */ +#define IS_STR_COMMAND(c) ((c) & 0x80) + + +#define DFLT_SIZE (12) +#define SMALLSIZE ((int)(DFLT_SIZE * SM_FACTOR)) + +/* + * Define the default font size of a measure number. + */ +#define MNUM_SIZE (11) + +/* + * Define types of lines and curves. + */ +#define L_NORMAL (0) +#define L_MEDIUM (1) +#define L_WIDE (2) +#define L_WAVY (3) +#define L_DOTTED (4) +#define L_DASHED (5) + +/* + * Define the kinds of justification. + */ +#define J_LEFT (1) +#define J_RIGHT (2) +#define J_CENTER (3) +#define J_NONE (4) +#define J_RAGPARA (5) /* ragged-right paragraph */ +#define J_JUSTPARA (6) /* justified paragraph */ + +/* + * Define the ending styles (which staffs 1st, 2nd, etc. endings are to + * be drawn on). + */ +#define ENDING_TOP (0) /* only above top visible staff */ +#define ENDING_BARRED (1) /* above each group of staffs barred together*/ +#define ENDING_GROUPED (2) /* above each group of staffs grouped */ + /* together by braces or brackets */ + +/* + * Define types of rehearsal letters/numbers. + */ +#define REH_NONE (0) /* none at all */ +#define REH_STRING (1) /* user-supplied string */ +#define REH_NUM (2) /* consecutive numbers 1, 2, 3, . . . */ +#define REH_LET (3) /* consecutive letters A, B, C, . . . */ +#define REH_MNUM (4) /* use current measure number */ + +/* + * Define the style of (ways of drawing) rehearsal letters/numbers. + */ +#define RS_PLAIN (0) /* just the letter/number */ +#define RS_BOXED (1) /* enclosed in a box */ +#define RS_CIRCLED (2) /* enclosed in a circle */ + +/* + * Define the ways to print pedal markings. + */ +#define P_LINE (0) /* draw a line under where the pedal is down */ +#define P_PEDSTAR (1) /* print "Ped." and the start and "*" at end */ +#define P_ALTPEDSTAR (2) /* like P_PEDSTAR but only "Ped." when bounce*/ + +/* + * Define the side of a stem that a partial beam can be on. There is code in + * prntdata.c that depends on these values, -1 and 1. + */ +#define PB_LEFT (-1) +#define PB_RIGHT (1) + +/* + * Define types of intervals. There is code that depends on these being in + * this order, starting from 0, counting up (like in trnspose.c). + */ +#define DIMINISHED (0) +#define MINOR (1) +#define PERFECT (2) +#define MAJOR (3) +#define AUGMENTED (4) + +/* + * Define the input style. + */ +#define IS_VOICE_INPUT (0) /* voice-at-a-time (must be zero) */ +#define IS_CHORD_INPUT (1) /* chord-at-a-time */ + +/* + * Define the valid page sizes. The values must match the indexes of + * pagesztbl in gram.y. + */ +#define PS_LETTER (0) +#define PS_LEGAL (1) +#define PS_FLSA (2) +#define PS_HALFLETTER (3) +#define PS_A4 (4) +#define PS_A5 (5) +#define PS_A6 (6) + +/* Define page orientations */ +#define O_PORTRAIT (0) +#define O_LANDSCAPE (1) + +/* + * Define various constants ============================================= + */ + +/* the number of PostScript points in one inch */ +#define PPI (72.0) + +/* the size of a point in inches */ +#define POINT (1.0 / PPI) + +/* the distance between a note and the next higher note */ +#define STEPSIZE (3.0 * POINT) + +/* size of white space for surrounding things that should be padded thus */ +#define STDPAD (STEPSIZE / 3.0) + +/* (distance between tab staff lines) / (distance between normal staff lines)*/ +#define TABRATIO (1.735) + +/* scaling factor giving size of "sm" (small) music chars relative to normal */ +#define SM_FACTOR (0.65) + +/* scaling factor giving size of a grace fret number relative to normal */ +#define SMFRETSIZE ((int)(0.80 * DFLT_SIZE)) + +/* font character size information is stored in FONTFACTORs of an inch */ +#define FONTFACTOR (1000.0) + +/* widths of various types of lines, in points */ +#define W_NORMAL (0.7) +#define W_MEDIUM (1.5) +#define W_WIDE (3.0) + +/* vertical distance between two flags or two beams */ +#define FLAGSEP (1.6 * STEPSIZE) /* for normal notes */ +#define SMFLAGSEP (FLAGSEP * SM_FACTOR) /* for cue or grace notes */ + +/* minimum width to be given to a multirest */ +#define MINMULTIWIDTH (0.7) + +/* temporary width for a measure rest, serves as a marker */ +#define TEMPMRPTWIDTH (0.02) + +/* half the width of a restart bar */ +#define HALF_RESTART_WIDTH (12 * POINT) + +/* padding provided to force more room between groups for various reasons */ +#define TIESLURPAD (0.12) /* ties and slurs */ +#define SLASHPAD (0.06) /* slashes through stems */ +#define ALTPAD (0.12) /* alternation beams between groups */ +#define ROLLPADDING (12 * STDPAD) /* a roll to the left of a group */ + +/* padding to be put after a clef */ +#define CLEFPAD (2.0 * STDPAD) + +/* how high certain things are */ +#define TUPHEIGHT (10.0/3.0 * STEPSIZE) /* tuplet bracket */ +#define OCTHEIGHT (10.0/3.0 * STEPSIZE) /* octave bracket */ +#define ENDINGHEIGHT (13.0/3.0 * STEPSIZE) /* ending bracket */ +#define MULTIHEIGHT (12.0/3.0 * STEPSIZE) /* multirest number */ +#define MINWITHHEIGHT (2.2 * STEPSIZE) /* minimum "with" list item */ + +/* horizontal extent of a slash, in stepsizes */ +#define SLASHHORZ (5.0 / 3.0) + +/* + * The maximum number of notes there could ever be in a "hand" (the notes of a + * chord that occur on a given staff) is the number of unique notes that can + * exist, C0 through B9. + */ +#define MAXHAND ((MAXOCTAVE - MINOCTAVE + 1) * 7) + +/* the length in the X direction of a tabslur to or from nowhere */ +#define SLIDEXLEN (3.0 * STEPSIZE) + +/* define the default distance, in stepsizes, between the lines of a grid */ +#define WHEREUSED_GS (1.6) /* when printed by the music */ +#define ATEND_GS (2.0) /* when printed at the end of the song */ + +#define NO (0) +#define YES (1) + +/* the "used" field in input SSVs uses the following in addition to YES/NO */ +#define UNSET (2) + +#ifndef PI +#define PI (3.141592653589793) +#endif + +#define CMPERINCH (2.54) /* centimeters per inch */ + +/* + * Define miscellaneous macros ============================================= + */ + +/* number of elements in an array */ +#define NUMELEM(a) (sizeof(a) / sizeof((a)[0])) + +/* + * Define macros for allocating structures. + */ +#define MALLOC(structtype, new_p, numelem) { \ + if ((new_p = (struct structtype *)malloc((unsigned) \ + (((numelem) == 0 ? 1 : (numelem)) * \ + sizeof(struct structtype)))) == 0) \ + l_no_mem(__FILE__, __LINE__); \ +} +#define CALLOC(structtype, new_p, numelem) { \ + if ((new_p = (struct structtype *)calloc( \ + (numelem) == 0 ? 1 : (numelem), \ + (unsigned)sizeof(struct structtype))) == 0) \ + l_no_mem(__FILE__, __LINE__); \ +} +#ifndef __STDC__ +#define REALLOC(structtype, new_p, numelem) { \ + if ((new_p = (struct structtype *)realloc((char *)(new_p), \ + (unsigned)(((numelem) == 0 ? 1 : (numelem)) * \ + sizeof(struct structtype)))) == 0) \ + l_no_mem(__FILE__, __LINE__); \ +} +#else +#define REALLOC(structtype, new_p, numelem) { \ + if ((new_p = (struct structtype *)realloc((void *)(new_p), \ + (unsigned)(((numelem) == 0 ? 1 : (numelem)) * \ + sizeof(struct structtype)))) == 0) \ + l_no_mem(__FILE__, __LINE__); \ +} +#endif + +/* + * Define macros for allocating other arrays. + */ +#define MALLOCA(type, new_p, numelem) { \ + if ((new_p = (type *)malloc((unsigned) \ + (((numelem) == 0 ? 1 : (numelem)) * \ + sizeof(type)))) == 0) \ + l_no_mem(__FILE__, __LINE__); \ +} +#define CALLOCA(type, new_p, numelem) { \ + if ((new_p = (type *)calloc((numelem) == 0 ? 1 : (numelem), \ + (unsigned)sizeof(type))) == 0) \ + l_no_mem(__FILE__, __LINE__); \ +} +#ifndef __STDC__ +#define REALLOCA(type, new_p, numelem) { \ + if ((new_p = (type *)realloc((char *)(new_p), \ + (unsigned)(((numelem) == 0 ? 1 : (numelem)) * \ + sizeof(type)))) == 0) \ + l_no_mem(__FILE__, __LINE__); \ +} +#else +#define REALLOCA(type, new_p, numelem) { \ + if ((new_p = (type *)realloc((void *)(new_p), \ + (unsigned)(((numelem) == 0 ? 1 : (numelem)) * \ + sizeof(type)))) == 0) \ + l_no_mem(__FILE__, __LINE__); \ +} +#endif + +/* define macro for freeing memory */ +#ifdef __STDC__ +#define FREE(mem_p) free((void *)mem_p) +#else +#define FREE(mem_p) free((char *)mem_p) +#endif + +/* convert a RATIONAL to a float */ +#define RAT2FLOAT(rat) ( (float)(rat).n / (float)(rat).d ) + +/* the usual minimum and maximum macros */ +#define MAX(a, b) ( (a) > (b) ? (a) : (b) ) +#define MIN(a, b) ( (a) < (b) ? (a) : (b) ) + +/* absolute value of the difference of a and b */ +#define ABSDIFF(a, b) ( (a) > (b) ? (a) - (b) : (b) - (a) ) + +/* even and odd numbers (positive, zero, or negative; works on any compiler) */ +#define EVEN(a) (abs(a) % 2 == 0) +#define ODD(a) (abs(a) % 2 == 1) + +#define SQUARED(x) ((x) * (x)) +#define NEARESTQUARTER(x) ( (int)((x) * 4.0 + 0.5) / 4.0 ) + +/* half the height of a staff in stepsizes; use 1 for 1-line staffs */ +#define HALFSTAFF(s) ((svpath(s, STAFFLINES)->stafflines == 5) ? 4 : 1) + +/* given ptr to a group, return the NOTE struct for note nearest to the beam */ +#define BNOTE(gs_p) \ + (gs_p)->notelist[ (gs_p)->stemdir == UP ? 0 : (gs_p)->nnotes - 1 ] + +/* + * Define indices into GRPSYL.notelist for the first (FNNI) and last (LNNI) + * non-cross-staff-stemmed notes. Also define indices for the first (FCNI) + * and last (LCNI) cross-staff-stemmed notes. + * + * For FNNI and LNNI to work, there must be non-CSS notes, although even if + * not, it's still okay to have loops like + * for (n = FNNI(gs_p); n <= LNNI(gs_p); n++) + * and the NNN macro, which uses them, always works. + * + * LCNI and FCNI only work if there are CSS notes. + */ +#define FNNI(gs_p) ((gs_p)->stemto == CS_ABOVE ? \ + (gs_p)->stemto_idx + 1 : 0) +#define LNNI(gs_p) ((gs_p)->stemto == CS_BELOW ? \ + (gs_p)->stemto_idx - 1 : (gs_p)->nnotes - 1) +#define FCNI(gs_p) ((gs_p)->stemto == CS_ABOVE ? \ + 0 : (gs_p)->stemto_idx) +#define LCNI(gs_p) ((gs_p)->stemto == CS_BELOW ? \ + (gs_p)->nnotes - 1 : (gs_p)->stemto_idx) + +/* define the Number of Normal Notes (non-CSS notes) in a group */ +#define NNN(gs_p) (LNNI(gs_p) - FNNI(gs_p) + 1) + +/* test whether the note given via the index is CSS */ +#define IS_CSS_NOTE(gs_p, idx) ( \ + (((gs_p)->stemto == CS_ABOVE && idx <= (gs_p)->stemto_idx) || \ + ((gs_p)->stemto == CS_BELOW && idx >= (gs_p)->stemto_idx)) \ +) + +/* test whether any CSS notes that exist would be on stem side of the group */ +#define STEMSIDE_CSS(gs_p) \ + ((gs_p)->stemto == CS_ABOVE && (gs_p)->stemdir == UP || \ + (gs_p)->stemto == CS_BELOW && (gs_p)->stemdir == DOWN) + +/* + * Define CSS_STEPS to be an offset to be applied to "stepsup" when the note is + * on the other staff. It needs to be at twice as big as the interval between + * the highest and lowest notes so that stepsup plus or minus half of it will + * become a value that it could never be for a normal note (see doacc()), and + * it has to be an even number, because, for example, that matters for vertical + * dot placement. + */ +#define CSS_STEPS (MAXHAND * 2) + +/* is this FEED followed by a CLEFSIG (music), not a block? */ +#define IS_CLEFSIG_FEED(mll_p) ((mll_p)->str == S_FEED && \ + (mll_p)->next != 0 && (mll_p)->next->str == S_CLEFSIG) + +/* + * This macro is to be used as in this example: + * extern int func P((int parm1, float parm2)); + * The ANSI version will result in a function prototype. The other version + * will result in a function declaration (no parameters). + */ +#ifdef __STDC__ +#define P(parms) parms +#else +#define P(parms) () +#endif + +#endif diff --git a/mup/mup/errors.c b/mup/mup/errors.c new file mode 100644 index 0000000..d00f8b9 --- /dev/null +++ b/mup/mup/errors.c @@ -0,0 +1,604 @@ + +/* Copyright (c) 1995, 1997, 1999, 2000, 2001, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* various functions for printing error messages and exiting when + * things go wrong */ + +#include "globals.h" +#include "rational.h" + +#ifdef __STDC__ +#include +#else +#include +#endif + +#ifdef Mac_BBEdit +#include +#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(); +} + + +/* 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(); +} + + +/* 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); +} + + +/* 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"); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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 +} + + +/* 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++; +} + + + + +/* 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"); + } +} + + +/* 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; + } +} + + +/* 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; +} + + +/* Print the text of input line where error was found. */ + +void +print_offending_line(filename, lineno) + +char *filename; +int lineno; + +{ + /* We cache file info to save time when multiple errors */ + static FILE *f = 0; + static char *prev_filename = 0; + static int prev_lineno = 0; + int inp; /* a byte read from file */ + int skipcount; /* how many lines to skip past */ + + /* We try to reuse already opened file to save time, + * but need to open new file when necessary. */ + if (f == 0 || prev_filename != filename) { + /* close any previously open file */ + if (f != 0) { + (void) fclose(f); + } + /* Note that if Mup is reading from stdin, we will try to + * open a file entitled "stdin" here. That will almost + * certainly fail, but we can't easily get the line from + * stdin anyway, so user just won't get the context in that + * case. People who are having Mup read from stdin are probably + * savvy enough that this isn't a big problem. (We never used + * to print this context ever, and no one complained.) + * So the only weird case is if the user happens to have a + * file whose name is literally "stdin" but the actual stdin + * being read is some other file, in which case they'll get + * garbage. But anyone using stdin for a file name is probably + * smart enough to figure out the strange results in that case. + * In the case of include files found via $MUPPATH, + * filename will have already been expanded to a full path, + * so we don't have to do anything special here for them. + */ + if ((f = fopen(filename, "r")) == 0) { + return; + } + skipcount = lineno - 1; + prev_filename = filename; + } + else if (lineno > prev_lineno) { + /* We can continue where we left off in the file */ + skipcount = lineno - prev_lineno - 1; + } + else { + /* Earlier line in same file; easiest to just start over. + * This could happen, because sometimes we don't realize + * there is an error until a later line (E.g., only when + * getting to bar line we find inconsistency in the + * contents of the bar.) */ + rewind(f); + skipcount = lineno - 1; + } + + /* Skip to the line of interest and print it. */ + for (inp = 0; skipcount > 0; skipcount--) { + /* We read byte-by-byte so we don't need to guess + * how big a buffer to use to hold a line. + */ + while ((inp = getc(f)) != '\n' && inp != EOF) { + ; + } + if (inp == EOF) { + break; + } + } + if (inp != EOF) { + (void) fprintf(stderr, " "); + while ((inp = getc(f)) != '\n' && inp != EOF) { + putc(inp, stderr); + } + putc('\n', stderr); + } + prev_lineno = lineno; + /* Note that we leave the file open, to save time + * in case we need to read more from it + * due to additional errors from the same file. + */ +} diff --git a/mup/mup/extchar.h b/mup/mup/extchar.h new file mode 100644 index 0000000..3d2bdc2 --- /dev/null +++ b/mup/mup/extchar.h @@ -0,0 +1,106 @@ +/* Copyright (c) 1996, 2002, 2004 by Arkkra Enterprises */ +/* All rights reserved. */ + +#ifdef EXTCHAR + +/* Define the extended (non-ASCII) characters */ +/* Mapping between name and number is done via Ext_char_table[] */ + +#define C_exclamdown (32) +#define C_cent (33) +#define C_sterling (34) +#define C_yen (35) +#define C_quotedblleft (36) +#define C_guillemotleft (37) +#define C_guillemotright (38) +#define C_guilsinglleft (39) +#define C_guilsinglright (40) +#define C_dagger (41) +#define C_daggerdbl (42) +#define C_bullet (43) +#define C_quotedblbase (44) +#define C_quotedblright (45) +#define C_questiondown (46) +#define C_grave (47) +#define C_acute (48) +#define C_macron (49) +#define C_breve (50) +#define C_dotaccent (51) +#define C_dieresis (52) +#define C_ring (53) +#define C_cedilla (54) +#define C_hungarumlaut (55) +#define C_ogonek (56) +#define C_caron (57) +#define C_emdash (58) +#define C_AE (59) +#define C_ae (60) +#define C_ordfeminine (61) +#define C_ordmasculine (62) +#define C_Lslash (63) +#define C_lslash (64) +#define C_Oslash (65) +#define C_oslash (66) +#define C_OE (67) +#define C_oe (68) +#define C_dotlessi (69) +#define C_germandbls (70) +#define C_Aacute (71) +#define C_aacute (72) +#define C_Acircumflex (73) +#define C_acircumflex (74) +#define C_Adieresis (75) +#define C_adieresis (76) +#define C_Agrave (77) +#define C_agrave (78) +#define C_Aring (79) +#define C_aring (80) +#define C_Atilde (81) +#define C_atilde (82) +#define C_Ccedilla (83) +#define C_ccedilla (84) +#define C_Eacute (85) +#define C_eacute (86) +#define C_Ecircumflex (87) +#define C_ecircumflex (88) +#define C_Edieresis (89) +#define C_edieresis (90) +#define C_Egrave (91) +#define C_egrave (92) +#define C_Iacute (93) +#define C_iacute (94) +#define C_Icircumflex (95) +#define C_icircumflex (96) +#define C_Idieresis (97) +#define C_idieresis (98) +#define C_Igrave (99) +#define C_igrave (100) +#define C_Ntilde (101) +#define C_ntilde (102) +#define C_Oacute (103) +#define C_oacute (104) +#define C_Ocircumflex (105) +#define C_ocircumflex (106) +#define C_Odieresis (107) +#define C_odieresis (108) +#define C_Ograve (109) +#define C_ograve (110) +#define C_Otilde (111) +#define C_otilde (112) +#define C_Scaron (113) +#define C_scaron (114) +#define C_Uacute (115) +#define C_uacute (116) +#define C_Ucircumflex (117) +#define C_ucircumflex (118) +#define C_Udieresis (119) +#define C_udieresis (120) +#define C_Ugrave (121) +#define C_ugrave (122) +#define C_Ydieresis (123) +#define C_ydieresis (124) +#define C_Zcaron (125) +#define C_zcaron (126) +#define C_space (127) + +#endif diff --git a/mup/mup/extchtbl.c b/mup/mup/extchtbl.c new file mode 100644 index 0000000..2dfa2fe --- /dev/null +++ b/mup/mup/extchtbl.c @@ -0,0 +1,114 @@ +/* Copyright (c) 1996, 2002, 2004 by Arkkra Enterprises */ +/* All rights reserved */ + +/* Machine-generated mapping of music char names to code numbers */ + +#include "defines.h" +#include "structs.h" + +#ifdef EXTCHAR + +struct SPECCHAR Ext_char_table[CHARS_IN_FONT+1] = { + { "AE", C_AE }, + { "Aacute", C_Aacute }, + { "Acircumflex", C_Acircumflex }, + { "Adieresis", C_Adieresis }, + { "Agrave", C_Agrave }, + { "Aring", C_Aring }, + { "Atilde", C_Atilde }, + { "Ccedilla", C_Ccedilla }, + { "Eacute", C_Eacute }, + { "Ecircumflex", C_Ecircumflex }, + { "Edieresis", C_Edieresis }, + { "Egrave", C_Egrave }, + { "Iacute", C_Iacute }, + { "Icircumflex", C_Icircumflex }, + { "Idieresis", C_Idieresis }, + { "Igrave", C_Igrave }, + { "Lslash", C_Lslash }, + { "Ntilde", C_Ntilde }, + { "OE", C_OE }, + { "Oacute", C_Oacute }, + { "Ocircumflex", C_Ocircumflex }, + { "Odieresis", C_Odieresis }, + { "Ograve", C_Ograve }, + { "Oslash", C_Oslash }, + { "Otilde", C_Otilde }, + { "Scaron", C_Scaron }, + { "Uacute", C_Uacute }, + { "Ucircumflex", C_Ucircumflex }, + { "Udieresis", C_Udieresis }, + { "Ugrave", C_Ugrave }, + { "Ydieresis", C_Ydieresis }, + { "Zcaron", C_Zcaron }, + { "aacute", C_aacute }, + { "acircumflex", C_acircumflex }, + { "acute", C_acute }, + { "adieresis", C_adieresis }, + { "ae", C_ae }, + { "agrave", C_agrave }, + { "aring", C_aring }, + { "atilde", C_atilde }, + { "breve", C_breve }, + { "bullet", C_bullet }, + { "caron", C_caron }, + { "ccedilla", C_ccedilla }, + { "cedilla", C_cedilla }, + { "cent", C_cent }, + { "dagger", C_dagger }, + { "daggerdbl", C_daggerdbl }, + { "dieresis", C_dieresis }, + { "dotaccent", C_dotaccent }, + { "dotlessi", C_dotlessi }, + { "eacute", C_eacute }, + { "ecircumflex", C_ecircumflex }, + { "edieresis", C_edieresis }, + { "egrave", C_egrave }, + { "emdash", C_emdash }, + { "exclamdown", C_exclamdown }, + { "germandbls", C_germandbls }, + { "grave", C_grave }, + { "guillemotleft", C_guillemotleft }, + { "guillemotright", C_guillemotright }, + { "guilsinglleft", C_guilsinglleft }, + { "guilsinglright", C_guilsinglright }, + { "hungarumlaut", C_hungarumlaut }, + { "iacute", C_iacute }, + { "icircumflex", C_icircumflex }, + { "idieresis", C_idieresis }, + { "igrave", C_igrave }, + { "lslash", C_lslash }, + { "macron", C_macron }, + { "ntilde", C_ntilde }, + { "oacute", C_oacute }, + { "ocircumflex", C_ocircumflex }, + { "odieresis", C_odieresis }, + { "oe", C_oe }, + { "ogonek", C_ogonek }, + { "ograve", C_ograve }, + { "ordfeminine", C_ordfeminine }, + { "ordmasculine", C_ordmasculine }, + { "oslash", C_oslash }, + { "otilde", C_otilde }, + { "questiondown", C_questiondown }, + { "quotedblbase", C_quotedblbase }, + { "quotedblleft", C_quotedblleft }, + { "quotedblright", C_quotedblright }, + { "ring", C_ring }, + { "scaron", C_scaron }, + { "space", C_space }, + { "sterling", C_sterling }, + { "uacute", C_uacute }, + { "ucircumflex", C_ucircumflex }, + { "udieresis", C_udieresis }, + { "ugrave", C_ugrave }, + { "ydieresis", C_ydieresis }, + { "yen", C_yen }, + { "zcaron", C_zcaron }, + { (char *) 0, 0 } + +}; +#else +/* to avoid 'empty translation unit' warnings */ +static int dummy; +#endif diff --git a/mup/mup/font.c b/mup/mup/font.c new file mode 100644 index 0000000..c74aec4 --- /dev/null +++ b/mup/mup/font.c @@ -0,0 +1,426 @@ + +/* Copyright (c) 1999, 2000, 2002, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + +/* This file contains functions related to fonts, + * both user defined and native PostScript fonts. + */ + +#include +#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)); + + +/* 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); +} + + +/* 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)); +} + + +/* 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"); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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); +} + + +/* return the height for a font in inches for a given size */ + +double +fontheight(font, size) + +int font; +int size; + +{ + return( (double) Maxfontheight[font_index(font)] * + ((double) size / (double) DFLT_SIZE) ); +} + + + +/* return the ascent for a font in inches for a given size */ + +double +fontascent(font, size) + +int font; +int size; + +{ + return( (double) Maxfontascent[font_index(font)] * + ((double) size / (double) DFLT_SIZE) ); +} + + + +/* return the descent for a font in inches for a given size */ + +double +fontdescent(font, size) + +int font; +int size; + +{ + return( fontheight(font, size) - fontascent (font, size) ); +} diff --git a/mup/mup/fontdata.c b/mup/mup/fontdata.c new file mode 100644 index 0000000..343b082 --- /dev/null +++ b/mup/mup/fontdata.c @@ -0,0 +1,17883 @@ +/* Copyright (c) 1995, 1996, 1999 by Arkkra Enterprises */ +/* All rights reserved */ + +/* this file was generated from font information. + * It gives the width, height, and ascent for all the + * text characters in FONTFACTORs of an inch */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +struct FONTINFO Fontinfo[MAXFONTS] = { +{ + /* width table for font TR */ + { + 42, /* ' ' */ + 55, /* '!' */ + 68, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 139, /* '%' */ + 130, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 83, /* '*' */ + 94, /* '+' */ + 42, /* ',' */ + 55, /* '-' */ + 42, /* '.' */ + 46, /* '/' */ + 83, /* '0' */ + 83, /* '1' */ + 83, /* '2' */ + 83, /* '3' */ + 83, /* '4' */ + 83, /* '5' */ + 83, /* '6' */ + 83, /* '7' */ + 83, /* '8' */ + 83, /* '9' */ + 46, /* ':' */ + 46, /* ';' */ + 94, /* '<' */ + 94, /* '=' */ + 94, /* '>' */ + 74, /* '?' */ + 153, /* '@' */ + 120, /* 'A' */ + 111, /* 'B' */ + 111, /* 'C' */ + 120, /* 'D' */ + 102, /* 'E' */ + 93, /* 'F' */ + 120, /* 'G' */ + 120, /* 'H' */ + 55, /* 'I' */ + 65, /* 'J' */ + 120, /* 'K' */ + 102, /* 'L' */ + 148, /* 'M' */ + 120, /* 'N' */ + 120, /* 'O' */ + 93, /* 'P' */ + 120, /* 'Q' */ + 111, /* 'R' */ + 93, /* 'S' */ + 102, /* 'T' */ + 120, /* 'U' */ + 120, /* 'V' */ + 157, /* 'W' */ + 120, /* 'X' */ + 120, /* 'Y' */ + 102, /* 'Z' */ + 55, /* '[' */ + 46, /* '\' */ + 55, /* ']' */ + 78, /* '^' */ + 83, /* '_' */ + 55, /* '`' */ + 74, /* 'a' */ + 83, /* 'b' */ + 74, /* 'c' */ + 83, /* 'd' */ + 74, /* 'e' */ + 55, /* 'f' */ + 83, /* 'g' */ + 83, /* 'h' */ + 46, /* 'i' */ + 46, /* 'j' */ + 83, /* 'k' */ + 46, /* 'l' */ + 130, /* 'm' */ + 83, /* 'n' */ + 83, /* 'o' */ + 83, /* 'p' */ + 83, /* 'q' */ + 55, /* 'r' */ + 65, /* 's' */ + 46, /* 't' */ + 83, /* 'u' */ + 83, /* 'v' */ + 120, /* 'w' */ + 83, /* 'x' */ + 83, /* 'y' */ + 74, /* 'z' */ + 80, /* '{' */ + 33, /* '|' */ + 80, /* '}' */ + 90, /* '~' */ + }, + /* height table for font TR */ + { + 153, /* ' ' */ + 144, /* '!' */ + 142, /* '"' */ + 139, /* '#' */ + 163, /* '$' */ + 144, /* '%' */ + 144, /* '&' */ + 142, /* ''' */ + 170, /* '(' */ + 170, /* ')' */ + 142, /* '*' */ + 112, /* '+' */ + 69, /* ',' */ + 69, /* '-' */ + 47, /* '.' */ + 144, /* '/' */ + 144, /* '0' */ + 140, /* '1' */ + 142, /* '2' */ + 144, /* '3' */ + 142, /* '4' */ + 145, /* '5' */ + 144, /* '6' */ + 141, /* '7' */ + 144, /* '8' */ + 146, /* '9' */ + 108, /* ':' */ + 129, /* ';' */ + 115, /* '<' */ + 92, /* '=' */ + 115, /* '>' */ + 144, /* '?' */ + 144, /* '@' */ + 142, /* 'A' */ + 139, /* 'B' */ + 144, /* 'C' */ + 139, /* 'D' */ + 139, /* 'E' */ + 139, /* 'F' */ + 144, /* 'G' */ + 139, /* 'H' */ + 139, /* 'I' */ + 141, /* 'J' */ + 139, /* 'K' */ + 139, /* 'L' */ + 139, /* 'M' */ + 141, /* 'N' */ + 144, /* 'O' */ + 139, /* 'P' */ + 172, /* 'Q' */ + 139, /* 'R' */ + 144, /* 'S' */ + 139, /* 'T' */ + 141, /* 'U' */ + 141, /* 'V' */ + 141, /* 'W' */ + 139, /* 'X' */ + 139, /* 'Y' */ + 139, /* 'Z' */ + 164, /* '[' */ + 144, /* '\' */ + 164, /* ']' */ + 139, /* '^' */ + 38, /* '_' */ + 140, /* '`' */ + 108, /* 'a' */ + 144, /* 'b' */ + 108, /* 'c' */ + 144, /* 'd' */ + 108, /* 'e' */ + 142, /* 'f' */ + 141, /* 'g' */ + 142, /* 'h' */ + 142, /* 'i' */ + 178, /* 'j' */ + 142, /* 'k' */ + 142, /* 'l' */ + 106, /* 'm' */ + 106, /* 'n' */ + 108, /* 'o' */ + 141, /* 'p' */ + 141, /* 'q' */ + 106, /* 'r' */ + 108, /* 's' */ + 126, /* 't' */ + 104, /* 'u' */ + 104, /* 'v' */ + 104, /* 'w' */ + 102, /* 'x' */ + 138, /* 'y' */ + 102, /* 'z' */ + 172, /* '{' */ + 144, /* '|' */ + 172, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font TR */ + { + 108, /* ' ' */ + 128, /* '!' */ + 128, /* '"' */ + 125, /* '#' */ + 135, /* '$' */ + 128, /* '%' */ + 128, /* '&' */ + 128, /* ''' */ + 127, /* '(' */ + 127, /* ')' */ + 128, /* '*' */ + 98, /* '+' */ + 32, /* ',' */ + 55, /* '-' */ + 31, /* '.' */ + 128, /* '/' */ + 128, /* '0' */ + 127, /* '1' */ + 128, /* '2' */ + 128, /* '3' */ + 128, /* '4' */ + 129, /* '5' */ + 128, /* '6' */ + 125, /* '7' */ + 128, /* '8' */ + 128, /* '9' */ + 92, /* ':' */ + 92, /* ';' */ + 100, /* '<' */ + 78, /* '=' */ + 100, /* '>' */ + 128, /* '?' */ + 128, /* '@' */ + 128, /* 'A' */ + 125, /* 'B' */ + 128, /* 'C' */ + 125, /* 'D' */ + 125, /* 'E' */ + 125, /* 'F' */ + 128, /* 'G' */ + 125, /* 'H' */ + 125, /* 'I' */ + 125, /* 'J' */ + 125, /* 'K' */ + 125, /* 'L' */ + 125, /* 'M' */ + 125, /* 'N' */ + 128, /* 'O' */ + 125, /* 'P' */ + 128, /* 'Q' */ + 125, /* 'R' */ + 128, /* 'S' */ + 125, /* 'T' */ + 125, /* 'U' */ + 125, /* 'V' */ + 125, /* 'W' */ + 125, /* 'X' */ + 125, /* 'Y' */ + 125, /* 'Z' */ + 125, /* '[' */ + 128, /* '\' */ + 125, /* ']' */ + 125, /* '^' */ + 2, /* '_' */ + 127, /* '`' */ + 92, /* 'a' */ + 128, /* 'b' */ + 92, /* 'c' */ + 128, /* 'd' */ + 92, /* 'e' */ + 128, /* 'f' */ + 92, /* 'g' */ + 128, /* 'h' */ + 128, /* 'i' */ + 128, /* 'j' */ + 128, /* 'k' */ + 128, /* 'l' */ + 92, /* 'm' */ + 92, /* 'n' */ + 92, /* 'o' */ + 92, /* 'p' */ + 92, /* 'q' */ + 92, /* 'r' */ + 92, /* 's' */ + 110, /* 't' */ + 88, /* 'u' */ + 88, /* 'v' */ + 88, /* 'w' */ + 88, /* 'x' */ + 88, /* 'y' */ + 88, /* 'z' */ + 128, /* '{' */ + 128, /* '|' */ + 128, /* '}' */ + 68, /* '~' */ + }, + + "Times-Roman", + 0, + NO + }, { + /* width table for font TI */ + { + 42, /* ' ' */ + 55, /* '!' */ + 70, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 139, /* '%' */ + 130, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 83, /* '*' */ + 112, /* '+' */ + 42, /* ',' */ + 55, /* '-' */ + 42, /* '.' */ + 46, /* '/' */ + 83, /* '0' */ + 83, /* '1' */ + 83, /* '2' */ + 83, /* '3' */ + 83, /* '4' */ + 83, /* '5' */ + 83, /* '6' */ + 83, /* '7' */ + 83, /* '8' */ + 83, /* '9' */ + 55, /* ':' */ + 55, /* ';' */ + 112, /* '<' */ + 112, /* '=' */ + 112, /* '>' */ + 83, /* '?' */ + 153, /* '@' */ + 102, /* 'A' */ + 102, /* 'B' */ + 111, /* 'C' */ + 120, /* 'D' */ + 102, /* 'E' */ + 102, /* 'F' */ + 120, /* 'G' */ + 120, /* 'H' */ + 55, /* 'I' */ + 74, /* 'J' */ + 111, /* 'K' */ + 93, /* 'L' */ + 139, /* 'M' */ + 111, /* 'N' */ + 120, /* 'O' */ + 102, /* 'P' */ + 120, /* 'Q' */ + 102, /* 'R' */ + 83, /* 'S' */ + 93, /* 'T' */ + 120, /* 'U' */ + 102, /* 'V' */ + 139, /* 'W' */ + 102, /* 'X' */ + 93, /* 'Y' */ + 93, /* 'Z' */ + 65, /* '[' */ + 46, /* '\' */ + 65, /* ']' */ + 70, /* '^' */ + 83, /* '_' */ + 55, /* '`' */ + 83, /* 'a' */ + 83, /* 'b' */ + 74, /* 'c' */ + 83, /* 'd' */ + 74, /* 'e' */ + 46, /* 'f' */ + 83, /* 'g' */ + 83, /* 'h' */ + 46, /* 'i' */ + 46, /* 'j' */ + 74, /* 'k' */ + 46, /* 'l' */ + 120, /* 'm' */ + 83, /* 'n' */ + 83, /* 'o' */ + 83, /* 'p' */ + 83, /* 'q' */ + 65, /* 'r' */ + 65, /* 's' */ + 46, /* 't' */ + 83, /* 'u' */ + 74, /* 'v' */ + 111, /* 'w' */ + 74, /* 'x' */ + 74, /* 'y' */ + 65, /* 'z' */ + 67, /* '{' */ + 46, /* '|' */ + 67, /* '}' */ + 90, /* '~' */ + }, + /* height table for font TI */ + { + 153, /* ' ' */ + 141, /* '!' */ + 139, /* '"' */ + 140, /* '#' */ + 164, /* '$' */ + 143, /* '%' */ + 141, /* '&' */ + 139, /* ''' */ + 169, /* '(' */ + 169, /* ')' */ + 139, /* '*' */ + 112, /* '+' */ + 66, /* ',' */ + 69, /* '-' */ + 47, /* '.' */ + 141, /* '/' */ + 144, /* '0' */ + 140, /* '1' */ + 142, /* '2' */ + 141, /* '3' */ + 140, /* '4' */ + 141, /* '5' */ + 144, /* '6' */ + 141, /* '7' */ + 141, /* '8' */ + 142, /* '9' */ + 104, /* ':' */ + 124, /* ';' */ + 115, /* '<' */ + 92, /* '=' */ + 115, /* '>' */ + 141, /* '?' */ + 141, /* '@' */ + 139, /* 'A' */ + 136, /* 'B' */ + 141, /* 'C' */ + 136, /* 'D' */ + 136, /* 'E' */ + 136, /* 'F' */ + 141, /* 'G' */ + 136, /* 'H' */ + 136, /* 'I' */ + 138, /* 'J' */ + 136, /* 'K' */ + 136, /* 'L' */ + 136, /* 'M' */ + 138, /* 'N' */ + 141, /* 'O' */ + 136, /* 'P' */ + 168, /* 'Q' */ + 136, /* 'R' */ + 141, /* 'S' */ + 136, /* 'T' */ + 138, /* 'U' */ + 138, /* 'V' */ + 138, /* 'W' */ + 136, /* 'X' */ + 136, /* 'Y' */ + 136, /* 'Z' */ + 164, /* '[' */ + 141, /* '\' */ + 164, /* ']' */ + 139, /* '^' */ + 38, /* '_' */ + 139, /* '`' */ + 104, /* 'a' */ + 144, /* 'b' */ + 104, /* 'c' */ + 144, /* 'd' */ + 104, /* 'e' */ + 178, /* 'f' */ + 138, /* 'g' */ + 144, /* 'h' */ + 138, /* 'i' */ + 171, /* 'j' */ + 144, /* 'k' */ + 144, /* 'l' */ + 104, /* 'm' */ + 104, /* 'n' */ + 104, /* 'o' */ + 136, /* 'p' */ + 138, /* 'q' */ + 102, /* 'r' */ + 104, /* 's' */ + 121, /* 't' */ + 104, /* 'u' */ + 104, /* 'v' */ + 104, /* 'w' */ + 104, /* 'x' */ + 137, /* 'y' */ + 111, /* 'z' */ + 172, /* '{' */ + 141, /* '|' */ + 172, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font TI */ + { + 108, /* ' ' */ + 125, /* '!' */ + 125, /* '"' */ + 127, /* '#' */ + 136, /* '$' */ + 127, /* '%' */ + 125, /* '&' */ + 125, /* ''' */ + 125, /* '(' */ + 125, /* ')' */ + 125, /* '*' */ + 98, /* '+' */ + 31, /* ',' */ + 55, /* '-' */ + 31, /* '.' */ + 125, /* '/' */ + 128, /* '0' */ + 126, /* '1' */ + 128, /* '2' */ + 125, /* '3' */ + 127, /* '4' */ + 125, /* '5' */ + 128, /* '6' */ + 125, /* '7' */ + 125, /* '8' */ + 125, /* '9' */ + 88, /* ':' */ + 88, /* ';' */ + 100, /* '<' */ + 78, /* '=' */ + 100, /* '>' */ + 125, /* '?' */ + 125, /* '@' */ + 125, /* 'A' */ + 122, /* 'B' */ + 125, /* 'C' */ + 122, /* 'D' */ + 122, /* 'E' */ + 122, /* 'F' */ + 125, /* 'G' */ + 122, /* 'H' */ + 122, /* 'I' */ + 122, /* 'J' */ + 122, /* 'K' */ + 122, /* 'L' */ + 122, /* 'M' */ + 122, /* 'N' */ + 125, /* 'O' */ + 122, /* 'P' */ + 125, /* 'Q' */ + 122, /* 'R' */ + 125, /* 'S' */ + 122, /* 'T' */ + 122, /* 'U' */ + 122, /* 'V' */ + 122, /* 'W' */ + 122, /* 'X' */ + 122, /* 'Y' */ + 122, /* 'Z' */ + 125, /* '[' */ + 125, /* '\' */ + 125, /* ']' */ + 125, /* '^' */ + 2, /* '_' */ + 125, /* '`' */ + 88, /* 'a' */ + 128, /* 'b' */ + 88, /* 'c' */ + 128, /* 'd' */ + 88, /* 'e' */ + 128, /* 'f' */ + 88, /* 'g' */ + 128, /* 'h' */ + 122, /* 'i' */ + 122, /* 'j' */ + 128, /* 'k' */ + 128, /* 'l' */ + 88, /* 'm' */ + 88, /* 'n' */ + 88, /* 'o' */ + 88, /* 'p' */ + 88, /* 'q' */ + 88, /* 'r' */ + 88, /* 's' */ + 105, /* 't' */ + 87, /* 'u' */ + 88, /* 'v' */ + 88, /* 'w' */ + 88, /* 'x' */ + 88, /* 'y' */ + 85, /* 'z' */ + 128, /* '{' */ + 125, /* '|' */ + 128, /* '}' */ + 68, /* '~' */ + }, + + "Times-Italic", + 0, + YES + }, { + /* width table for font TB */ + { + 42, /* ' ' */ + 55, /* '!' */ + 92, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 167, /* '%' */ + 139, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 83, /* '*' */ + 95, /* '+' */ + 42, /* ',' */ + 55, /* '-' */ + 42, /* '.' */ + 46, /* '/' */ + 83, /* '0' */ + 83, /* '1' */ + 83, /* '2' */ + 83, /* '3' */ + 83, /* '4' */ + 83, /* '5' */ + 83, /* '6' */ + 83, /* '7' */ + 83, /* '8' */ + 83, /* '9' */ + 55, /* ':' */ + 55, /* ';' */ + 95, /* '<' */ + 95, /* '=' */ + 95, /* '>' */ + 83, /* '?' */ + 155, /* '@' */ + 120, /* 'A' */ + 111, /* 'B' */ + 120, /* 'C' */ + 120, /* 'D' */ + 111, /* 'E' */ + 102, /* 'F' */ + 130, /* 'G' */ + 130, /* 'H' */ + 65, /* 'I' */ + 83, /* 'J' */ + 130, /* 'K' */ + 111, /* 'L' */ + 157, /* 'M' */ + 120, /* 'N' */ + 130, /* 'O' */ + 102, /* 'P' */ + 130, /* 'Q' */ + 120, /* 'R' */ + 93, /* 'S' */ + 111, /* 'T' */ + 120, /* 'U' */ + 120, /* 'V' */ + 167, /* 'W' */ + 120, /* 'X' */ + 120, /* 'Y' */ + 111, /* 'Z' */ + 55, /* '[' */ + 46, /* '\' */ + 55, /* ']' */ + 97, /* '^' */ + 83, /* '_' */ + 55, /* '`' */ + 83, /* 'a' */ + 93, /* 'b' */ + 74, /* 'c' */ + 93, /* 'd' */ + 74, /* 'e' */ + 55, /* 'f' */ + 83, /* 'g' */ + 93, /* 'h' */ + 46, /* 'i' */ + 55, /* 'j' */ + 93, /* 'k' */ + 46, /* 'l' */ + 139, /* 'm' */ + 93, /* 'n' */ + 83, /* 'o' */ + 93, /* 'p' */ + 93, /* 'q' */ + 74, /* 'r' */ + 65, /* 's' */ + 55, /* 't' */ + 93, /* 'u' */ + 83, /* 'v' */ + 120, /* 'w' */ + 83, /* 'x' */ + 83, /* 'y' */ + 74, /* 'z' */ + 66, /* '{' */ + 37, /* '|' */ + 66, /* '}' */ + 87, /* '~' */ + }, + /* height table for font TB */ + { + 153, /* ' ' */ + 144, /* '!' */ + 142, /* '"' */ + 144, /* '#' */ + 169, /* '$' */ + 144, /* '%' */ + 144, /* '&' */ + 142, /* ''' */ + 171, /* '(' */ + 171, /* ')' */ + 142, /* '*' */ + 112, /* '+' */ + 86, /* ',' */ + 76, /* '-' */ + 56, /* '.' */ + 144, /* '/' */ + 144, /* '0' */ + 142, /* '1' */ + 142, /* '2' */ + 144, /* '3' */ + 142, /* '4' */ + 141, /* '5' */ + 145, /* '6' */ + 139, /* '7' */ + 144, /* '8' */ + 144, /* '9' */ + 111, /* ':' */ + 139, /* ';' */ + 116, /* '<' */ + 92, /* '=' */ + 116, /* '>' */ + 144, /* '?' */ + 144, /* '@' */ + 142, /* 'A' */ + 139, /* 'B' */ + 144, /* 'C' */ + 139, /* 'D' */ + 139, /* 'E' */ + 139, /* 'F' */ + 144, /* 'G' */ + 139, /* 'H' */ + 139, /* 'I' */ + 154, /* 'J' */ + 139, /* 'K' */ + 139, /* 'L' */ + 139, /* 'M' */ + 141, /* 'N' */ + 144, /* 'O' */ + 139, /* 'P' */ + 171, /* 'Q' */ + 139, /* 'R' */ + 144, /* 'S' */ + 139, /* 'T' */ + 141, /* 'U' */ + 141, /* 'V' */ + 141, /* 'W' */ + 139, /* 'X' */ + 139, /* 'Y' */ + 139, /* 'Z' */ + 164, /* '[' */ + 144, /* '\' */ + 164, /* ']' */ + 139, /* '^' */ + 38, /* '_' */ + 143, /* '`' */ + 111, /* 'a' */ + 141, /* 'b' */ + 111, /* 'c' */ + 141, /* 'd' */ + 111, /* 'e' */ + 142, /* 'f' */ + 144, /* 'g' */ + 139, /* 'h' */ + 142, /* 'i' */ + 178, /* 'j' */ + 139, /* 'k' */ + 139, /* 'l' */ + 109, /* 'm' */ + 109, /* 'n' */ + 111, /* 'o' */ + 144, /* 'p' */ + 144, /* 'q' */ + 109, /* 'r' */ + 111, /* 's' */ + 135, /* 't' */ + 108, /* 'u' */ + 108, /* 'v' */ + 108, /* 'w' */ + 106, /* 'x' */ + 141, /* 'y' */ + 106, /* 'z' */ + 174, /* '{' */ + 144, /* '|' */ + 174, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font TB */ + { + 108, /* ' ' */ + 128, /* '!' */ + 128, /* '"' */ + 131, /* '#' */ + 139, /* '$' */ + 128, /* '%' */ + 128, /* '&' */ + 128, /* ''' */ + 130, /* '(' */ + 130, /* ')' */ + 128, /* '*' */ + 98, /* '+' */ + 42, /* ',' */ + 62, /* '-' */ + 40, /* '.' */ + 128, /* '/' */ + 128, /* '0' */ + 128, /* '1' */ + 128, /* '2' */ + 128, /* '3' */ + 128, /* '4' */ + 125, /* '5' */ + 129, /* '6' */ + 125, /* '7' */ + 128, /* '8' */ + 128, /* '9' */ + 95, /* ':' */ + 95, /* ';' */ + 100, /* '<' */ + 78, /* '=' */ + 100, /* '>' */ + 128, /* '?' */ + 128, /* '@' */ + 128, /* 'A' */ + 125, /* 'B' */ + 128, /* 'C' */ + 125, /* 'D' */ + 125, /* 'E' */ + 125, /* 'F' */ + 128, /* 'G' */ + 125, /* 'H' */ + 125, /* 'I' */ + 125, /* 'J' */ + 125, /* 'K' */ + 125, /* 'L' */ + 125, /* 'M' */ + 125, /* 'N' */ + 128, /* 'O' */ + 125, /* 'P' */ + 128, /* 'Q' */ + 125, /* 'R' */ + 128, /* 'S' */ + 125, /* 'T' */ + 125, /* 'U' */ + 125, /* 'V' */ + 125, /* 'W' */ + 125, /* 'X' */ + 125, /* 'Y' */ + 125, /* 'Z' */ + 125, /* '[' */ + 128, /* '\' */ + 125, /* ']' */ + 125, /* '^' */ + 2, /* '_' */ + 129, /* '`' */ + 95, /* 'a' */ + 125, /* 'b' */ + 95, /* 'c' */ + 125, /* 'd' */ + 95, /* 'e' */ + 128, /* 'f' */ + 95, /* 'g' */ + 125, /* 'h' */ + 128, /* 'i' */ + 128, /* 'j' */ + 125, /* 'k' */ + 125, /* 'l' */ + 95, /* 'm' */ + 95, /* 'n' */ + 95, /* 'o' */ + 95, /* 'p' */ + 95, /* 'q' */ + 95, /* 'r' */ + 95, /* 's' */ + 119, /* 't' */ + 92, /* 'u' */ + 92, /* 'v' */ + 92, /* 'w' */ + 92, /* 'x' */ + 92, /* 'y' */ + 92, /* 'z' */ + 132, /* '{' */ + 128, /* '|' */ + 132, /* '}' */ + 68, /* '~' */ + }, + + "Times-Bold", + 0, + NO + }, { + /* width table for font TX */ + { + 42, /* ' ' */ + 65, /* '!' */ + 92, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 139, /* '%' */ + 130, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 83, /* '*' */ + 95, /* '+' */ + 42, /* ',' */ + 55, /* '-' */ + 42, /* '.' */ + 46, /* '/' */ + 83, /* '0' */ + 83, /* '1' */ + 83, /* '2' */ + 83, /* '3' */ + 83, /* '4' */ + 83, /* '5' */ + 83, /* '6' */ + 83, /* '7' */ + 83, /* '8' */ + 83, /* '9' */ + 55, /* ':' */ + 55, /* ';' */ + 95, /* '<' */ + 95, /* '=' */ + 95, /* '>' */ + 83, /* '?' */ + 139, /* '@' */ + 111, /* 'A' */ + 111, /* 'B' */ + 111, /* 'C' */ + 120, /* 'D' */ + 111, /* 'E' */ + 111, /* 'F' */ + 120, /* 'G' */ + 130, /* 'H' */ + 65, /* 'I' */ + 83, /* 'J' */ + 111, /* 'K' */ + 102, /* 'L' */ + 148, /* 'M' */ + 120, /* 'N' */ + 120, /* 'O' */ + 102, /* 'P' */ + 120, /* 'Q' */ + 111, /* 'R' */ + 93, /* 'S' */ + 102, /* 'T' */ + 120, /* 'U' */ + 111, /* 'V' */ + 148, /* 'W' */ + 111, /* 'X' */ + 102, /* 'Y' */ + 102, /* 'Z' */ + 55, /* '[' */ + 46, /* '\' */ + 55, /* ']' */ + 95, /* '^' */ + 83, /* '_' */ + 55, /* '`' */ + 83, /* 'a' */ + 83, /* 'b' */ + 74, /* 'c' */ + 83, /* 'd' */ + 74, /* 'e' */ + 55, /* 'f' */ + 83, /* 'g' */ + 93, /* 'h' */ + 46, /* 'i' */ + 46, /* 'j' */ + 83, /* 'k' */ + 46, /* 'l' */ + 130, /* 'm' */ + 93, /* 'n' */ + 83, /* 'o' */ + 83, /* 'p' */ + 83, /* 'q' */ + 65, /* 'r' */ + 65, /* 's' */ + 46, /* 't' */ + 93, /* 'u' */ + 74, /* 'v' */ + 111, /* 'w' */ + 83, /* 'x' */ + 74, /* 'y' */ + 65, /* 'z' */ + 58, /* '{' */ + 37, /* '|' */ + 58, /* '}' */ + 95, /* '~' */ + }, + /* height table for font TX */ + { + 153, /* ' ' */ + 144, /* '!' */ + 142, /* '"' */ + 144, /* '#' */ + 167, /* '$' */ + 145, /* '%' */ + 144, /* '&' */ + 142, /* ''' */ + 172, /* '(' */ + 172, /* ')' */ + 142, /* '*' */ + 112, /* '+' */ + 80, /* ',' */ + 76, /* '-' */ + 53, /* '.' */ + 144, /* '/' */ + 144, /* '0' */ + 142, /* '1' */ + 142, /* '2' */ + 144, /* '3' */ + 142, /* '4' */ + 141, /* '5' */ + 143, /* '6' */ + 139, /* '7' */ + 144, /* '8' */ + 144, /* '9' */ + 108, /* ':' */ + 136, /* ';' */ + 116, /* '<' */ + 92, /* '=' */ + 116, /* '>' */ + 144, /* '?' */ + 144, /* '@' */ + 142, /* 'A' */ + 139, /* 'B' */ + 144, /* 'C' */ + 139, /* 'D' */ + 139, /* 'E' */ + 139, /* 'F' */ + 144, /* 'G' */ + 139, /* 'H' */ + 139, /* 'I' */ + 154, /* 'J' */ + 139, /* 'K' */ + 139, /* 'L' */ + 141, /* 'M' */ + 141, /* 'N' */ + 144, /* 'O' */ + 139, /* 'P' */ + 178, /* 'Q' */ + 139, /* 'R' */ + 144, /* 'S' */ + 139, /* 'T' */ + 141, /* 'U' */ + 141, /* 'V' */ + 141, /* 'W' */ + 139, /* 'X' */ + 139, /* 'Y' */ + 139, /* 'Z' */ + 164, /* '[' */ + 144, /* '\' */ + 164, /* ']' */ + 139, /* '^' */ + 38, /* '_' */ + 142, /* '`' */ + 108, /* 'a' */ + 146, /* 'b' */ + 108, /* 'c' */ + 146, /* 'd' */ + 108, /* 'e' */ + 178, /* 'f' */ + 141, /* 'g' */ + 147, /* 'h' */ + 144, /* 'i' */ + 178, /* 'j' */ + 146, /* 'k' */ + 147, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 138, /* 'p' */ + 141, /* 'q' */ + 106, /* 'r' */ + 108, /* 's' */ + 129, /* 't' */ + 107, /* 'u' */ + 108, /* 'v' */ + 108, /* 'w' */ + 108, /* 'x' */ + 141, /* 'y' */ + 114, /* 'z' */ + 173, /* '{' */ + 144, /* '|' */ + 173, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font TX */ + { + 108, /* ' ' */ + 128, /* '!' */ + 128, /* '"' */ + 131, /* '#' */ + 136, /* '$' */ + 129, /* '%' */ + 128, /* '&' */ + 128, /* ''' */ + 128, /* '(' */ + 128, /* ')' */ + 128, /* '*' */ + 98, /* '+' */ + 36, /* ',' */ + 62, /* '-' */ + 36, /* '.' */ + 128, /* '/' */ + 128, /* '0' */ + 128, /* '1' */ + 128, /* '2' */ + 128, /* '3' */ + 128, /* '4' */ + 125, /* '5' */ + 127, /* '6' */ + 125, /* '7' */ + 128, /* '8' */ + 128, /* '9' */ + 92, /* ':' */ + 92, /* ';' */ + 100, /* '<' */ + 78, /* '=' */ + 100, /* '>' */ + 128, /* '?' */ + 128, /* '@' */ + 128, /* 'A' */ + 125, /* 'B' */ + 128, /* 'C' */ + 125, /* 'D' */ + 125, /* 'E' */ + 125, /* 'F' */ + 128, /* 'G' */ + 125, /* 'H' */ + 125, /* 'I' */ + 125, /* 'J' */ + 125, /* 'K' */ + 125, /* 'L' */ + 125, /* 'M' */ + 125, /* 'N' */ + 128, /* 'O' */ + 125, /* 'P' */ + 128, /* 'Q' */ + 125, /* 'R' */ + 128, /* 'S' */ + 125, /* 'T' */ + 125, /* 'U' */ + 125, /* 'V' */ + 125, /* 'W' */ + 125, /* 'X' */ + 125, /* 'Y' */ + 125, /* 'Z' */ + 125, /* '[' */ + 128, /* '\' */ + 125, /* ']' */ + 125, /* '^' */ + 2, /* '_' */ + 128, /* '`' */ + 92, /* 'a' */ + 130, /* 'b' */ + 92, /* 'c' */ + 130, /* 'd' */ + 92, /* 'e' */ + 128, /* 'f' */ + 92, /* 'g' */ + 130, /* 'h' */ + 128, /* 'i' */ + 128, /* 'j' */ + 130, /* 'k' */ + 130, /* 'l' */ + 92, /* 'm' */ + 92, /* 'n' */ + 92, /* 'o' */ + 92, /* 'p' */ + 92, /* 'q' */ + 92, /* 'r' */ + 92, /* 's' */ + 113, /* 't' */ + 91, /* 'u' */ + 92, /* 'v' */ + 92, /* 'w' */ + 92, /* 'x' */ + 92, /* 'y' */ + 88, /* 'z' */ + 128, /* '{' */ + 128, /* '|' */ + 128, /* '}' */ + 68, /* '~' */ + }, + + "Times-BoldItalic", + 0, + YES + }, { + /* width table for font AR */ + { + 46, /* ' ' */ + 49, /* '!' */ + 51, /* '"' */ + 92, /* '#' */ + 92, /* '$' */ + 129, /* '%' */ + 126, /* '&' */ + 58, /* ''' */ + 61, /* '(' */ + 61, /* ')' */ + 71, /* '*' */ + 101, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 73, /* '/' */ + 92, /* '0' */ + 92, /* '1' */ + 92, /* '2' */ + 92, /* '3' */ + 92, /* '4' */ + 92, /* '5' */ + 92, /* '6' */ + 92, /* '7' */ + 92, /* '8' */ + 92, /* '9' */ + 46, /* ':' */ + 46, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 98, /* '?' */ + 144, /* '@' */ + 123, /* 'A' */ + 96, /* 'B' */ + 135, /* 'C' */ + 124, /* 'D' */ + 89, /* 'E' */ + 81, /* 'F' */ + 145, /* 'G' */ + 114, /* 'H' */ + 38, /* 'I' */ + 80, /* 'J' */ + 98, /* 'K' */ + 77, /* 'L' */ + 153, /* 'M' */ + 123, /* 'N' */ + 145, /* 'O' */ + 99, /* 'P' */ + 145, /* 'Q' */ + 101, /* 'R' */ + 83, /* 'S' */ + 71, /* 'T' */ + 109, /* 'U' */ + 117, /* 'V' */ + 160, /* 'W' */ + 101, /* 'X' */ + 99, /* 'Y' */ + 80, /* 'Z' */ + 58, /* '[' */ + 101, /* '\' */ + 58, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 58, /* '`' */ + 114, /* 'a' */ + 114, /* 'b' */ + 108, /* 'c' */ + 114, /* 'd' */ + 108, /* 'e' */ + 52, /* 'f' */ + 112, /* 'g' */ + 102, /* 'h' */ + 33, /* 'i' */ + 34, /* 'j' */ + 84, /* 'k' */ + 33, /* 'l' */ + 156, /* 'm' */ + 102, /* 'n' */ + 109, /* 'o' */ + 114, /* 'p' */ + 114, /* 'q' */ + 50, /* 'r' */ + 65, /* 's' */ + 56, /* 't' */ + 101, /* 'u' */ + 92, /* 'v' */ + 138, /* 'w' */ + 80, /* 'x' */ + 89, /* 'y' */ + 71, /* 'z' */ + 58, /* '{' */ + 112, /* '|' */ + 58, /* '}' */ + 101, /* '~' */ + }, + /* height table for font AR */ + { + 153, /* ' ' */ + 152, /* '!' */ + 152, /* '"' */ + 152, /* '#' */ + 171, /* '$' */ + 158, /* '%' */ + 158, /* '&' */ + 152, /* ''' */ + 172, /* '(' */ + 172, /* ')' */ + 153, /* '*' */ + 122, /* '+' */ + 60, /* ',' */ + 76, /* '-' */ + 49, /* '.' */ + 174, /* '/' */ + 158, /* '0' */ + 152, /* '1' */ + 156, /* '2' */ + 158, /* '3' */ + 152, /* '4' */ + 154, /* '5' */ + 154, /* '6' */ + 152, /* '7' */ + 158, /* '8' */ + 156, /* '9' */ + 112, /* ':' */ + 123, /* ';' */ + 122, /* '<' */ + 99, /* '=' */ + 122, /* '>' */ + 156, /* '?' */ + 158, /* '@' */ + 152, /* 'A' */ + 152, /* 'B' */ + 158, /* 'C' */ + 152, /* 'D' */ + 152, /* 'E' */ + 152, /* 'F' */ + 158, /* 'G' */ + 152, /* 'H' */ + 152, /* 'I' */ + 154, /* 'J' */ + 152, /* 'K' */ + 152, /* 'L' */ + 152, /* 'M' */ + 152, /* 'N' */ + 158, /* 'O' */ + 152, /* 'P' */ + 158, /* 'Q' */ + 152, /* 'R' */ + 158, /* 'S' */ + 152, /* 'T' */ + 154, /* 'U' */ + 152, /* 'V' */ + 152, /* 'W' */ + 152, /* 'X' */ + 152, /* 'Y' */ + 152, /* 'Z' */ + 172, /* '[' */ + 152, /* '\' */ + 172, /* ']' */ + 152, /* '^' */ + 38, /* '_' */ + 152, /* '`' */ + 124, /* 'a' */ + 154, /* 'b' */ + 124, /* 'c' */ + 154, /* 'd' */ + 124, /* 'e' */ + 152, /* 'f' */ + 158, /* 'g' */ + 152, /* 'h' */ + 152, /* 'i' */ + 184, /* 'j' */ + 152, /* 'k' */ + 152, /* 'l' */ + 122, /* 'm' */ + 122, /* 'n' */ + 124, /* 'o' */ + 154, /* 'p' */ + 154, /* 'q' */ + 122, /* 'r' */ + 124, /* 's' */ + 152, /* 't' */ + 121, /* 'u' */ + 119, /* 'v' */ + 119, /* 'w' */ + 119, /* 'x' */ + 151, /* 'y' */ + 119, /* 'z' */ + 173, /* '{' */ + 152, /* '|' */ + 173, /* '}' */ + 93, /* '~' */ + }, + /* ascent table for font AR */ + { + 108, /* ' ' */ + 138, /* '!' */ + 138, /* '"' */ + 138, /* '#' */ + 148, /* '$' */ + 142, /* '%' */ + 142, /* '&' */ + 138, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 139, /* '*' */ + 108, /* '+' */ + 35, /* ',' */ + 62, /* '-' */ + 35, /* '.' */ + 138, /* '/' */ + 142, /* '0' */ + 138, /* '1' */ + 142, /* '2' */ + 142, /* '3' */ + 138, /* '4' */ + 138, /* '5' */ + 138, /* '6' */ + 138, /* '7' */ + 142, /* '8' */ + 142, /* '9' */ + 98, /* ':' */ + 98, /* ';' */ + 108, /* '<' */ + 85, /* '=' */ + 108, /* '>' */ + 142, /* '?' */ + 142, /* '@' */ + 138, /* 'A' */ + 138, /* 'B' */ + 142, /* 'C' */ + 138, /* 'D' */ + 138, /* 'E' */ + 138, /* 'F' */ + 142, /* 'G' */ + 138, /* 'H' */ + 138, /* 'I' */ + 138, /* 'J' */ + 138, /* 'K' */ + 138, /* 'L' */ + 138, /* 'M' */ + 138, /* 'N' */ + 142, /* 'O' */ + 138, /* 'P' */ + 142, /* 'Q' */ + 138, /* 'R' */ + 142, /* 'S' */ + 138, /* 'T' */ + 138, /* 'U' */ + 138, /* 'V' */ + 138, /* 'W' */ + 138, /* 'X' */ + 138, /* 'Y' */ + 138, /* 'Z' */ + 137, /* '[' */ + 138, /* '\' */ + 137, /* ']' */ + 138, /* '^' */ + 2, /* '_' */ + 138, /* '`' */ + 108, /* 'a' */ + 138, /* 'b' */ + 108, /* 'c' */ + 138, /* 'd' */ + 108, /* 'e' */ + 138, /* 'f' */ + 108, /* 'g' */ + 138, /* 'h' */ + 138, /* 'i' */ + 138, /* 'j' */ + 138, /* 'k' */ + 138, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 108, /* 'p' */ + 108, /* 'q' */ + 108, /* 'r' */ + 108, /* 's' */ + 138, /* 't' */ + 105, /* 'u' */ + 105, /* 'v' */ + 105, /* 'w' */ + 105, /* 'x' */ + 105, /* 'y' */ + 105, /* 'z' */ + 138, /* '{' */ + 138, /* '|' */ + 138, /* '}' */ + 79, /* '~' */ + }, + + "AvantGarde-Book", + 0, + NO + }, { + /* width table for font AI */ + { + 46, /* ' ' */ + 49, /* '!' */ + 51, /* '"' */ + 92, /* '#' */ + 92, /* '$' */ + 129, /* '%' */ + 126, /* '&' */ + 58, /* ''' */ + 61, /* '(' */ + 61, /* ')' */ + 71, /* '*' */ + 101, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 73, /* '/' */ + 92, /* '0' */ + 92, /* '1' */ + 92, /* '2' */ + 92, /* '3' */ + 92, /* '4' */ + 92, /* '5' */ + 92, /* '6' */ + 92, /* '7' */ + 92, /* '8' */ + 92, /* '9' */ + 46, /* ':' */ + 46, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 98, /* '?' */ + 144, /* '@' */ + 123, /* 'A' */ + 96, /* 'B' */ + 135, /* 'C' */ + 124, /* 'D' */ + 89, /* 'E' */ + 81, /* 'F' */ + 145, /* 'G' */ + 114, /* 'H' */ + 38, /* 'I' */ + 80, /* 'J' */ + 98, /* 'K' */ + 77, /* 'L' */ + 153, /* 'M' */ + 123, /* 'N' */ + 145, /* 'O' */ + 99, /* 'P' */ + 145, /* 'Q' */ + 101, /* 'R' */ + 83, /* 'S' */ + 71, /* 'T' */ + 109, /* 'U' */ + 117, /* 'V' */ + 160, /* 'W' */ + 101, /* 'X' */ + 99, /* 'Y' */ + 80, /* 'Z' */ + 58, /* '[' */ + 101, /* '\' */ + 58, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 58, /* '`' */ + 114, /* 'a' */ + 114, /* 'b' */ + 108, /* 'c' */ + 114, /* 'd' */ + 108, /* 'e' */ + 52, /* 'f' */ + 112, /* 'g' */ + 102, /* 'h' */ + 33, /* 'i' */ + 34, /* 'j' */ + 84, /* 'k' */ + 33, /* 'l' */ + 156, /* 'm' */ + 102, /* 'n' */ + 109, /* 'o' */ + 114, /* 'p' */ + 114, /* 'q' */ + 50, /* 'r' */ + 65, /* 's' */ + 56, /* 't' */ + 101, /* 'u' */ + 92, /* 'v' */ + 138, /* 'w' */ + 80, /* 'x' */ + 89, /* 'y' */ + 71, /* 'z' */ + 58, /* '{' */ + 112, /* '|' */ + 58, /* '}' */ + 101, /* '~' */ + }, + /* height table for font AI */ + { + 153, /* ' ' */ + 152, /* '!' */ + 152, /* '"' */ + 152, /* '#' */ + 171, /* '$' */ + 158, /* '%' */ + 158, /* '&' */ + 152, /* ''' */ + 172, /* '(' */ + 172, /* ')' */ + 153, /* '*' */ + 119, /* '+' */ + 60, /* ',' */ + 76, /* '-' */ + 49, /* '.' */ + 174, /* '/' */ + 158, /* '0' */ + 152, /* '1' */ + 156, /* '2' */ + 158, /* '3' */ + 152, /* '4' */ + 154, /* '5' */ + 154, /* '6' */ + 152, /* '7' */ + 158, /* '8' */ + 156, /* '9' */ + 112, /* ':' */ + 123, /* ';' */ + 122, /* '<' */ + 99, /* '=' */ + 122, /* '>' */ + 156, /* '?' */ + 158, /* '@' */ + 152, /* 'A' */ + 152, /* 'B' */ + 158, /* 'C' */ + 152, /* 'D' */ + 152, /* 'E' */ + 152, /* 'F' */ + 158, /* 'G' */ + 152, /* 'H' */ + 152, /* 'I' */ + 154, /* 'J' */ + 152, /* 'K' */ + 152, /* 'L' */ + 152, /* 'M' */ + 152, /* 'N' */ + 158, /* 'O' */ + 152, /* 'P' */ + 158, /* 'Q' */ + 152, /* 'R' */ + 158, /* 'S' */ + 152, /* 'T' */ + 154, /* 'U' */ + 152, /* 'V' */ + 152, /* 'W' */ + 152, /* 'X' */ + 152, /* 'Y' */ + 152, /* 'Z' */ + 172, /* '[' */ + 152, /* '\' */ + 172, /* ']' */ + 152, /* '^' */ + 38, /* '_' */ + 152, /* '`' */ + 124, /* 'a' */ + 154, /* 'b' */ + 124, /* 'c' */ + 154, /* 'd' */ + 124, /* 'e' */ + 152, /* 'f' */ + 158, /* 'g' */ + 152, /* 'h' */ + 152, /* 'i' */ + 184, /* 'j' */ + 152, /* 'k' */ + 152, /* 'l' */ + 122, /* 'm' */ + 122, /* 'n' */ + 124, /* 'o' */ + 154, /* 'p' */ + 154, /* 'q' */ + 122, /* 'r' */ + 124, /* 's' */ + 152, /* 't' */ + 121, /* 'u' */ + 119, /* 'v' */ + 119, /* 'w' */ + 119, /* 'x' */ + 151, /* 'y' */ + 119, /* 'z' */ + 173, /* '{' */ + 152, /* '|' */ + 173, /* '}' */ + 93, /* '~' */ + }, + /* ascent table for font AI */ + { + 108, /* ' ' */ + 138, /* '!' */ + 138, /* '"' */ + 138, /* '#' */ + 148, /* '$' */ + 142, /* '%' */ + 142, /* '&' */ + 138, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 139, /* '*' */ + 105, /* '+' */ + 35, /* ',' */ + 62, /* '-' */ + 35, /* '.' */ + 138, /* '/' */ + 142, /* '0' */ + 138, /* '1' */ + 142, /* '2' */ + 142, /* '3' */ + 138, /* '4' */ + 138, /* '5' */ + 138, /* '6' */ + 138, /* '7' */ + 142, /* '8' */ + 142, /* '9' */ + 98, /* ':' */ + 98, /* ';' */ + 108, /* '<' */ + 85, /* '=' */ + 108, /* '>' */ + 142, /* '?' */ + 142, /* '@' */ + 138, /* 'A' */ + 138, /* 'B' */ + 142, /* 'C' */ + 138, /* 'D' */ + 138, /* 'E' */ + 138, /* 'F' */ + 142, /* 'G' */ + 138, /* 'H' */ + 138, /* 'I' */ + 138, /* 'J' */ + 138, /* 'K' */ + 138, /* 'L' */ + 138, /* 'M' */ + 138, /* 'N' */ + 142, /* 'O' */ + 138, /* 'P' */ + 142, /* 'Q' */ + 138, /* 'R' */ + 142, /* 'S' */ + 138, /* 'T' */ + 138, /* 'U' */ + 138, /* 'V' */ + 138, /* 'W' */ + 138, /* 'X' */ + 138, /* 'Y' */ + 138, /* 'Z' */ + 137, /* '[' */ + 138, /* '\' */ + 137, /* ']' */ + 138, /* '^' */ + 2, /* '_' */ + 138, /* '`' */ + 108, /* 'a' */ + 138, /* 'b' */ + 108, /* 'c' */ + 138, /* 'd' */ + 108, /* 'e' */ + 138, /* 'f' */ + 108, /* 'g' */ + 138, /* 'h' */ + 138, /* 'i' */ + 138, /* 'j' */ + 138, /* 'k' */ + 138, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 108, /* 'p' */ + 108, /* 'q' */ + 108, /* 'r' */ + 108, /* 's' */ + 138, /* 't' */ + 105, /* 'u' */ + 105, /* 'v' */ + 105, /* 'w' */ + 105, /* 'x' */ + 105, /* 'y' */ + 105, /* 'z' */ + 138, /* '{' */ + 138, /* '|' */ + 138, /* '}' */ + 79, /* '~' */ + }, + + "AvantGarde-BookOblique", + 0, + YES + }, { + /* width table for font AB */ + { + 47, /* ' ' */ + 47, /* '!' */ + 60, /* '"' */ + 93, /* '#' */ + 93, /* '$' */ + 143, /* '%' */ + 113, /* '&' */ + 47, /* ''' */ + 63, /* '(' */ + 63, /* ')' */ + 73, /* '*' */ + 100, /* '+' */ + 47, /* ',' */ + 70, /* '-' */ + 47, /* '.' */ + 77, /* '/' */ + 93, /* '0' */ + 93, /* '1' */ + 93, /* '2' */ + 93, /* '3' */ + 93, /* '4' */ + 93, /* '5' */ + 93, /* '6' */ + 93, /* '7' */ + 93, /* '8' */ + 93, /* '9' */ + 47, /* ':' */ + 47, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 93, /* '?' */ + 123, /* '@' */ + 123, /* 'A' */ + 97, /* 'B' */ + 130, /* 'C' */ + 117, /* 'D' */ + 87, /* 'E' */ + 80, /* 'F' */ + 140, /* 'G' */ + 113, /* 'H' */ + 47, /* 'I' */ + 80, /* 'J' */ + 103, /* 'K' */ + 73, /* 'L' */ + 150, /* 'M' */ + 123, /* 'N' */ + 140, /* 'O' */ + 93, /* 'P' */ + 140, /* 'Q' */ + 97, /* 'R' */ + 87, /* 'S' */ + 70, /* 'T' */ + 107, /* 'U' */ + 117, /* 'V' */ + 150, /* 'W' */ + 113, /* 'X' */ + 103, /* 'Y' */ + 83, /* 'Z' */ + 53, /* '[' */ + 107, /* '\' */ + 53, /* ']' */ + 100, /* '^' */ + 83, /* '_' */ + 47, /* '`' */ + 110, /* 'a' */ + 110, /* 'b' */ + 107, /* 'c' */ + 110, /* 'd' */ + 107, /* 'e' */ + 47, /* 'f' */ + 110, /* 'g' */ + 100, /* 'h' */ + 40, /* 'i' */ + 43, /* 'j' */ + 97, /* 'k' */ + 40, /* 'l' */ + 157, /* 'm' */ + 100, /* 'n' */ + 107, /* 'o' */ + 110, /* 'p' */ + 110, /* 'q' */ + 53, /* 'r' */ + 73, /* 's' */ + 50, /* 't' */ + 100, /* 'u' */ + 93, /* 'v' */ + 133, /* 'w' */ + 93, /* 'x' */ + 97, /* 'y' */ + 77, /* 'z' */ + 57, /* '{' */ + 100, /* '|' */ + 57, /* '}' */ + 100, /* '~' */ + }, + /* height table for font AB */ + { + 153, /* ' ' */ + 152, /* '!' */ + 152, /* '"' */ + 152, /* '#' */ + 181, /* '$' */ + 158, /* '%' */ + 158, /* '&' */ + 152, /* ''' */ + 174, /* '(' */ + 174, /* ')' */ + 151, /* '*' */ + 132, /* '+' */ + 72, /* ',' */ + 86, /* '-' */ + 49, /* '.' */ + 174, /* '/' */ + 158, /* '0' */ + 152, /* '1' */ + 156, /* '2' */ + 158, /* '3' */ + 152, /* '4' */ + 154, /* '5' */ + 154, /* '6' */ + 152, /* '7' */ + 158, /* '8' */ + 156, /* '9' */ + 112, /* ':' */ + 136, /* ';' */ + 125, /* '<' */ + 116, /* '=' */ + 125, /* '>' */ + 156, /* '?' */ + 158, /* '@' */ + 152, /* 'A' */ + 152, /* 'B' */ + 158, /* 'C' */ + 152, /* 'D' */ + 152, /* 'E' */ + 152, /* 'F' */ + 158, /* 'G' */ + 152, /* 'H' */ + 152, /* 'I' */ + 154, /* 'J' */ + 152, /* 'K' */ + 152, /* 'L' */ + 152, /* 'M' */ + 152, /* 'N' */ + 158, /* 'O' */ + 152, /* 'P' */ + 158, /* 'Q' */ + 152, /* 'R' */ + 158, /* 'S' */ + 152, /* 'T' */ + 154, /* 'U' */ + 152, /* 'V' */ + 152, /* 'W' */ + 152, /* 'X' */ + 152, /* 'Y' */ + 152, /* 'Z' */ + 174, /* '[' */ + 152, /* '\' */ + 174, /* ']' */ + 152, /* '^' */ + 44, /* '_' */ + 152, /* '`' */ + 124, /* 'a' */ + 154, /* 'b' */ + 124, /* 'c' */ + 154, /* 'd' */ + 124, /* 'e' */ + 152, /* 'f' */ + 158, /* 'g' */ + 152, /* 'h' */ + 152, /* 'i' */ + 184, /* 'j' */ + 152, /* 'k' */ + 152, /* 'l' */ + 122, /* 'm' */ + 122, /* 'n' */ + 124, /* 'o' */ + 154, /* 'p' */ + 154, /* 'q' */ + 122, /* 'r' */ + 124, /* 's' */ + 152, /* 't' */ + 121, /* 'u' */ + 119, /* 'v' */ + 119, /* 'w' */ + 119, /* 'x' */ + 151, /* 'y' */ + 119, /* 'z' */ + 174, /* '{' */ + 152, /* '|' */ + 174, /* '}' */ + 98, /* '~' */ + }, + /* ascent table for font AB */ + { + 108, /* ' ' */ + 138, /* '!' */ + 138, /* '"' */ + 138, /* '#' */ + 155, /* '$' */ + 142, /* '%' */ + 142, /* '&' */ + 138, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 137, /* '*' */ + 118, /* '+' */ + 35, /* ',' */ + 72, /* '-' */ + 35, /* '.' */ + 138, /* '/' */ + 142, /* '0' */ + 138, /* '1' */ + 142, /* '2' */ + 142, /* '3' */ + 138, /* '4' */ + 138, /* '5' */ + 138, /* '6' */ + 138, /* '7' */ + 142, /* '8' */ + 142, /* '9' */ + 98, /* ':' */ + 98, /* ';' */ + 111, /* '<' */ + 102, /* '=' */ + 111, /* '>' */ + 142, /* '?' */ + 142, /* '@' */ + 138, /* 'A' */ + 138, /* 'B' */ + 142, /* 'C' */ + 138, /* 'D' */ + 138, /* 'E' */ + 138, /* 'F' */ + 142, /* 'G' */ + 138, /* 'H' */ + 138, /* 'I' */ + 138, /* 'J' */ + 138, /* 'K' */ + 138, /* 'L' */ + 138, /* 'M' */ + 138, /* 'N' */ + 142, /* 'O' */ + 138, /* 'P' */ + 142, /* 'Q' */ + 138, /* 'R' */ + 142, /* 'S' */ + 138, /* 'T' */ + 138, /* 'U' */ + 138, /* 'V' */ + 138, /* 'W' */ + 138, /* 'X' */ + 138, /* 'Y' */ + 138, /* 'Z' */ + 137, /* '[' */ + 138, /* '\' */ + 137, /* ']' */ + 138, /* '^' */ + 8, /* '_' */ + 138, /* '`' */ + 108, /* 'a' */ + 138, /* 'b' */ + 108, /* 'c' */ + 138, /* 'd' */ + 108, /* 'e' */ + 138, /* 'f' */ + 108, /* 'g' */ + 138, /* 'h' */ + 138, /* 'i' */ + 138, /* 'j' */ + 138, /* 'k' */ + 138, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 108, /* 'p' */ + 108, /* 'q' */ + 108, /* 'r' */ + 108, /* 's' */ + 138, /* 't' */ + 105, /* 'u' */ + 105, /* 'v' */ + 105, /* 'w' */ + 105, /* 'x' */ + 105, /* 'y' */ + 105, /* 'z' */ + 138, /* '{' */ + 138, /* '|' */ + 138, /* '}' */ + 84, /* '~' */ + }, + + "AvantGarde-Demi", + 0, + NO + }, { + /* width table for font AX */ + { + 47, /* ' ' */ + 47, /* '!' */ + 60, /* '"' */ + 93, /* '#' */ + 93, /* '$' */ + 143, /* '%' */ + 113, /* '&' */ + 47, /* ''' */ + 63, /* '(' */ + 63, /* ')' */ + 73, /* '*' */ + 100, /* '+' */ + 47, /* ',' */ + 70, /* '-' */ + 47, /* '.' */ + 77, /* '/' */ + 93, /* '0' */ + 93, /* '1' */ + 93, /* '2' */ + 93, /* '3' */ + 93, /* '4' */ + 93, /* '5' */ + 93, /* '6' */ + 93, /* '7' */ + 93, /* '8' */ + 93, /* '9' */ + 47, /* ':' */ + 47, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 93, /* '?' */ + 123, /* '@' */ + 123, /* 'A' */ + 97, /* 'B' */ + 130, /* 'C' */ + 117, /* 'D' */ + 87, /* 'E' */ + 80, /* 'F' */ + 140, /* 'G' */ + 113, /* 'H' */ + 47, /* 'I' */ + 80, /* 'J' */ + 103, /* 'K' */ + 73, /* 'L' */ + 150, /* 'M' */ + 123, /* 'N' */ + 140, /* 'O' */ + 93, /* 'P' */ + 140, /* 'Q' */ + 97, /* 'R' */ + 87, /* 'S' */ + 70, /* 'T' */ + 107, /* 'U' */ + 117, /* 'V' */ + 150, /* 'W' */ + 113, /* 'X' */ + 103, /* 'Y' */ + 83, /* 'Z' */ + 53, /* '[' */ + 107, /* '\' */ + 53, /* ']' */ + 100, /* '^' */ + 83, /* '_' */ + 47, /* '`' */ + 110, /* 'a' */ + 110, /* 'b' */ + 107, /* 'c' */ + 110, /* 'd' */ + 107, /* 'e' */ + 47, /* 'f' */ + 110, /* 'g' */ + 100, /* 'h' */ + 40, /* 'i' */ + 43, /* 'j' */ + 97, /* 'k' */ + 40, /* 'l' */ + 157, /* 'm' */ + 100, /* 'n' */ + 107, /* 'o' */ + 110, /* 'p' */ + 110, /* 'q' */ + 53, /* 'r' */ + 73, /* 's' */ + 50, /* 't' */ + 100, /* 'u' */ + 93, /* 'v' */ + 133, /* 'w' */ + 93, /* 'x' */ + 97, /* 'y' */ + 77, /* 'z' */ + 57, /* '{' */ + 100, /* '|' */ + 57, /* '}' */ + 100, /* '~' */ + }, + /* height table for font AX */ + { + 153, /* ' ' */ + 152, /* '!' */ + 152, /* '"' */ + 152, /* '#' */ + 181, /* '$' */ + 158, /* '%' */ + 158, /* '&' */ + 152, /* ''' */ + 174, /* '(' */ + 174, /* ')' */ + 151, /* '*' */ + 129, /* '+' */ + 72, /* ',' */ + 86, /* '-' */ + 49, /* '.' */ + 174, /* '/' */ + 158, /* '0' */ + 152, /* '1' */ + 156, /* '2' */ + 158, /* '3' */ + 152, /* '4' */ + 154, /* '5' */ + 154, /* '6' */ + 152, /* '7' */ + 158, /* '8' */ + 156, /* '9' */ + 112, /* ':' */ + 136, /* ';' */ + 125, /* '<' */ + 116, /* '=' */ + 125, /* '>' */ + 156, /* '?' */ + 158, /* '@' */ + 152, /* 'A' */ + 152, /* 'B' */ + 158, /* 'C' */ + 152, /* 'D' */ + 152, /* 'E' */ + 152, /* 'F' */ + 158, /* 'G' */ + 152, /* 'H' */ + 152, /* 'I' */ + 154, /* 'J' */ + 152, /* 'K' */ + 152, /* 'L' */ + 152, /* 'M' */ + 152, /* 'N' */ + 158, /* 'O' */ + 152, /* 'P' */ + 158, /* 'Q' */ + 152, /* 'R' */ + 158, /* 'S' */ + 152, /* 'T' */ + 154, /* 'U' */ + 152, /* 'V' */ + 152, /* 'W' */ + 152, /* 'X' */ + 152, /* 'Y' */ + 152, /* 'Z' */ + 174, /* '[' */ + 152, /* '\' */ + 174, /* ']' */ + 156, /* '^' */ + 44, /* '_' */ + 152, /* '`' */ + 124, /* 'a' */ + 154, /* 'b' */ + 124, /* 'c' */ + 154, /* 'd' */ + 124, /* 'e' */ + 152, /* 'f' */ + 158, /* 'g' */ + 152, /* 'h' */ + 152, /* 'i' */ + 184, /* 'j' */ + 152, /* 'k' */ + 152, /* 'l' */ + 122, /* 'm' */ + 122, /* 'n' */ + 124, /* 'o' */ + 154, /* 'p' */ + 154, /* 'q' */ + 122, /* 'r' */ + 124, /* 's' */ + 152, /* 't' */ + 121, /* 'u' */ + 119, /* 'v' */ + 119, /* 'w' */ + 119, /* 'x' */ + 151, /* 'y' */ + 119, /* 'z' */ + 174, /* '{' */ + 152, /* '|' */ + 174, /* '}' */ + 98, /* '~' */ + }, + /* ascent table for font AX */ + { + 108, /* ' ' */ + 138, /* '!' */ + 138, /* '"' */ + 138, /* '#' */ + 155, /* '$' */ + 142, /* '%' */ + 142, /* '&' */ + 138, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 137, /* '*' */ + 115, /* '+' */ + 35, /* ',' */ + 72, /* '-' */ + 35, /* '.' */ + 138, /* '/' */ + 142, /* '0' */ + 138, /* '1' */ + 142, /* '2' */ + 142, /* '3' */ + 138, /* '4' */ + 138, /* '5' */ + 138, /* '6' */ + 138, /* '7' */ + 142, /* '8' */ + 142, /* '9' */ + 98, /* ':' */ + 98, /* ';' */ + 111, /* '<' */ + 102, /* '=' */ + 111, /* '>' */ + 142, /* '?' */ + 142, /* '@' */ + 138, /* 'A' */ + 138, /* 'B' */ + 142, /* 'C' */ + 138, /* 'D' */ + 138, /* 'E' */ + 138, /* 'F' */ + 142, /* 'G' */ + 138, /* 'H' */ + 138, /* 'I' */ + 138, /* 'J' */ + 138, /* 'K' */ + 138, /* 'L' */ + 138, /* 'M' */ + 138, /* 'N' */ + 142, /* 'O' */ + 138, /* 'P' */ + 142, /* 'Q' */ + 138, /* 'R' */ + 142, /* 'S' */ + 138, /* 'T' */ + 138, /* 'U' */ + 138, /* 'V' */ + 138, /* 'W' */ + 138, /* 'X' */ + 138, /* 'Y' */ + 138, /* 'Z' */ + 137, /* '[' */ + 138, /* '\' */ + 137, /* ']' */ + 142, /* '^' */ + 8, /* '_' */ + 138, /* '`' */ + 108, /* 'a' */ + 138, /* 'b' */ + 108, /* 'c' */ + 138, /* 'd' */ + 108, /* 'e' */ + 138, /* 'f' */ + 108, /* 'g' */ + 138, /* 'h' */ + 138, /* 'i' */ + 138, /* 'j' */ + 138, /* 'k' */ + 138, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 108, /* 'p' */ + 108, /* 'q' */ + 108, /* 'r' */ + 108, /* 's' */ + 138, /* 't' */ + 105, /* 'u' */ + 105, /* 'v' */ + 105, /* 'w' */ + 105, /* 'x' */ + 105, /* 'y' */ + 105, /* 'z' */ + 138, /* '{' */ + 138, /* '|' */ + 138, /* '}' */ + 84, /* '~' */ + }, + + "AvantGarde-DemiOblique", + 0, + YES + }, { + /* width table for font CR */ + { + 100, /* ' ' */ + 100, /* '!' */ + 100, /* '"' */ + 100, /* '#' */ + 100, /* '$' */ + 100, /* '%' */ + 100, /* '&' */ + 100, /* ''' */ + 100, /* '(' */ + 100, /* ')' */ + 100, /* '*' */ + 100, /* '+' */ + 100, /* ',' */ + 100, /* '-' */ + 100, /* '.' */ + 100, /* '/' */ + 100, /* '0' */ + 100, /* '1' */ + 100, /* '2' */ + 100, /* '3' */ + 100, /* '4' */ + 100, /* '5' */ + 100, /* '6' */ + 100, /* '7' */ + 100, /* '8' */ + 100, /* '9' */ + 100, /* ':' */ + 100, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 100, /* '?' */ + 100, /* '@' */ + 100, /* 'A' */ + 100, /* 'B' */ + 100, /* 'C' */ + 100, /* 'D' */ + 100, /* 'E' */ + 100, /* 'F' */ + 100, /* 'G' */ + 100, /* 'H' */ + 100, /* 'I' */ + 100, /* 'J' */ + 100, /* 'K' */ + 100, /* 'L' */ + 100, /* 'M' */ + 100, /* 'N' */ + 100, /* 'O' */ + 100, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 100, /* 'S' */ + 100, /* 'T' */ + 100, /* 'U' */ + 100, /* 'V' */ + 100, /* 'W' */ + 100, /* 'X' */ + 100, /* 'Y' */ + 100, /* 'Z' */ + 100, /* '[' */ + 100, /* '\' */ + 100, /* ']' */ + 100, /* '^' */ + 100, /* '_' */ + 100, /* '`' */ + 100, /* 'a' */ + 100, /* 'b' */ + 100, /* 'c' */ + 100, /* 'd' */ + 100, /* 'e' */ + 100, /* 'f' */ + 100, /* 'g' */ + 100, /* 'h' */ + 100, /* 'i' */ + 100, /* 'j' */ + 100, /* 'k' */ + 100, /* 'l' */ + 100, /* 'm' */ + 100, /* 'n' */ + 100, /* 'o' */ + 100, /* 'p' */ + 100, /* 'q' */ + 100, /* 'r' */ + 100, /* 's' */ + 100, /* 't' */ + 100, /* 'u' */ + 100, /* 'v' */ + 100, /* 'w' */ + 100, /* 'x' */ + 100, /* 'y' */ + 100, /* 'z' */ + 100, /* '{' */ + 100, /* '|' */ + 100, /* '}' */ + 100, /* '~' */ + }, + /* height table for font CR */ + { + 153, /* ' ' */ + 133, /* '!' */ + 128, /* '"' */ + 146, /* '#' */ + 151, /* '$' */ + 134, /* '%' */ + 118, /* '&' */ + 128, /* ''' */ + 149, /* '(' */ + 149, /* ')' */ + 128, /* '*' */ + 116, /* '+' */ + 76, /* ',' */ + 79, /* '-' */ + 49, /* '.' */ + 153, /* '/' */ + 134, /* '0' */ + 130, /* '1' */ + 132, /* '2' */ + 134, /* '3' */ + 129, /* '4' */ + 131, /* '5' */ + 134, /* '6' */ + 129, /* '7' */ + 134, /* '8' */ + 134, /* '9' */ + 101, /* ':' */ + 123, /* ';' */ + 114, /* '<' */ + 89, /* '=' */ + 114, /* '>' */ + 128, /* '?' */ + 141, /* '@' */ + 122, /* 'A' */ + 122, /* 'B' */ + 128, /* 'C' */ + 122, /* 'D' */ + 122, /* 'E' */ + 122, /* 'F' */ + 128, /* 'G' */ + 122, /* 'H' */ + 122, /* 'I' */ + 124, /* 'J' */ + 122, /* 'K' */ + 122, /* 'L' */ + 122, /* 'M' */ + 122, /* 'N' */ + 128, /* 'O' */ + 122, /* 'P' */ + 145, /* 'Q' */ + 122, /* 'R' */ + 128, /* 'S' */ + 122, /* 'T' */ + 124, /* 'U' */ + 122, /* 'V' */ + 122, /* 'W' */ + 122, /* 'X' */ + 122, /* 'Y' */ + 122, /* 'Z' */ + 151, /* '[' */ + 153, /* '\' */ + 151, /* ']' */ + 130, /* '^' */ + 34, /* '_' */ + 128, /* '`' */ + 104, /* 'a' */ + 131, /* 'b' */ + 104, /* 'c' */ + 131, /* 'd' */ + 104, /* 'e' */ + 129, /* 'f' */ + 134, /* 'g' */ + 129, /* 'h' */ + 132, /* 'i' */ + 164, /* 'j' */ + 129, /* 'k' */ + 129, /* 'l' */ + 102, /* 'm' */ + 102, /* 'n' */ + 104, /* 'o' */ + 134, /* 'p' */ + 134, /* 'q' */ + 102, /* 'r' */ + 104, /* 's' */ + 124, /* 't' */ + 101, /* 'u' */ + 99, /* 'v' */ + 99, /* 'w' */ + 99, /* 'x' */ + 128, /* 'y' */ + 99, /* 'z' */ + 149, /* '{' */ + 149, /* '|' */ + 149, /* '}' */ + 86, /* '~' */ + }, + /* ascent table for font CR */ + { + 108, /* ' ' */ + 117, /* '!' */ + 115, /* '"' */ + 122, /* '#' */ + 122, /* '$' */ + 118, /* '%' */ + 102, /* '&' */ + 115, /* ''' */ + 115, /* '(' */ + 115, /* ')' */ + 115, /* '*' */ + 102, /* '+' */ + 38, /* ',' */ + 65, /* '-' */ + 33, /* '.' */ + 125, /* '/' */ + 118, /* '0' */ + 116, /* '1' */ + 118, /* '2' */ + 118, /* '3' */ + 115, /* '4' */ + 115, /* '5' */ + 118, /* '6' */ + 115, /* '7' */ + 118, /* '8' */ + 118, /* '9' */ + 85, /* ':' */ + 85, /* ';' */ + 100, /* '<' */ + 75, /* '=' */ + 100, /* '>' */ + 112, /* '?' */ + 118, /* '@' */ + 108, /* 'A' */ + 108, /* 'B' */ + 112, /* 'C' */ + 108, /* 'D' */ + 108, /* 'E' */ + 108, /* 'F' */ + 112, /* 'G' */ + 108, /* 'H' */ + 108, /* 'I' */ + 108, /* 'J' */ + 108, /* 'K' */ + 108, /* 'L' */ + 108, /* 'M' */ + 108, /* 'N' */ + 112, /* 'O' */ + 108, /* 'P' */ + 112, /* 'Q' */ + 108, /* 'R' */ + 112, /* 'S' */ + 108, /* 'T' */ + 108, /* 'U' */ + 108, /* 'V' */ + 108, /* 'W' */ + 108, /* 'X' */ + 108, /* 'Y' */ + 108, /* 'Z' */ + 115, /* '[' */ + 125, /* '\' */ + 115, /* ']' */ + 116, /* '^' */ + 2, /* '_' */ + 115, /* '`' */ + 88, /* 'a' */ + 115, /* 'b' */ + 88, /* 'c' */ + 115, /* 'd' */ + 88, /* 'e' */ + 115, /* 'f' */ + 88, /* 'g' */ + 115, /* 'h' */ + 118, /* 'i' */ + 118, /* 'j' */ + 115, /* 'k' */ + 115, /* 'l' */ + 88, /* 'm' */ + 88, /* 'n' */ + 88, /* 'o' */ + 88, /* 'p' */ + 88, /* 'q' */ + 88, /* 'r' */ + 88, /* 's' */ + 108, /* 't' */ + 85, /* 'u' */ + 85, /* 'v' */ + 85, /* 'w' */ + 85, /* 'x' */ + 85, /* 'y' */ + 85, /* 'z' */ + 115, /* '{' */ + 115, /* '|' */ + 115, /* '}' */ + 72, /* '~' */ + }, + + "Courier", + 0, + NO + }, { + /* width table for font CI */ + { + 100, /* ' ' */ + 100, /* '!' */ + 100, /* '"' */ + 100, /* '#' */ + 100, /* '$' */ + 100, /* '%' */ + 100, /* '&' */ + 100, /* ''' */ + 100, /* '(' */ + 100, /* ')' */ + 100, /* '*' */ + 100, /* '+' */ + 100, /* ',' */ + 100, /* '-' */ + 100, /* '.' */ + 100, /* '/' */ + 100, /* '0' */ + 100, /* '1' */ + 100, /* '2' */ + 100, /* '3' */ + 100, /* '4' */ + 100, /* '5' */ + 100, /* '6' */ + 100, /* '7' */ + 100, /* '8' */ + 100, /* '9' */ + 100, /* ':' */ + 100, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 100, /* '?' */ + 100, /* '@' */ + 100, /* 'A' */ + 100, /* 'B' */ + 100, /* 'C' */ + 100, /* 'D' */ + 100, /* 'E' */ + 100, /* 'F' */ + 100, /* 'G' */ + 100, /* 'H' */ + 100, /* 'I' */ + 100, /* 'J' */ + 100, /* 'K' */ + 100, /* 'L' */ + 100, /* 'M' */ + 100, /* 'N' */ + 100, /* 'O' */ + 100, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 100, /* 'S' */ + 100, /* 'T' */ + 100, /* 'U' */ + 100, /* 'V' */ + 100, /* 'W' */ + 100, /* 'X' */ + 100, /* 'Y' */ + 100, /* 'Z' */ + 100, /* '[' */ + 100, /* '\' */ + 100, /* ']' */ + 100, /* '^' */ + 100, /* '_' */ + 100, /* '`' */ + 100, /* 'a' */ + 100, /* 'b' */ + 100, /* 'c' */ + 100, /* 'd' */ + 100, /* 'e' */ + 100, /* 'f' */ + 100, /* 'g' */ + 100, /* 'h' */ + 100, /* 'i' */ + 100, /* 'j' */ + 100, /* 'k' */ + 100, /* 'l' */ + 100, /* 'm' */ + 100, /* 'n' */ + 100, /* 'o' */ + 100, /* 'p' */ + 100, /* 'q' */ + 100, /* 'r' */ + 100, /* 's' */ + 100, /* 't' */ + 100, /* 'u' */ + 100, /* 'v' */ + 100, /* 'w' */ + 100, /* 'x' */ + 100, /* 'y' */ + 100, /* 'z' */ + 100, /* '{' */ + 100, /* '|' */ + 100, /* '}' */ + 100, /* '~' */ + }, + /* height table for font CI */ + { + 153, /* ' ' */ + 133, /* '!' */ + 128, /* '"' */ + 146, /* '#' */ + 154, /* '$' */ + 134, /* '%' */ + 118, /* '&' */ + 128, /* ''' */ + 149, /* '(' */ + 149, /* ')' */ + 128, /* '*' */ + 116, /* '+' */ + 76, /* ',' */ + 79, /* '-' */ + 49, /* '.' */ + 153, /* '/' */ + 134, /* '0' */ + 130, /* '1' */ + 132, /* '2' */ + 134, /* '3' */ + 129, /* '4' */ + 131, /* '5' */ + 134, /* '6' */ + 129, /* '7' */ + 134, /* '8' */ + 134, /* '9' */ + 101, /* ':' */ + 123, /* ';' */ + 114, /* '<' */ + 89, /* '=' */ + 114, /* '>' */ + 128, /* '?' */ + 141, /* '@' */ + 122, /* 'A' */ + 122, /* 'B' */ + 128, /* 'C' */ + 122, /* 'D' */ + 122, /* 'E' */ + 122, /* 'F' */ + 128, /* 'G' */ + 122, /* 'H' */ + 122, /* 'I' */ + 124, /* 'J' */ + 122, /* 'K' */ + 122, /* 'L' */ + 122, /* 'M' */ + 122, /* 'N' */ + 128, /* 'O' */ + 122, /* 'P' */ + 145, /* 'Q' */ + 122, /* 'R' */ + 128, /* 'S' */ + 122, /* 'T' */ + 124, /* 'U' */ + 122, /* 'V' */ + 122, /* 'W' */ + 122, /* 'X' */ + 122, /* 'Y' */ + 122, /* 'Z' */ + 151, /* '[' */ + 153, /* '\' */ + 151, /* ']' */ + 130, /* '^' */ + 34, /* '_' */ + 129, /* '`' */ + 104, /* 'a' */ + 131, /* 'b' */ + 104, /* 'c' */ + 131, /* 'd' */ + 104, /* 'e' */ + 129, /* 'f' */ + 134, /* 'g' */ + 129, /* 'h' */ + 132, /* 'i' */ + 164, /* 'j' */ + 129, /* 'k' */ + 129, /* 'l' */ + 102, /* 'm' */ + 102, /* 'n' */ + 104, /* 'o' */ + 134, /* 'p' */ + 134, /* 'q' */ + 102, /* 'r' */ + 104, /* 's' */ + 124, /* 't' */ + 101, /* 'u' */ + 99, /* 'v' */ + 99, /* 'w' */ + 99, /* 'x' */ + 128, /* 'y' */ + 99, /* 'z' */ + 149, /* '{' */ + 149, /* '|' */ + 149, /* '}' */ + 86, /* '~' */ + }, + /* ascent table for font CI */ + { + 108, /* ' ' */ + 117, /* '!' */ + 115, /* '"' */ + 122, /* '#' */ + 125, /* '$' */ + 118, /* '%' */ + 102, /* '&' */ + 115, /* ''' */ + 115, /* '(' */ + 115, /* ')' */ + 115, /* '*' */ + 102, /* '+' */ + 38, /* ',' */ + 65, /* '-' */ + 33, /* '.' */ + 125, /* '/' */ + 118, /* '0' */ + 116, /* '1' */ + 118, /* '2' */ + 118, /* '3' */ + 115, /* '4' */ + 115, /* '5' */ + 118, /* '6' */ + 115, /* '7' */ + 118, /* '8' */ + 118, /* '9' */ + 85, /* ':' */ + 85, /* ';' */ + 100, /* '<' */ + 75, /* '=' */ + 100, /* '>' */ + 112, /* '?' */ + 118, /* '@' */ + 108, /* 'A' */ + 108, /* 'B' */ + 112, /* 'C' */ + 108, /* 'D' */ + 108, /* 'E' */ + 108, /* 'F' */ + 112, /* 'G' */ + 108, /* 'H' */ + 108, /* 'I' */ + 108, /* 'J' */ + 108, /* 'K' */ + 108, /* 'L' */ + 108, /* 'M' */ + 108, /* 'N' */ + 112, /* 'O' */ + 108, /* 'P' */ + 112, /* 'Q' */ + 108, /* 'R' */ + 112, /* 'S' */ + 108, /* 'T' */ + 108, /* 'U' */ + 108, /* 'V' */ + 108, /* 'W' */ + 108, /* 'X' */ + 108, /* 'Y' */ + 108, /* 'Z' */ + 115, /* '[' */ + 125, /* '\' */ + 115, /* ']' */ + 116, /* '^' */ + 2, /* '_' */ + 115, /* '`' */ + 88, /* 'a' */ + 115, /* 'b' */ + 88, /* 'c' */ + 115, /* 'd' */ + 88, /* 'e' */ + 115, /* 'f' */ + 88, /* 'g' */ + 115, /* 'h' */ + 118, /* 'i' */ + 118, /* 'j' */ + 115, /* 'k' */ + 115, /* 'l' */ + 88, /* 'm' */ + 88, /* 'n' */ + 88, /* 'o' */ + 88, /* 'p' */ + 88, /* 'q' */ + 88, /* 'r' */ + 88, /* 's' */ + 108, /* 't' */ + 85, /* 'u' */ + 85, /* 'v' */ + 85, /* 'w' */ + 85, /* 'x' */ + 85, /* 'y' */ + 85, /* 'z' */ + 115, /* '{' */ + 115, /* '|' */ + 115, /* '}' */ + 72, /* '~' */ + }, + + "Courier-Italic", + 0, + YES + }, { + /* width table for font CB */ + { + 100, /* ' ' */ + 100, /* '!' */ + 100, /* '"' */ + 100, /* '#' */ + 100, /* '$' */ + 100, /* '%' */ + 100, /* '&' */ + 100, /* ''' */ + 100, /* '(' */ + 100, /* ')' */ + 100, /* '*' */ + 100, /* '+' */ + 100, /* ',' */ + 100, /* '-' */ + 100, /* '.' */ + 100, /* '/' */ + 100, /* '0' */ + 100, /* '1' */ + 100, /* '2' */ + 100, /* '3' */ + 100, /* '4' */ + 100, /* '5' */ + 100, /* '6' */ + 100, /* '7' */ + 100, /* '8' */ + 100, /* '9' */ + 100, /* ':' */ + 100, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 100, /* '?' */ + 100, /* '@' */ + 100, /* 'A' */ + 100, /* 'B' */ + 100, /* 'C' */ + 100, /* 'D' */ + 100, /* 'E' */ + 100, /* 'F' */ + 100, /* 'G' */ + 100, /* 'H' */ + 100, /* 'I' */ + 100, /* 'J' */ + 100, /* 'K' */ + 100, /* 'L' */ + 100, /* 'M' */ + 100, /* 'N' */ + 100, /* 'O' */ + 100, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 100, /* 'S' */ + 100, /* 'T' */ + 100, /* 'U' */ + 100, /* 'V' */ + 100, /* 'W' */ + 100, /* 'X' */ + 100, /* 'Y' */ + 100, /* 'Z' */ + 100, /* '[' */ + 100, /* '\' */ + 100, /* ']' */ + 100, /* '^' */ + 100, /* '_' */ + 100, /* '`' */ + 100, /* 'a' */ + 100, /* 'b' */ + 100, /* 'c' */ + 100, /* 'd' */ + 100, /* 'e' */ + 100, /* 'f' */ + 100, /* 'g' */ + 100, /* 'h' */ + 100, /* 'i' */ + 100, /* 'j' */ + 100, /* 'k' */ + 100, /* 'l' */ + 100, /* 'm' */ + 100, /* 'n' */ + 100, /* 'o' */ + 100, /* 'p' */ + 100, /* 'q' */ + 100, /* 'r' */ + 100, /* 's' */ + 100, /* 't' */ + 100, /* 'u' */ + 100, /* 'v' */ + 100, /* 'w' */ + 100, /* 'x' */ + 100, /* 'y' */ + 100, /* 'z' */ + 100, /* '{' */ + 100, /* '|' */ + 100, /* '}' */ + 100, /* '~' */ + }, + /* height table for font CB */ + { + 153, /* ' ' */ + 136, /* '!' */ + 129, /* '"' */ + 156, /* '#' */ + 161, /* '$' */ + 131, /* '%' */ + 121, /* '&' */ + 132, /* ''' */ + 159, /* '(' */ + 159, /* ')' */ + 131, /* '*' */ + 121, /* '+' */ + 76, /* ',' */ + 82, /* '-' */ + 49, /* '.' */ + 162, /* '/' */ + 138, /* '0' */ + 134, /* '1' */ + 136, /* '2' */ + 138, /* '3' */ + 131, /* '4' */ + 134, /* '5' */ + 138, /* '6' */ + 132, /* '7' */ + 138, /* '8' */ + 138, /* '9' */ + 104, /* ':' */ + 129, /* ';' */ + 111, /* '<' */ + 99, /* '=' */ + 111, /* '>' */ + 131, /* '?' */ + 158, /* '@' */ + 126, /* 'A' */ + 126, /* 'B' */ + 131, /* 'C' */ + 126, /* 'D' */ + 126, /* 'E' */ + 126, /* 'F' */ + 131, /* 'G' */ + 126, /* 'H' */ + 126, /* 'I' */ + 128, /* 'J' */ + 126, /* 'K' */ + 126, /* 'L' */ + 126, /* 'M' */ + 126, /* 'N' */ + 131, /* 'O' */ + 126, /* 'P' */ + 154, /* 'Q' */ + 126, /* 'R' */ + 131, /* 'S' */ + 126, /* 'T' */ + 128, /* 'U' */ + 126, /* 'V' */ + 126, /* 'W' */ + 126, /* 'X' */ + 126, /* 'Y' */ + 126, /* 'Z' */ + 158, /* '[' */ + 162, /* '\' */ + 158, /* ']' */ + 136, /* '^' */ + 38, /* '_' */ + 129, /* '`' */ + 108, /* 'a' */ + 134, /* 'b' */ + 108, /* 'c' */ + 134, /* 'd' */ + 108, /* 'e' */ + 132, /* 'f' */ + 141, /* 'g' */ + 132, /* 'h' */ + 132, /* 'i' */ + 168, /* 'j' */ + 132, /* 'k' */ + 132, /* 'l' */ + 106, /* 'm' */ + 106, /* 'n' */ + 108, /* 'o' */ + 141, /* 'p' */ + 141, /* 'q' */ + 106, /* 'r' */ + 108, /* 's' */ + 131, /* 't' */ + 104, /* 'u' */ + 102, /* 'v' */ + 102, /* 'w' */ + 102, /* 'x' */ + 138, /* 'y' */ + 102, /* 'z' */ + 157, /* '{' */ + 157, /* '|' */ + 157, /* '}' */ + 92, /* '~' */ + }, + /* ascent table for font CB */ + { + 108, /* ' ' */ + 120, /* '!' */ + 115, /* '"' */ + 126, /* '#' */ + 128, /* '$' */ + 115, /* '%' */ + 105, /* '&' */ + 118, /* ''' */ + 119, /* '(' */ + 119, /* ')' */ + 118, /* '*' */ + 107, /* '+' */ + 36, /* ',' */ + 68, /* '-' */ + 33, /* '.' */ + 130, /* '/' */ + 122, /* '0' */ + 120, /* '1' */ + 122, /* '2' */ + 122, /* '3' */ + 118, /* '4' */ + 118, /* '5' */ + 122, /* '6' */ + 118, /* '7' */ + 122, /* '8' */ + 122, /* '9' */ + 88, /* ':' */ + 88, /* ';' */ + 97, /* '<' */ + 85, /* '=' */ + 97, /* '>' */ + 115, /* '?' */ + 118, /* '@' */ + 112, /* 'A' */ + 112, /* 'B' */ + 115, /* 'C' */ + 112, /* 'D' */ + 112, /* 'E' */ + 112, /* 'F' */ + 115, /* 'G' */ + 112, /* 'H' */ + 112, /* 'I' */ + 112, /* 'J' */ + 112, /* 'K' */ + 112, /* 'L' */ + 112, /* 'M' */ + 112, /* 'N' */ + 115, /* 'O' */ + 112, /* 'P' */ + 115, /* 'Q' */ + 112, /* 'R' */ + 115, /* 'S' */ + 112, /* 'T' */ + 112, /* 'U' */ + 112, /* 'V' */ + 112, /* 'W' */ + 112, /* 'X' */ + 112, /* 'Y' */ + 112, /* 'Z' */ + 118, /* '[' */ + 130, /* '\' */ + 118, /* ']' */ + 123, /* '^' */ + 2, /* '_' */ + 115, /* '`' */ + 92, /* 'a' */ + 118, /* 'b' */ + 92, /* 'c' */ + 118, /* 'd' */ + 92, /* 'e' */ + 118, /* 'f' */ + 92, /* 'g' */ + 118, /* 'h' */ + 118, /* 'i' */ + 118, /* 'j' */ + 118, /* 'k' */ + 118, /* 'l' */ + 92, /* 'm' */ + 92, /* 'n' */ + 92, /* 'o' */ + 92, /* 'p' */ + 92, /* 'q' */ + 92, /* 'r' */ + 92, /* 's' */ + 115, /* 't' */ + 88, /* 'u' */ + 88, /* 'v' */ + 88, /* 'w' */ + 88, /* 'x' */ + 88, /* 'y' */ + 88, /* 'z' */ + 118, /* '{' */ + 118, /* '|' */ + 118, /* '}' */ + 78, /* '~' */ + }, + + "Courier-Bold", + 0, + NO + }, { + /* width table for font CX */ + { + 100, /* ' ' */ + 100, /* '!' */ + 100, /* '"' */ + 100, /* '#' */ + 100, /* '$' */ + 100, /* '%' */ + 100, /* '&' */ + 100, /* ''' */ + 100, /* '(' */ + 100, /* ')' */ + 100, /* '*' */ + 100, /* '+' */ + 100, /* ',' */ + 100, /* '-' */ + 100, /* '.' */ + 100, /* '/' */ + 100, /* '0' */ + 100, /* '1' */ + 100, /* '2' */ + 100, /* '3' */ + 100, /* '4' */ + 100, /* '5' */ + 100, /* '6' */ + 100, /* '7' */ + 100, /* '8' */ + 100, /* '9' */ + 100, /* ':' */ + 100, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 100, /* '?' */ + 100, /* '@' */ + 100, /* 'A' */ + 100, /* 'B' */ + 100, /* 'C' */ + 100, /* 'D' */ + 100, /* 'E' */ + 100, /* 'F' */ + 100, /* 'G' */ + 100, /* 'H' */ + 100, /* 'I' */ + 100, /* 'J' */ + 100, /* 'K' */ + 100, /* 'L' */ + 100, /* 'M' */ + 100, /* 'N' */ + 100, /* 'O' */ + 100, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 100, /* 'S' */ + 100, /* 'T' */ + 100, /* 'U' */ + 100, /* 'V' */ + 100, /* 'W' */ + 100, /* 'X' */ + 100, /* 'Y' */ + 100, /* 'Z' */ + 100, /* '[' */ + 100, /* '\' */ + 100, /* ']' */ + 100, /* '^' */ + 100, /* '_' */ + 100, /* '`' */ + 100, /* 'a' */ + 100, /* 'b' */ + 100, /* 'c' */ + 100, /* 'd' */ + 100, /* 'e' */ + 100, /* 'f' */ + 100, /* 'g' */ + 100, /* 'h' */ + 100, /* 'i' */ + 100, /* 'j' */ + 100, /* 'k' */ + 100, /* 'l' */ + 100, /* 'm' */ + 100, /* 'n' */ + 100, /* 'o' */ + 100, /* 'p' */ + 100, /* 'q' */ + 100, /* 'r' */ + 100, /* 's' */ + 100, /* 't' */ + 100, /* 'u' */ + 100, /* 'v' */ + 100, /* 'w' */ + 100, /* 'x' */ + 100, /* 'y' */ + 100, /* 'z' */ + 100, /* '{' */ + 100, /* '|' */ + 100, /* '}' */ + 100, /* '~' */ + }, + /* height table for font CX */ + { + 153, /* ' ' */ + 136, /* '!' */ + 129, /* '"' */ + 156, /* '#' */ + 161, /* '$' */ + 131, /* '%' */ + 121, /* '&' */ + 132, /* ''' */ + 159, /* '(' */ + 159, /* ')' */ + 131, /* '*' */ + 121, /* '+' */ + 76, /* ',' */ + 82, /* '-' */ + 49, /* '.' */ + 162, /* '/' */ + 138, /* '0' */ + 134, /* '1' */ + 136, /* '2' */ + 138, /* '3' */ + 131, /* '4' */ + 134, /* '5' */ + 138, /* '6' */ + 132, /* '7' */ + 138, /* '8' */ + 138, /* '9' */ + 104, /* ':' */ + 129, /* ';' */ + 111, /* '<' */ + 99, /* '=' */ + 111, /* '>' */ + 131, /* '?' */ + 158, /* '@' */ + 126, /* 'A' */ + 126, /* 'B' */ + 131, /* 'C' */ + 126, /* 'D' */ + 126, /* 'E' */ + 126, /* 'F' */ + 131, /* 'G' */ + 126, /* 'H' */ + 126, /* 'I' */ + 128, /* 'J' */ + 126, /* 'K' */ + 126, /* 'L' */ + 126, /* 'M' */ + 126, /* 'N' */ + 131, /* 'O' */ + 126, /* 'P' */ + 154, /* 'Q' */ + 126, /* 'R' */ + 131, /* 'S' */ + 126, /* 'T' */ + 128, /* 'U' */ + 126, /* 'V' */ + 126, /* 'W' */ + 126, /* 'X' */ + 126, /* 'Y' */ + 126, /* 'Z' */ + 158, /* '[' */ + 162, /* '\' */ + 158, /* ']' */ + 136, /* '^' */ + 38, /* '_' */ + 129, /* '`' */ + 108, /* 'a' */ + 134, /* 'b' */ + 108, /* 'c' */ + 134, /* 'd' */ + 108, /* 'e' */ + 132, /* 'f' */ + 141, /* 'g' */ + 132, /* 'h' */ + 132, /* 'i' */ + 168, /* 'j' */ + 132, /* 'k' */ + 132, /* 'l' */ + 106, /* 'm' */ + 106, /* 'n' */ + 108, /* 'o' */ + 141, /* 'p' */ + 141, /* 'q' */ + 106, /* 'r' */ + 108, /* 's' */ + 131, /* 't' */ + 104, /* 'u' */ + 102, /* 'v' */ + 102, /* 'w' */ + 102, /* 'x' */ + 138, /* 'y' */ + 102, /* 'z' */ + 157, /* '{' */ + 157, /* '|' */ + 157, /* '}' */ + 92, /* '~' */ + }, + /* ascent table for font CX */ + { + 108, /* ' ' */ + 120, /* '!' */ + 115, /* '"' */ + 126, /* '#' */ + 128, /* '$' */ + 115, /* '%' */ + 105, /* '&' */ + 118, /* ''' */ + 119, /* '(' */ + 119, /* ')' */ + 118, /* '*' */ + 107, /* '+' */ + 36, /* ',' */ + 68, /* '-' */ + 33, /* '.' */ + 130, /* '/' */ + 122, /* '0' */ + 120, /* '1' */ + 122, /* '2' */ + 122, /* '3' */ + 118, /* '4' */ + 118, /* '5' */ + 122, /* '6' */ + 118, /* '7' */ + 122, /* '8' */ + 122, /* '9' */ + 88, /* ':' */ + 88, /* ';' */ + 97, /* '<' */ + 85, /* '=' */ + 97, /* '>' */ + 115, /* '?' */ + 118, /* '@' */ + 112, /* 'A' */ + 112, /* 'B' */ + 115, /* 'C' */ + 112, /* 'D' */ + 112, /* 'E' */ + 112, /* 'F' */ + 115, /* 'G' */ + 112, /* 'H' */ + 112, /* 'I' */ + 112, /* 'J' */ + 112, /* 'K' */ + 112, /* 'L' */ + 112, /* 'M' */ + 112, /* 'N' */ + 115, /* 'O' */ + 112, /* 'P' */ + 115, /* 'Q' */ + 112, /* 'R' */ + 115, /* 'S' */ + 112, /* 'T' */ + 112, /* 'U' */ + 112, /* 'V' */ + 112, /* 'W' */ + 112, /* 'X' */ + 112, /* 'Y' */ + 112, /* 'Z' */ + 118, /* '[' */ + 130, /* '\' */ + 118, /* ']' */ + 123, /* '^' */ + 2, /* '_' */ + 115, /* '`' */ + 92, /* 'a' */ + 118, /* 'b' */ + 92, /* 'c' */ + 118, /* 'd' */ + 92, /* 'e' */ + 118, /* 'f' */ + 92, /* 'g' */ + 118, /* 'h' */ + 118, /* 'i' */ + 118, /* 'j' */ + 118, /* 'k' */ + 118, /* 'l' */ + 92, /* 'm' */ + 92, /* 'n' */ + 92, /* 'o' */ + 92, /* 'p' */ + 92, /* 'q' */ + 92, /* 'r' */ + 92, /* 's' */ + 115, /* 't' */ + 88, /* 'u' */ + 88, /* 'v' */ + 88, /* 'w' */ + 88, /* 'x' */ + 88, /* 'y' */ + 88, /* 'z' */ + 118, /* '{' */ + 118, /* '|' */ + 118, /* '}' */ + 78, /* '~' */ + }, + + "Courier-BoldItalic", + 0, + YES + }, { + /* width table for font HR */ + { + 46, /* ' ' */ + 46, /* '!' */ + 59, /* '"' */ + 93, /* '#' */ + 93, /* '$' */ + 148, /* '%' */ + 111, /* '&' */ + 37, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 65, /* '*' */ + 97, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 46, /* '/' */ + 93, /* '0' */ + 93, /* '1' */ + 93, /* '2' */ + 93, /* '3' */ + 93, /* '4' */ + 93, /* '5' */ + 93, /* '6' */ + 93, /* '7' */ + 93, /* '8' */ + 93, /* '9' */ + 46, /* ':' */ + 46, /* ';' */ + 97, /* '<' */ + 97, /* '=' */ + 97, /* '>' */ + 93, /* '?' */ + 169, /* '@' */ + 111, /* 'A' */ + 111, /* 'B' */ + 120, /* 'C' */ + 120, /* 'D' */ + 111, /* 'E' */ + 102, /* 'F' */ + 130, /* 'G' */ + 120, /* 'H' */ + 46, /* 'I' */ + 83, /* 'J' */ + 111, /* 'K' */ + 93, /* 'L' */ + 139, /* 'M' */ + 120, /* 'N' */ + 130, /* 'O' */ + 111, /* 'P' */ + 130, /* 'Q' */ + 120, /* 'R' */ + 111, /* 'S' */ + 102, /* 'T' */ + 120, /* 'U' */ + 111, /* 'V' */ + 157, /* 'W' */ + 111, /* 'X' */ + 111, /* 'Y' */ + 102, /* 'Z' */ + 46, /* '[' */ + 46, /* '\' */ + 46, /* ']' */ + 78, /* '^' */ + 93, /* '_' */ + 37, /* '`' */ + 93, /* 'a' */ + 93, /* 'b' */ + 83, /* 'c' */ + 93, /* 'd' */ + 93, /* 'e' */ + 46, /* 'f' */ + 93, /* 'g' */ + 93, /* 'h' */ + 37, /* 'i' */ + 37, /* 'j' */ + 83, /* 'k' */ + 37, /* 'l' */ + 139, /* 'm' */ + 93, /* 'n' */ + 93, /* 'o' */ + 93, /* 'p' */ + 93, /* 'q' */ + 55, /* 'r' */ + 83, /* 's' */ + 46, /* 't' */ + 93, /* 'u' */ + 83, /* 'v' */ + 120, /* 'w' */ + 83, /* 'x' */ + 83, /* 'y' */ + 83, /* 'z' */ + 56, /* '{' */ + 43, /* '|' */ + 56, /* '}' */ + 97, /* '~' */ + }, + /* height table for font HR */ + { + 153, /* ' ' */ + 149, /* '!' */ + 146, /* '"' */ + 146, /* '#' */ + 177, /* '$' */ + 148, /* '%' */ + 149, /* '&' */ + 149, /* ''' */ + 184, /* '(' */ + 184, /* ')' */ + 149, /* '*' */ + 109, /* '+' */ + 70, /* ',' */ + 79, /* '-' */ + 46, /* '.' */ + 151, /* '/' */ + 149, /* '0' */ + 146, /* '1' */ + 146, /* '2' */ + 149, /* '3' */ + 146, /* '4' */ + 149, /* '5' */ + 149, /* '6' */ + 146, /* '7' */ + 149, /* '8' */ + 149, /* '9' */ + 116, /* ':' */ + 140, /* ';' */ + 108, /* '<' */ + 89, /* '=' */ + 108, /* '>' */ + 152, /* '?' */ + 178, /* '@' */ + 149, /* 'A' */ + 149, /* 'B' */ + 155, /* 'C' */ + 149, /* 'D' */ + 149, /* 'E' */ + 149, /* 'F' */ + 155, /* 'G' */ + 149, /* 'H' */ + 149, /* 'I' */ + 152, /* 'J' */ + 149, /* 'K' */ + 149, /* 'L' */ + 149, /* 'M' */ + 149, /* 'N' */ + 155, /* 'O' */ + 149, /* 'P' */ + 162, /* 'Q' */ + 149, /* 'R' */ + 155, /* 'S' */ + 149, /* 'T' */ + 152, /* 'U' */ + 149, /* 'V' */ + 149, /* 'W' */ + 149, /* 'X' */ + 149, /* 'Y' */ + 149, /* 'Z' */ + 184, /* '[' */ + 151, /* '\' */ + 184, /* ']' */ + 146, /* '^' */ + 38, /* '_' */ + 146, /* '`' */ + 122, /* 'a' */ + 152, /* 'b' */ + 122, /* 'c' */ + 152, /* 'd' */ + 122, /* 'e' */ + 149, /* 'f' */ + 154, /* 'g' */ + 149, /* 'h' */ + 149, /* 'i' */ + 185, /* 'j' */ + 149, /* 'k' */ + 149, /* 'l' */ + 119, /* 'm' */ + 119, /* 'n' */ + 122, /* 'o' */ + 154, /* 'p' */ + 154, /* 'q' */ + 119, /* 'r' */ + 122, /* 's' */ + 142, /* 't' */ + 118, /* 'u' */ + 116, /* 'v' */ + 116, /* 'w' */ + 116, /* 'x' */ + 151, /* 'y' */ + 116, /* 'z' */ + 184, /* '{' */ + 184, /* '|' */ + 184, /* '}' */ + 99, /* '~' */ + }, + /* ascent table for font HR */ + { + 108, /* ' ' */ + 135, /* '!' */ + 132, /* '"' */ + 130, /* '#' */ + 142, /* '$' */ + 132, /* '%' */ + 132, /* '&' */ + 135, /* ''' */ + 135, /* '(' */ + 135, /* ')' */ + 135, /* '*' */ + 93, /* '+' */ + 32, /* ',' */ + 65, /* '-' */ + 32, /* '.' */ + 135, /* '/' */ + 132, /* '0' */ + 132, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 132, /* '4' */ + 132, /* '5' */ + 132, /* '6' */ + 132, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 102, /* ':' */ + 102, /* ';' */ + 93, /* '<' */ + 75, /* '=' */ + 93, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 135, /* 'A' */ + 135, /* 'B' */ + 138, /* 'C' */ + 135, /* 'D' */ + 135, /* 'E' */ + 135, /* 'F' */ + 138, /* 'G' */ + 135, /* 'H' */ + 135, /* 'I' */ + 135, /* 'J' */ + 135, /* 'K' */ + 135, /* 'L' */ + 135, /* 'M' */ + 135, /* 'N' */ + 138, /* 'O' */ + 135, /* 'P' */ + 138, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 135, /* 'T' */ + 135, /* 'U' */ + 135, /* 'V' */ + 135, /* 'W' */ + 135, /* 'X' */ + 135, /* 'Y' */ + 135, /* 'Z' */ + 135, /* '[' */ + 135, /* '\' */ + 135, /* ']' */ + 132, /* '^' */ + -5, /* '_' */ + 132, /* '`' */ + 105, /* 'a' */ + 135, /* 'b' */ + 105, /* 'c' */ + 135, /* 'd' */ + 105, /* 'e' */ + 135, /* 'f' */ + 105, /* 'g' */ + 135, /* 'h' */ + 135, /* 'i' */ + 135, /* 'j' */ + 135, /* 'k' */ + 135, /* 'l' */ + 105, /* 'm' */ + 105, /* 'n' */ + 105, /* 'o' */ + 105, /* 'p' */ + 105, /* 'q' */ + 105, /* 'r' */ + 105, /* 's' */ + 125, /* 't' */ + 102, /* 'u' */ + 102, /* 'v' */ + 102, /* 'w' */ + 102, /* 'x' */ + 102, /* 'y' */ + 102, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 85, /* '~' */ + }, + + "Helvetica", + 0, + NO + }, { + /* width table for font HI */ + { + 46, /* ' ' */ + 46, /* '!' */ + 59, /* '"' */ + 93, /* '#' */ + 93, /* '$' */ + 148, /* '%' */ + 111, /* '&' */ + 37, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 65, /* '*' */ + 97, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 46, /* '/' */ + 93, /* '0' */ + 93, /* '1' */ + 93, /* '2' */ + 93, /* '3' */ + 93, /* '4' */ + 93, /* '5' */ + 93, /* '6' */ + 93, /* '7' */ + 93, /* '8' */ + 93, /* '9' */ + 46, /* ':' */ + 46, /* ';' */ + 97, /* '<' */ + 97, /* '=' */ + 97, /* '>' */ + 93, /* '?' */ + 169, /* '@' */ + 111, /* 'A' */ + 111, /* 'B' */ + 120, /* 'C' */ + 120, /* 'D' */ + 111, /* 'E' */ + 102, /* 'F' */ + 130, /* 'G' */ + 120, /* 'H' */ + 46, /* 'I' */ + 83, /* 'J' */ + 111, /* 'K' */ + 93, /* 'L' */ + 139, /* 'M' */ + 120, /* 'N' */ + 130, /* 'O' */ + 111, /* 'P' */ + 130, /* 'Q' */ + 120, /* 'R' */ + 111, /* 'S' */ + 102, /* 'T' */ + 120, /* 'U' */ + 111, /* 'V' */ + 157, /* 'W' */ + 111, /* 'X' */ + 111, /* 'Y' */ + 102, /* 'Z' */ + 46, /* '[' */ + 46, /* '\' */ + 46, /* ']' */ + 78, /* '^' */ + 93, /* '_' */ + 37, /* '`' */ + 93, /* 'a' */ + 93, /* 'b' */ + 83, /* 'c' */ + 93, /* 'd' */ + 93, /* 'e' */ + 46, /* 'f' */ + 93, /* 'g' */ + 93, /* 'h' */ + 37, /* 'i' */ + 37, /* 'j' */ + 83, /* 'k' */ + 37, /* 'l' */ + 139, /* 'm' */ + 93, /* 'n' */ + 93, /* 'o' */ + 93, /* 'p' */ + 93, /* 'q' */ + 55, /* 'r' */ + 83, /* 's' */ + 46, /* 't' */ + 93, /* 'u' */ + 83, /* 'v' */ + 120, /* 'w' */ + 83, /* 'x' */ + 83, /* 'y' */ + 83, /* 'z' */ + 56, /* '{' */ + 43, /* '|' */ + 56, /* '}' */ + 97, /* '~' */ + }, + /* height table for font HI */ + { + 153, /* ' ' */ + 149, /* '!' */ + 146, /* '"' */ + 146, /* '#' */ + 177, /* '$' */ + 148, /* '%' */ + 149, /* '&' */ + 146, /* ''' */ + 184, /* '(' */ + 184, /* ')' */ + 149, /* '*' */ + 109, /* '+' */ + 70, /* ',' */ + 79, /* '-' */ + 46, /* '.' */ + 151, /* '/' */ + 149, /* '0' */ + 146, /* '1' */ + 146, /* '2' */ + 149, /* '3' */ + 146, /* '4' */ + 149, /* '5' */ + 149, /* '6' */ + 146, /* '7' */ + 149, /* '8' */ + 149, /* '9' */ + 116, /* ':' */ + 140, /* ';' */ + 108, /* '<' */ + 89, /* '=' */ + 108, /* '>' */ + 152, /* '?' */ + 178, /* '@' */ + 149, /* 'A' */ + 149, /* 'B' */ + 155, /* 'C' */ + 149, /* 'D' */ + 149, /* 'E' */ + 149, /* 'F' */ + 155, /* 'G' */ + 149, /* 'H' */ + 149, /* 'I' */ + 152, /* 'J' */ + 149, /* 'K' */ + 149, /* 'L' */ + 149, /* 'M' */ + 149, /* 'N' */ + 155, /* 'O' */ + 149, /* 'P' */ + 162, /* 'Q' */ + 149, /* 'R' */ + 155, /* 'S' */ + 149, /* 'T' */ + 152, /* 'U' */ + 149, /* 'V' */ + 149, /* 'W' */ + 149, /* 'X' */ + 149, /* 'Y' */ + 149, /* 'Z' */ + 184, /* '[' */ + 151, /* '\' */ + 184, /* ']' */ + 146, /* '^' */ + 38, /* '_' */ + 146, /* '`' */ + 122, /* 'a' */ + 152, /* 'b' */ + 122, /* 'c' */ + 152, /* 'd' */ + 122, /* 'e' */ + 149, /* 'f' */ + 154, /* 'g' */ + 149, /* 'h' */ + 149, /* 'i' */ + 185, /* 'j' */ + 149, /* 'k' */ + 149, /* 'l' */ + 119, /* 'm' */ + 119, /* 'n' */ + 122, /* 'o' */ + 154, /* 'p' */ + 154, /* 'q' */ + 119, /* 'r' */ + 122, /* 's' */ + 142, /* 't' */ + 118, /* 'u' */ + 116, /* 'v' */ + 116, /* 'w' */ + 116, /* 'x' */ + 151, /* 'y' */ + 116, /* 'z' */ + 184, /* '{' */ + 184, /* '|' */ + 184, /* '}' */ + 99, /* '~' */ + }, + /* ascent table for font HI */ + { + 108, /* ' ' */ + 135, /* '!' */ + 132, /* '"' */ + 130, /* '#' */ + 142, /* '$' */ + 132, /* '%' */ + 132, /* '&' */ + 132, /* ''' */ + 135, /* '(' */ + 135, /* ')' */ + 135, /* '*' */ + 93, /* '+' */ + 32, /* ',' */ + 65, /* '-' */ + 32, /* '.' */ + 135, /* '/' */ + 132, /* '0' */ + 132, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 132, /* '4' */ + 132, /* '5' */ + 132, /* '6' */ + 132, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 102, /* ':' */ + 102, /* ';' */ + 93, /* '<' */ + 75, /* '=' */ + 93, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 135, /* 'A' */ + 135, /* 'B' */ + 138, /* 'C' */ + 135, /* 'D' */ + 135, /* 'E' */ + 135, /* 'F' */ + 138, /* 'G' */ + 135, /* 'H' */ + 135, /* 'I' */ + 135, /* 'J' */ + 135, /* 'K' */ + 135, /* 'L' */ + 135, /* 'M' */ + 135, /* 'N' */ + 138, /* 'O' */ + 135, /* 'P' */ + 138, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 135, /* 'T' */ + 135, /* 'U' */ + 135, /* 'V' */ + 135, /* 'W' */ + 135, /* 'X' */ + 135, /* 'Y' */ + 135, /* 'Z' */ + 135, /* '[' */ + 135, /* '\' */ + 135, /* ']' */ + 132, /* '^' */ + -5, /* '_' */ + 132, /* '`' */ + 105, /* 'a' */ + 135, /* 'b' */ + 105, /* 'c' */ + 135, /* 'd' */ + 105, /* 'e' */ + 135, /* 'f' */ + 105, /* 'g' */ + 135, /* 'h' */ + 135, /* 'i' */ + 135, /* 'j' */ + 135, /* 'k' */ + 135, /* 'l' */ + 105, /* 'm' */ + 105, /* 'n' */ + 105, /* 'o' */ + 105, /* 'p' */ + 105, /* 'q' */ + 105, /* 'r' */ + 105, /* 's' */ + 125, /* 't' */ + 102, /* 'u' */ + 102, /* 'v' */ + 102, /* 'w' */ + 102, /* 'x' */ + 102, /* 'y' */ + 102, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 85, /* '~' */ + }, + + "Helvetica-Oblique", + 0, + YES + }, { + /* width table for font HB */ + { + 46, /* ' ' */ + 55, /* '!' */ + 79, /* '"' */ + 93, /* '#' */ + 93, /* '$' */ + 148, /* '%' */ + 120, /* '&' */ + 46, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 65, /* '*' */ + 97, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 46, /* '/' */ + 93, /* '0' */ + 93, /* '1' */ + 93, /* '2' */ + 93, /* '3' */ + 93, /* '4' */ + 93, /* '5' */ + 93, /* '6' */ + 93, /* '7' */ + 93, /* '8' */ + 93, /* '9' */ + 55, /* ':' */ + 55, /* ';' */ + 97, /* '<' */ + 97, /* '=' */ + 97, /* '>' */ + 102, /* '?' */ + 162, /* '@' */ + 120, /* 'A' */ + 120, /* 'B' */ + 120, /* 'C' */ + 120, /* 'D' */ + 111, /* 'E' */ + 102, /* 'F' */ + 130, /* 'G' */ + 120, /* 'H' */ + 46, /* 'I' */ + 93, /* 'J' */ + 120, /* 'K' */ + 102, /* 'L' */ + 139, /* 'M' */ + 120, /* 'N' */ + 130, /* 'O' */ + 111, /* 'P' */ + 130, /* 'Q' */ + 120, /* 'R' */ + 111, /* 'S' */ + 102, /* 'T' */ + 120, /* 'U' */ + 111, /* 'V' */ + 157, /* 'W' */ + 111, /* 'X' */ + 111, /* 'Y' */ + 102, /* 'Z' */ + 55, /* '[' */ + 46, /* '\' */ + 55, /* ']' */ + 97, /* '^' */ + 93, /* '_' */ + 46, /* '`' */ + 93, /* 'a' */ + 102, /* 'b' */ + 93, /* 'c' */ + 102, /* 'd' */ + 93, /* 'e' */ + 55, /* 'f' */ + 102, /* 'g' */ + 102, /* 'h' */ + 46, /* 'i' */ + 46, /* 'j' */ + 93, /* 'k' */ + 46, /* 'l' */ + 148, /* 'm' */ + 102, /* 'n' */ + 102, /* 'o' */ + 102, /* 'p' */ + 102, /* 'q' */ + 65, /* 'r' */ + 93, /* 's' */ + 55, /* 't' */ + 102, /* 'u' */ + 93, /* 'v' */ + 130, /* 'w' */ + 93, /* 'x' */ + 93, /* 'y' */ + 83, /* 'z' */ + 65, /* '{' */ + 47, /* '|' */ + 65, /* '}' */ + 97, /* '~' */ + }, + /* height table for font HB */ + { + 153, /* ' ' */ + 149, /* '!' */ + 149, /* '"' */ + 149, /* '#' */ + 176, /* '$' */ + 148, /* '%' */ + 152, /* '&' */ + 149, /* ''' */ + 182, /* '(' */ + 182, /* ')' */ + 149, /* '*' */ + 109, /* '+' */ + 81, /* ',' */ + 82, /* '-' */ + 52, /* '.' */ + 149, /* '/' */ + 152, /* '0' */ + 146, /* '1' */ + 149, /* '2' */ + 152, /* '3' */ + 146, /* '4' */ + 152, /* '5' */ + 152, /* '6' */ + 149, /* '7' */ + 152, /* '8' */ + 155, /* '9' */ + 116, /* ':' */ + 145, /* ';' */ + 108, /* '<' */ + 96, /* '=' */ + 108, /* '>' */ + 152, /* '?' */ + 174, /* '@' */ + 149, /* 'A' */ + 149, /* 'B' */ + 155, /* 'C' */ + 149, /* 'D' */ + 149, /* 'E' */ + 149, /* 'F' */ + 155, /* 'G' */ + 149, /* 'H' */ + 149, /* 'I' */ + 152, /* 'J' */ + 149, /* 'K' */ + 149, /* 'L' */ + 149, /* 'M' */ + 149, /* 'N' */ + 155, /* 'O' */ + 149, /* 'P' */ + 161, /* 'Q' */ + 149, /* 'R' */ + 155, /* 'S' */ + 149, /* 'T' */ + 152, /* 'U' */ + 149, /* 'V' */ + 149, /* 'W' */ + 149, /* 'X' */ + 149, /* 'Y' */ + 149, /* 'Z' */ + 181, /* '[' */ + 149, /* '\' */ + 181, /* ']' */ + 144, /* '^' */ + 38, /* '_' */ + 149, /* '`' */ + 125, /* 'a' */ + 152, /* 'b' */ + 125, /* 'c' */ + 152, /* 'd' */ + 125, /* 'e' */ + 149, /* 'f' */ + 158, /* 'g' */ + 149, /* 'h' */ + 149, /* 'i' */ + 185, /* 'j' */ + 149, /* 'k' */ + 149, /* 'l' */ + 122, /* 'm' */ + 122, /* 'n' */ + 125, /* 'o' */ + 158, /* 'p' */ + 158, /* 'q' */ + 122, /* 'r' */ + 125, /* 's' */ + 143, /* 't' */ + 122, /* 'u' */ + 119, /* 'v' */ + 119, /* 'w' */ + 119, /* 'x' */ + 155, /* 'y' */ + 119, /* 'z' */ + 181, /* '{' */ + 182, /* '|' */ + 181, /* '}' */ + 79, /* '~' */ + }, + /* ascent table for font HB */ + { + 108, /* ' ' */ + 135, /* '!' */ + 135, /* '"' */ + 130, /* '#' */ + 141, /* '$' */ + 132, /* '%' */ + 135, /* '&' */ + 135, /* ''' */ + 135, /* '(' */ + 135, /* ')' */ + 135, /* '*' */ + 93, /* '+' */ + 38, /* ',' */ + 68, /* '-' */ + 38, /* '.' */ + 133, /* '/' */ + 136, /* '0' */ + 132, /* '1' */ + 136, /* '2' */ + 135, /* '3' */ + 132, /* '4' */ + 135, /* '5' */ + 136, /* '6' */ + 135, /* '7' */ + 136, /* '8' */ + 136, /* '9' */ + 102, /* ':' */ + 102, /* ';' */ + 93, /* '<' */ + 82, /* '=' */ + 93, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 135, /* 'A' */ + 135, /* 'B' */ + 138, /* 'C' */ + 135, /* 'D' */ + 135, /* 'E' */ + 135, /* 'F' */ + 138, /* 'G' */ + 135, /* 'H' */ + 135, /* 'I' */ + 135, /* 'J' */ + 135, /* 'K' */ + 135, /* 'L' */ + 135, /* 'M' */ + 135, /* 'N' */ + 138, /* 'O' */ + 135, /* 'P' */ + 138, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 135, /* 'T' */ + 135, /* 'U' */ + 135, /* 'V' */ + 135, /* 'W' */ + 135, /* 'X' */ + 135, /* 'Y' */ + 135, /* 'Z' */ + 135, /* '[' */ + 133, /* '\' */ + 135, /* ']' */ + 130, /* '^' */ + -8, /* '_' */ + 135, /* '`' */ + 108, /* 'a' */ + 135, /* 'b' */ + 108, /* 'c' */ + 135, /* 'd' */ + 108, /* 'e' */ + 135, /* 'f' */ + 108, /* 'g' */ + 135, /* 'h' */ + 135, /* 'i' */ + 135, /* 'j' */ + 135, /* 'k' */ + 135, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 108, /* 'p' */ + 108, /* 'q' */ + 108, /* 'r' */ + 108, /* 's' */ + 126, /* 't' */ + 105, /* 'u' */ + 105, /* 'v' */ + 105, /* 'w' */ + 105, /* 'x' */ + 105, /* 'y' */ + 105, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 65, /* '~' */ + }, + + "Helvetica-Bold", + 0, + NO + }, { + /* width table for font HX */ + { + 46, /* ' ' */ + 55, /* '!' */ + 79, /* '"' */ + 93, /* '#' */ + 93, /* '$' */ + 148, /* '%' */ + 120, /* '&' */ + 46, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 65, /* '*' */ + 97, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 46, /* '/' */ + 93, /* '0' */ + 93, /* '1' */ + 93, /* '2' */ + 93, /* '3' */ + 93, /* '4' */ + 93, /* '5' */ + 93, /* '6' */ + 93, /* '7' */ + 93, /* '8' */ + 93, /* '9' */ + 55, /* ':' */ + 55, /* ';' */ + 97, /* '<' */ + 97, /* '=' */ + 97, /* '>' */ + 102, /* '?' */ + 162, /* '@' */ + 120, /* 'A' */ + 120, /* 'B' */ + 120, /* 'C' */ + 120, /* 'D' */ + 111, /* 'E' */ + 102, /* 'F' */ + 130, /* 'G' */ + 120, /* 'H' */ + 46, /* 'I' */ + 93, /* 'J' */ + 120, /* 'K' */ + 102, /* 'L' */ + 139, /* 'M' */ + 120, /* 'N' */ + 130, /* 'O' */ + 111, /* 'P' */ + 130, /* 'Q' */ + 120, /* 'R' */ + 111, /* 'S' */ + 102, /* 'T' */ + 120, /* 'U' */ + 111, /* 'V' */ + 157, /* 'W' */ + 111, /* 'X' */ + 111, /* 'Y' */ + 102, /* 'Z' */ + 55, /* '[' */ + 46, /* '\' */ + 55, /* ']' */ + 97, /* '^' */ + 93, /* '_' */ + 46, /* '`' */ + 93, /* 'a' */ + 102, /* 'b' */ + 93, /* 'c' */ + 102, /* 'd' */ + 93, /* 'e' */ + 55, /* 'f' */ + 102, /* 'g' */ + 102, /* 'h' */ + 46, /* 'i' */ + 46, /* 'j' */ + 93, /* 'k' */ + 46, /* 'l' */ + 148, /* 'm' */ + 102, /* 'n' */ + 102, /* 'o' */ + 102, /* 'p' */ + 102, /* 'q' */ + 65, /* 'r' */ + 93, /* 's' */ + 55, /* 't' */ + 102, /* 'u' */ + 93, /* 'v' */ + 130, /* 'w' */ + 93, /* 'x' */ + 93, /* 'y' */ + 83, /* 'z' */ + 65, /* '{' */ + 47, /* '|' */ + 65, /* '}' */ + 97, /* '~' */ + }, + /* height table for font HX */ + { + 153, /* ' ' */ + 149, /* '!' */ + 149, /* '"' */ + 149, /* '#' */ + 176, /* '$' */ + 149, /* '%' */ + 152, /* '&' */ + 149, /* ''' */ + 182, /* '(' */ + 182, /* ')' */ + 149, /* '*' */ + 109, /* '+' */ + 81, /* ',' */ + 82, /* '-' */ + 52, /* '.' */ + 149, /* '/' */ + 152, /* '0' */ + 146, /* '1' */ + 149, /* '2' */ + 152, /* '3' */ + 146, /* '4' */ + 152, /* '5' */ + 152, /* '6' */ + 149, /* '7' */ + 152, /* '8' */ + 152, /* '9' */ + 116, /* ':' */ + 145, /* ';' */ + 108, /* '<' */ + 96, /* '=' */ + 108, /* '>' */ + 152, /* '?' */ + 174, /* '@' */ + 149, /* 'A' */ + 149, /* 'B' */ + 155, /* 'C' */ + 149, /* 'D' */ + 149, /* 'E' */ + 149, /* 'F' */ + 155, /* 'G' */ + 149, /* 'H' */ + 149, /* 'I' */ + 152, /* 'J' */ + 149, /* 'K' */ + 149, /* 'L' */ + 149, /* 'M' */ + 149, /* 'N' */ + 155, /* 'O' */ + 149, /* 'P' */ + 161, /* 'Q' */ + 149, /* 'R' */ + 155, /* 'S' */ + 149, /* 'T' */ + 152, /* 'U' */ + 149, /* 'V' */ + 149, /* 'W' */ + 149, /* 'X' */ + 149, /* 'Y' */ + 149, /* 'Z' */ + 181, /* '[' */ + 150, /* '\' */ + 181, /* ']' */ + 144, /* '^' */ + 38, /* '_' */ + 149, /* '`' */ + 125, /* 'a' */ + 152, /* 'b' */ + 125, /* 'c' */ + 152, /* 'd' */ + 125, /* 'e' */ + 149, /* 'f' */ + 158, /* 'g' */ + 149, /* 'h' */ + 149, /* 'i' */ + 185, /* 'j' */ + 149, /* 'k' */ + 149, /* 'l' */ + 122, /* 'm' */ + 122, /* 'n' */ + 125, /* 'o' */ + 158, /* 'p' */ + 158, /* 'q' */ + 122, /* 'r' */ + 125, /* 's' */ + 143, /* 't' */ + 122, /* 'u' */ + 119, /* 'v' */ + 119, /* 'w' */ + 119, /* 'x' */ + 158, /* 'y' */ + 119, /* 'z' */ + 181, /* '{' */ + 182, /* '|' */ + 181, /* '}' */ + 79, /* '~' */ + }, + /* ascent table for font HX */ + { + 108, /* ' ' */ + 135, /* '!' */ + 135, /* '"' */ + 130, /* '#' */ + 141, /* '$' */ + 132, /* '%' */ + 135, /* '&' */ + 135, /* ''' */ + 135, /* '(' */ + 135, /* ')' */ + 135, /* '*' */ + 93, /* '+' */ + 38, /* ',' */ + 68, /* '-' */ + 38, /* '.' */ + 133, /* '/' */ + 136, /* '0' */ + 132, /* '1' */ + 136, /* '2' */ + 136, /* '3' */ + 132, /* '4' */ + 135, /* '5' */ + 135, /* '6' */ + 135, /* '7' */ + 136, /* '8' */ + 136, /* '9' */ + 102, /* ':' */ + 102, /* ';' */ + 93, /* '<' */ + 82, /* '=' */ + 93, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 135, /* 'A' */ + 135, /* 'B' */ + 138, /* 'C' */ + 135, /* 'D' */ + 135, /* 'E' */ + 135, /* 'F' */ + 138, /* 'G' */ + 135, /* 'H' */ + 135, /* 'I' */ + 135, /* 'J' */ + 135, /* 'K' */ + 135, /* 'L' */ + 135, /* 'M' */ + 135, /* 'N' */ + 138, /* 'O' */ + 135, /* 'P' */ + 138, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 135, /* 'T' */ + 135, /* 'U' */ + 135, /* 'V' */ + 135, /* 'W' */ + 135, /* 'X' */ + 135, /* 'Y' */ + 135, /* 'Z' */ + 135, /* '[' */ + 132, /* '\' */ + 135, /* ']' */ + 130, /* '^' */ + 2, /* '_' */ + 135, /* '`' */ + 108, /* 'a' */ + 135, /* 'b' */ + 108, /* 'c' */ + 135, /* 'd' */ + 108, /* 'e' */ + 135, /* 'f' */ + 108, /* 'g' */ + 135, /* 'h' */ + 135, /* 'i' */ + 135, /* 'j' */ + 135, /* 'k' */ + 135, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 108, /* 'p' */ + 108, /* 'q' */ + 108, /* 'r' */ + 108, /* 's' */ + 126, /* 't' */ + 105, /* 'u' */ + 105, /* 'v' */ + 105, /* 'w' */ + 105, /* 'x' */ + 105, /* 'y' */ + 105, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 65, /* '~' */ + }, + + "Helvetica-BoldOblique", + 0, + YES + }, { + /* width table for font BR */ + { + 53, /* ' ' */ + 50, /* '!' */ + 63, /* '"' */ + 103, /* '#' */ + 103, /* '$' */ + 150, /* '%' */ + 133, /* '&' */ + 37, /* ''' */ + 50, /* '(' */ + 50, /* ')' */ + 73, /* '*' */ + 100, /* '+' */ + 53, /* ',' */ + 67, /* '-' */ + 53, /* '.' */ + 100, /* '/' */ + 103, /* '0' */ + 103, /* '1' */ + 103, /* '2' */ + 103, /* '3' */ + 103, /* '4' */ + 103, /* '5' */ + 103, /* '6' */ + 103, /* '7' */ + 103, /* '8' */ + 103, /* '9' */ + 53, /* ':' */ + 53, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 90, /* '?' */ + 137, /* '@' */ + 113, /* 'A' */ + 123, /* 'B' */ + 123, /* 'C' */ + 133, /* 'D' */ + 120, /* 'E' */ + 107, /* 'F' */ + 133, /* 'G' */ + 133, /* 'H' */ + 57, /* 'I' */ + 100, /* 'J' */ + 120, /* 'K' */ + 100, /* 'L' */ + 153, /* 'M' */ + 123, /* 'N' */ + 133, /* 'O' */ + 103, /* 'P' */ + 137, /* 'Q' */ + 120, /* 'R' */ + 110, /* 'S' */ + 103, /* 'T' */ + 130, /* 'U' */ + 117, /* 'V' */ + 160, /* 'W' */ + 120, /* 'X' */ + 107, /* 'Y' */ + 107, /* 'Z' */ + 50, /* '[' */ + 100, /* '\' */ + 50, /* ']' */ + 100, /* '^' */ + 83, /* '_' */ + 37, /* '`' */ + 97, /* 'a' */ + 103, /* 'b' */ + 87, /* 'c' */ + 103, /* 'd' */ + 87, /* 'e' */ + 53, /* 'f' */ + 90, /* 'g' */ + 110, /* 'h' */ + 50, /* 'i' */ + 50, /* 'j' */ + 103, /* 'k' */ + 50, /* 'l' */ + 157, /* 'm' */ + 110, /* 'n' */ + 93, /* 'o' */ + 103, /* 'p' */ + 97, /* 'q' */ + 73, /* 'r' */ + 87, /* 's' */ + 63, /* 't' */ + 113, /* 'u' */ + 87, /* 'v' */ + 130, /* 'w' */ + 93, /* 'x' */ + 90, /* 'y' */ + 80, /* 'z' */ + 47, /* '{' */ + 100, /* '|' */ + 47, /* '}' */ + 100, /* '~' */ + }, + /* height table for font BR */ + { + 153, /* ' ' */ + 148, /* '!' */ + 146, /* '"' */ + 139, /* '#' */ + 178, /* '$' */ + 148, /* '%' */ + 148, /* '&' */ + 146, /* ''' */ + 172, /* '(' */ + 172, /* ')' */ + 146, /* '*' */ + 127, /* '+' */ + 66, /* ',' */ + 76, /* '-' */ + 49, /* '.' */ + 171, /* '/' */ + 148, /* '0' */ + 142, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 142, /* '4' */ + 150, /* '5' */ + 148, /* '6' */ + 142, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 114, /* ':' */ + 131, /* ';' */ + 128, /* '<' */ + 109, /* '=' */ + 128, /* '>' */ + 148, /* '?' */ + 148, /* '@' */ + 142, /* 'A' */ + 142, /* 'B' */ + 148, /* 'C' */ + 142, /* 'D' */ + 142, /* 'E' */ + 142, /* 'F' */ + 148, /* 'G' */ + 142, /* 'H' */ + 142, /* 'I' */ + 144, /* 'J' */ + 142, /* 'K' */ + 142, /* 'L' */ + 142, /* 'M' */ + 142, /* 'N' */ + 148, /* 'O' */ + 142, /* 'P' */ + 178, /* 'Q' */ + 142, /* 'R' */ + 148, /* 'S' */ + 142, /* 'T' */ + 144, /* 'U' */ + 142, /* 'V' */ + 142, /* 'W' */ + 142, /* 'X' */ + 142, /* 'Y' */ + 142, /* 'Z' */ + 168, /* '[' */ + 147, /* '\' */ + 169, /* ']' */ + 148, /* '^' */ + 38, /* '_' */ + 143, /* '`' */ + 114, /* 'a' */ + 149, /* 'b' */ + 114, /* 'c' */ + 149, /* 'd' */ + 114, /* 'e' */ + 149, /* 'f' */ + 161, /* 'g' */ + 147, /* 'h' */ + 136, /* 'i' */ + 174, /* 'j' */ + 147, /* 'k' */ + 147, /* 'l' */ + 112, /* 'm' */ + 112, /* 'n' */ + 114, /* 'o' */ + 151, /* 'p' */ + 151, /* 'q' */ + 112, /* 'r' */ + 114, /* 's' */ + 141, /* 't' */ + 111, /* 'u' */ + 109, /* 'v' */ + 109, /* 'w' */ + 109, /* 'x' */ + 148, /* 'y' */ + 109, /* 'z' */ + 171, /* '{' */ + 148, /* '|' */ + 171, /* '}' */ + 83, /* '~' */ + }, + /* ascent table for font BR */ + { + 108, /* ' ' */ + 132, /* '!' */ + 132, /* '"' */ + 125, /* '#' */ + 146, /* '$' */ + 132, /* '%' */ + 132, /* '&' */ + 132, /* ''' */ + 133, /* '(' */ + 133, /* ')' */ + 132, /* '*' */ + 113, /* '+' */ + 33, /* ',' */ + 62, /* '-' */ + 33, /* '.' */ + 133, /* '/' */ + 132, /* '0' */ + 128, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 128, /* '4' */ + 133, /* '5' */ + 132, /* '6' */ + 128, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 98, /* ':' */ + 98, /* ';' */ + 114, /* '<' */ + 95, /* '=' */ + 114, /* '>' */ + 132, /* '?' */ + 132, /* '@' */ + 128, /* 'A' */ + 128, /* 'B' */ + 132, /* 'C' */ + 128, /* 'D' */ + 128, /* 'E' */ + 128, /* 'F' */ + 132, /* 'G' */ + 128, /* 'H' */ + 128, /* 'I' */ + 128, /* 'J' */ + 128, /* 'K' */ + 128, /* 'L' */ + 128, /* 'M' */ + 128, /* 'N' */ + 132, /* 'O' */ + 128, /* 'P' */ + 132, /* 'Q' */ + 128, /* 'R' */ + 132, /* 'S' */ + 128, /* 'T' */ + 128, /* 'U' */ + 128, /* 'V' */ + 128, /* 'W' */ + 128, /* 'X' */ + 128, /* 'Y' */ + 128, /* 'Z' */ + 132, /* '[' */ + 133, /* '\' */ + 132, /* ']' */ + 134, /* '^' */ + -2, /* '_' */ + 130, /* '`' */ + 98, /* 'a' */ + 133, /* 'b' */ + 98, /* 'c' */ + 133, /* 'd' */ + 98, /* 'e' */ + 135, /* 'f' */ + 108, /* 'g' */ + 133, /* 'h' */ + 122, /* 'i' */ + 122, /* 'j' */ + 133, /* 'k' */ + 133, /* 'l' */ + 98, /* 'm' */ + 98, /* 'n' */ + 98, /* 'o' */ + 98, /* 'p' */ + 98, /* 'q' */ + 98, /* 'r' */ + 98, /* 's' */ + 125, /* 't' */ + 95, /* 'u' */ + 95, /* 'v' */ + 95, /* 'w' */ + 95, /* 'x' */ + 95, /* 'y' */ + 95, /* 'z' */ + 137, /* '{' */ + 134, /* '|' */ + 137, /* '}' */ + 69, /* '~' */ + }, + + "Bookman-Light", + 0, + NO + }, { + /* width table for font BI */ + { + 50, /* ' ' */ + 53, /* '!' */ + 60, /* '"' */ + 103, /* '#' */ + 103, /* '$' */ + 133, /* '%' */ + 137, /* '&' */ + 47, /* ''' */ + 47, /* '(' */ + 47, /* ')' */ + 73, /* '*' */ + 100, /* '+' */ + 50, /* ',' */ + 53, /* '-' */ + 50, /* '.' */ + 100, /* '/' */ + 103, /* '0' */ + 103, /* '1' */ + 103, /* '2' */ + 103, /* '3' */ + 103, /* '4' */ + 103, /* '5' */ + 103, /* '6' */ + 103, /* '7' */ + 103, /* '8' */ + 103, /* '9' */ + 50, /* ':' */ + 50, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 90, /* '?' */ + 130, /* '@' */ + 117, /* 'A' */ + 120, /* 'B' */ + 120, /* 'C' */ + 123, /* 'D' */ + 113, /* 'E' */ + 103, /* 'F' */ + 127, /* 'G' */ + 133, /* 'H' */ + 53, /* 'I' */ + 93, /* 'J' */ + 120, /* 'K' */ + 97, /* 'L' */ + 143, /* 'M' */ + 120, /* 'N' */ + 127, /* 'O' */ + 100, /* 'P' */ + 130, /* 'Q' */ + 117, /* 'R' */ + 107, /* 'S' */ + 100, /* 'T' */ + 120, /* 'U' */ + 113, /* 'V' */ + 160, /* 'W' */ + 117, /* 'X' */ + 110, /* 'Y' */ + 97, /* 'Z' */ + 43, /* '[' */ + 100, /* '\' */ + 43, /* ']' */ + 100, /* '^' */ + 83, /* '_' */ + 47, /* '`' */ + 103, /* 'a' */ + 100, /* 'b' */ + 80, /* 'c' */ + 107, /* 'd' */ + 90, /* 'e' */ + 57, /* 'f' */ + 93, /* 'g' */ + 103, /* 'h' */ + 47, /* 'i' */ + 47, /* 'j' */ + 100, /* 'k' */ + 47, /* 'l' */ + 147, /* 'm' */ + 103, /* 'n' */ + 90, /* 'o' */ + 100, /* 'p' */ + 93, /* 'q' */ + 67, /* 'r' */ + 90, /* 's' */ + 57, /* 't' */ + 103, /* 'u' */ + 90, /* 'v' */ + 147, /* 'w' */ + 90, /* 'x' */ + 100, /* 'y' */ + 87, /* 'z' */ + 60, /* '{' */ + 100, /* '|' */ + 63, /* '}' */ + 100, /* '~' */ + }, + /* height table for font BI */ + { + 153, /* ' ' */ + 148, /* '!' */ + 146, /* '"' */ + 139, /* '#' */ + 169, /* '$' */ + 148, /* '%' */ + 148, /* '&' */ + 146, /* ''' */ + 167, /* '(' */ + 167, /* ')' */ + 146, /* '*' */ + 127, /* '+' */ + 66, /* ',' */ + 76, /* '-' */ + 50, /* '.' */ + 167, /* '/' */ + 148, /* '0' */ + 142, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 142, /* '4' */ + 144, /* '5' */ + 148, /* '6' */ + 142, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 114, /* ':' */ + 131, /* ';' */ + 128, /* '<' */ + 109, /* '=' */ + 128, /* '>' */ + 148, /* '?' */ + 148, /* '@' */ + 142, /* 'A' */ + 142, /* 'B' */ + 148, /* 'C' */ + 142, /* 'D' */ + 142, /* 'E' */ + 142, /* 'F' */ + 148, /* 'G' */ + 142, /* 'H' */ + 142, /* 'I' */ + 144, /* 'J' */ + 142, /* 'K' */ + 142, /* 'L' */ + 142, /* 'M' */ + 142, /* 'N' */ + 148, /* 'O' */ + 142, /* 'P' */ + 178, /* 'Q' */ + 142, /* 'R' */ + 148, /* 'S' */ + 142, /* 'T' */ + 144, /* 'U' */ + 142, /* 'V' */ + 142, /* 'W' */ + 142, /* 'X' */ + 142, /* 'Y' */ + 142, /* 'Z' */ + 171, /* '[' */ + 147, /* '\' */ + 169, /* ']' */ + 148, /* '^' */ + 38, /* '_' */ + 143, /* '`' */ + 114, /* 'a' */ + 149, /* 'b' */ + 114, /* 'c' */ + 149, /* 'd' */ + 114, /* 'e' */ + 184, /* 'f' */ + 148, /* 'g' */ + 149, /* 'h' */ + 141, /* 'i' */ + 174, /* 'j' */ + 149, /* 'k' */ + 149, /* 'l' */ + 114, /* 'm' */ + 114, /* 'n' */ + 114, /* 'o' */ + 148, /* 'p' */ + 148, /* 'q' */ + 112, /* 'r' */ + 114, /* 's' */ + 141, /* 't' */ + 111, /* 'u' */ + 114, /* 'v' */ + 114, /* 'w' */ + 114, /* 'x' */ + 144, /* 'y' */ + 114, /* 'z' */ + 179, /* '{' */ + 148, /* '|' */ + 179, /* '}' */ + 83, /* '~' */ + }, + /* ascent table for font BI */ + { + 108, /* ' ' */ + 132, /* '!' */ + 132, /* '"' */ + 125, /* '#' */ + 141, /* '$' */ + 132, /* '%' */ + 132, /* '&' */ + 132, /* ''' */ + 133, /* '(' */ + 133, /* ')' */ + 132, /* '*' */ + 113, /* '+' */ + 33, /* ',' */ + 62, /* '-' */ + 34, /* '.' */ + 133, /* '/' */ + 132, /* '0' */ + 128, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 128, /* '4' */ + 128, /* '5' */ + 132, /* '6' */ + 128, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 98, /* ':' */ + 98, /* ';' */ + 114, /* '<' */ + 95, /* '=' */ + 114, /* '>' */ + 132, /* '?' */ + 132, /* '@' */ + 128, /* 'A' */ + 128, /* 'B' */ + 132, /* 'C' */ + 128, /* 'D' */ + 128, /* 'E' */ + 128, /* 'F' */ + 132, /* 'G' */ + 128, /* 'H' */ + 128, /* 'I' */ + 128, /* 'J' */ + 128, /* 'K' */ + 128, /* 'L' */ + 128, /* 'M' */ + 128, /* 'N' */ + 132, /* 'O' */ + 128, /* 'P' */ + 132, /* 'Q' */ + 128, /* 'R' */ + 132, /* 'S' */ + 128, /* 'T' */ + 128, /* 'U' */ + 128, /* 'V' */ + 128, /* 'W' */ + 128, /* 'X' */ + 128, /* 'Y' */ + 128, /* 'Z' */ + 135, /* '[' */ + 133, /* '\' */ + 133, /* ']' */ + 134, /* '^' */ + -2, /* '_' */ + 130, /* '`' */ + 98, /* 'a' */ + 133, /* 'b' */ + 98, /* 'c' */ + 133, /* 'd' */ + 98, /* 'e' */ + 135, /* 'f' */ + 98, /* 'g' */ + 133, /* 'h' */ + 125, /* 'i' */ + 125, /* 'j' */ + 133, /* 'k' */ + 133, /* 'l' */ + 98, /* 'm' */ + 98, /* 'n' */ + 98, /* 'o' */ + 98, /* 'p' */ + 98, /* 'q' */ + 98, /* 'r' */ + 98, /* 's' */ + 125, /* 't' */ + 95, /* 'u' */ + 98, /* 'v' */ + 98, /* 'w' */ + 98, /* 'x' */ + 95, /* 'y' */ + 98, /* 'z' */ + 139, /* '{' */ + 134, /* '|' */ + 139, /* '}' */ + 69, /* '~' */ + }, + + "Bookman-LightItalic", + 0, + YES + }, { + /* width table for font BB */ + { + 57, /* ' ' */ + 60, /* '!' */ + 70, /* '"' */ + 110, /* '#' */ + 110, /* '$' */ + 157, /* '%' */ + 133, /* '&' */ + 53, /* ''' */ + 53, /* '(' */ + 53, /* ')' */ + 77, /* '*' */ + 100, /* '+' */ + 57, /* ',' */ + 60, /* '-' */ + 57, /* '.' */ + 100, /* '/' */ + 110, /* '0' */ + 110, /* '1' */ + 110, /* '2' */ + 110, /* '3' */ + 110, /* '4' */ + 110, /* '5' */ + 110, /* '6' */ + 110, /* '7' */ + 110, /* '8' */ + 110, /* '9' */ + 57, /* ':' */ + 57, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 110, /* '?' */ + 137, /* '@' */ + 120, /* 'A' */ + 120, /* 'B' */ + 123, /* 'C' */ + 130, /* 'D' */ + 120, /* 'E' */ + 113, /* 'F' */ + 130, /* 'G' */ + 137, /* 'H' */ + 67, /* 'I' */ + 107, /* 'J' */ + 133, /* 'K' */ + 107, /* 'L' */ + 157, /* 'M' */ + 123, /* 'N' */ + 133, /* 'O' */ + 110, /* 'P' */ + 133, /* 'Q' */ + 130, /* 'R' */ + 110, /* 'S' */ + 117, /* 'T' */ + 123, /* 'U' */ + 120, /* 'V' */ + 157, /* 'W' */ + 130, /* 'X' */ + 117, /* 'Y' */ + 107, /* 'Z' */ + 50, /* '[' */ + 100, /* '\' */ + 50, /* ']' */ + 100, /* '^' */ + 83, /* '_' */ + 53, /* '`' */ + 97, /* 'a' */ + 100, /* 'b' */ + 97, /* 'c' */ + 107, /* 'd' */ + 97, /* 'e' */ + 63, /* 'f' */ + 97, /* 'g' */ + 113, /* 'h' */ + 60, /* 'i' */ + 57, /* 'j' */ + 110, /* 'k' */ + 57, /* 'l' */ + 167, /* 'm' */ + 113, /* 'n' */ + 103, /* 'o' */ + 107, /* 'p' */ + 103, /* 'q' */ + 77, /* 'r' */ + 87, /* 's' */ + 77, /* 't' */ + 110, /* 'u' */ + 100, /* 'v' */ + 133, /* 'w' */ + 100, /* 'x' */ + 103, /* 'y' */ + 93, /* 'z' */ + 53, /* '{' */ + 100, /* '|' */ + 53, /* '}' */ + 100, /* '~' */ + }, + /* height table for font BB */ + { + 153, /* ' ' */ + 148, /* '!' */ + 146, /* '"' */ + 142, /* '#' */ + 181, /* '$' */ + 148, /* '%' */ + 148, /* '&' */ + 146, /* ''' */ + 176, /* '(' */ + 176, /* ')' */ + 146, /* '*' */ + 127, /* '+' */ + 76, /* ',' */ + 79, /* '-' */ + 58, /* '.' */ + 171, /* '/' */ + 148, /* '0' */ + 142, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 142, /* '4' */ + 151, /* '5' */ + 148, /* '6' */ + 142, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 118, /* ':' */ + 136, /* ';' */ + 135, /* '<' */ + 112, /* '=' */ + 135, /* '>' */ + 148, /* '?' */ + 148, /* '@' */ + 142, /* 'A' */ + 142, /* 'B' */ + 148, /* 'C' */ + 142, /* 'D' */ + 142, /* 'E' */ + 142, /* 'F' */ + 148, /* 'G' */ + 142, /* 'H' */ + 142, /* 'I' */ + 144, /* 'J' */ + 142, /* 'K' */ + 142, /* 'L' */ + 142, /* 'M' */ + 142, /* 'N' */ + 148, /* 'O' */ + 142, /* 'P' */ + 181, /* 'Q' */ + 142, /* 'R' */ + 148, /* 'S' */ + 142, /* 'T' */ + 144, /* 'U' */ + 142, /* 'V' */ + 142, /* 'W' */ + 142, /* 'X' */ + 142, /* 'Y' */ + 142, /* 'Z' */ + 171, /* '[' */ + 149, /* '\' */ + 171, /* ']' */ + 148, /* '^' */ + 38, /* '_' */ + 143, /* '`' */ + 118, /* 'a' */ + 151, /* 'b' */ + 118, /* 'c' */ + 151, /* 'd' */ + 118, /* 'e' */ + 149, /* 'f' */ + 168, /* 'g' */ + 148, /* 'h' */ + 149, /* 'i' */ + 188, /* 'j' */ + 148, /* 'k' */ + 148, /* 'l' */ + 116, /* 'm' */ + 116, /* 'n' */ + 118, /* 'o' */ + 151, /* 'p' */ + 151, /* 'q' */ + 116, /* 'r' */ + 118, /* 's' */ + 140, /* 't' */ + 114, /* 'u' */ + 112, /* 'v' */ + 112, /* 'w' */ + 112, /* 'x' */ + 151, /* 'y' */ + 112, /* 'z' */ + 171, /* '{' */ + 148, /* '|' */ + 171, /* '}' */ + 102, /* '~' */ + }, + /* ascent table for font BB */ + { + 108, /* ' ' */ + 132, /* '!' */ + 132, /* '"' */ + 128, /* '#' */ + 148, /* '$' */ + 132, /* '%' */ + 132, /* '&' */ + 132, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 132, /* '*' */ + 113, /* '+' */ + 42, /* ',' */ + 65, /* '-' */ + 42, /* '.' */ + 134, /* '/' */ + 132, /* '0' */ + 128, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 128, /* '4' */ + 135, /* '5' */ + 132, /* '6' */ + 128, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 102, /* ':' */ + 102, /* ';' */ + 121, /* '<' */ + 98, /* '=' */ + 121, /* '>' */ + 132, /* '?' */ + 132, /* '@' */ + 128, /* 'A' */ + 128, /* 'B' */ + 132, /* 'C' */ + 128, /* 'D' */ + 128, /* 'E' */ + 128, /* 'F' */ + 132, /* 'G' */ + 128, /* 'H' */ + 128, /* 'I' */ + 128, /* 'J' */ + 128, /* 'K' */ + 128, /* 'L' */ + 128, /* 'M' */ + 128, /* 'N' */ + 132, /* 'O' */ + 128, /* 'P' */ + 132, /* 'Q' */ + 128, /* 'R' */ + 132, /* 'S' */ + 128, /* 'T' */ + 128, /* 'U' */ + 128, /* 'V' */ + 128, /* 'W' */ + 128, /* 'X' */ + 128, /* 'Y' */ + 128, /* 'Z' */ + 135, /* '[' */ + 135, /* '\' */ + 135, /* ']' */ + 134, /* '^' */ + -2, /* '_' */ + 130, /* '`' */ + 102, /* 'a' */ + 135, /* 'b' */ + 102, /* 'c' */ + 135, /* 'd' */ + 102, /* 'e' */ + 135, /* 'f' */ + 112, /* 'g' */ + 135, /* 'h' */ + 135, /* 'i' */ + 136, /* 'j' */ + 135, /* 'k' */ + 135, /* 'l' */ + 102, /* 'm' */ + 102, /* 'n' */ + 102, /* 'o' */ + 102, /* 'p' */ + 102, /* 'q' */ + 102, /* 'r' */ + 102, /* 's' */ + 124, /* 't' */ + 98, /* 'u' */ + 98, /* 'v' */ + 98, /* 'w' */ + 98, /* 'x' */ + 98, /* 'y' */ + 98, /* 'z' */ + 134, /* '{' */ + 134, /* '|' */ + 134, /* '}' */ + 88, /* '~' */ + }, + + "Bookman-Demi", + 0, + NO + }, { + /* width table for font BX */ + { + 57, /* ' ' */ + 53, /* '!' */ + 63, /* '"' */ + 113, /* '#' */ + 113, /* '$' */ + 147, /* '%' */ + 163, /* '&' */ + 53, /* ''' */ + 43, /* '(' */ + 43, /* ')' */ + 77, /* '*' */ + 100, /* '+' */ + 57, /* ',' */ + 47, /* '-' */ + 57, /* '.' */ + 60, /* '/' */ + 113, /* '0' */ + 113, /* '1' */ + 113, /* '2' */ + 113, /* '3' */ + 113, /* '4' */ + 113, /* '5' */ + 113, /* '6' */ + 113, /* '7' */ + 113, /* '8' */ + 113, /* '9' */ + 57, /* ':' */ + 57, /* ';' */ + 103, /* '<' */ + 100, /* '=' */ + 103, /* '>' */ + 103, /* '?' */ + 130, /* '@' */ + 120, /* 'A' */ + 120, /* 'B' */ + 117, /* 'C' */ + 127, /* 'D' */ + 120, /* 'E' */ + 110, /* 'F' */ + 127, /* 'G' */ + 133, /* 'H' */ + 63, /* 'I' */ + 103, /* 'J' */ + 130, /* 'K' */ + 107, /* 'L' */ + 143, /* 'M' */ + 123, /* 'N' */ + 127, /* 'O' */ + 107, /* 'P' */ + 127, /* 'Q' */ + 123, /* 'R' */ + 117, /* 'S' */ + 117, /* 'T' */ + 123, /* 'U' */ + 110, /* 'V' */ + 167, /* 'W' */ + 123, /* 'X' */ + 110, /* 'Y' */ + 113, /* 'Z' */ + 43, /* '[' */ + 97, /* '\' */ + 43, /* ']' */ + 103, /* '^' */ + 83, /* '_' */ + 53, /* '`' */ + 113, /* 'a' */ + 100, /* 'b' */ + 93, /* 'c' */ + 113, /* 'd' */ + 93, /* 'e' */ + 70, /* 'f' */ + 103, /* 'g' */ + 117, /* 'h' */ + 63, /* 'i' */ + 53, /* 'j' */ + 117, /* 'k' */ + 63, /* 'l' */ + 160, /* 'm' */ + 113, /* 'n' */ + 100, /* 'o' */ + 110, /* 'p' */ + 103, /* 'q' */ + 83, /* 'r' */ + 90, /* 's' */ + 73, /* 't' */ + 113, /* 'u' */ + 90, /* 'v' */ + 143, /* 'w' */ + 103, /* 'x' */ + 100, /* 'y' */ + 93, /* 'z' */ + 50, /* '{' */ + 103, /* '|' */ + 50, /* '}' */ + 103, /* '~' */ + }, + /* height table for font BX */ + { + 153, /* ' ' */ + 148, /* '!' */ + 142, /* '"' */ + 142, /* '#' */ + 186, /* '$' */ + 148, /* '%' */ + 148, /* '&' */ + 146, /* ''' */ + 170, /* '(' */ + 170, /* ')' */ + 146, /* '*' */ + 127, /* '+' */ + 79, /* ',' */ + 79, /* '-' */ + 59, /* '.' */ + 170, /* '/' */ + 148, /* '0' */ + 142, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 142, /* '4' */ + 144, /* '5' */ + 148, /* '6' */ + 142, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 118, /* ':' */ + 137, /* ';' */ + 135, /* '<' */ + 112, /* '=' */ + 135, /* '>' */ + 148, /* '?' */ + 148, /* '@' */ + 142, /* 'A' */ + 142, /* 'B' */ + 148, /* 'C' */ + 142, /* 'D' */ + 142, /* 'E' */ + 142, /* 'F' */ + 148, /* 'G' */ + 142, /* 'H' */ + 142, /* 'I' */ + 144, /* 'J' */ + 142, /* 'K' */ + 142, /* 'L' */ + 142, /* 'M' */ + 142, /* 'N' */ + 148, /* 'O' */ + 142, /* 'P' */ + 181, /* 'Q' */ + 142, /* 'R' */ + 148, /* 'S' */ + 142, /* 'T' */ + 144, /* 'U' */ + 142, /* 'V' */ + 142, /* 'W' */ + 142, /* 'X' */ + 142, /* 'Y' */ + 142, /* 'Z' */ + 171, /* '[' */ + 151, /* '\' */ + 171, /* ']' */ + 148, /* '^' */ + 38, /* '_' */ + 143, /* '`' */ + 118, /* 'a' */ + 152, /* 'b' */ + 118, /* 'c' */ + 152, /* 'd' */ + 118, /* 'e' */ + 188, /* 'f' */ + 148, /* 'g' */ + 152, /* 'h' */ + 157, /* 'i' */ + 190, /* 'j' */ + 152, /* 'k' */ + 152, /* 'l' */ + 118, /* 'm' */ + 118, /* 'n' */ + 118, /* 'o' */ + 151, /* 'p' */ + 151, /* 'q' */ + 116, /* 'r' */ + 118, /* 's' */ + 140, /* 't' */ + 114, /* 'u' */ + 118, /* 'v' */ + 118, /* 'w' */ + 118, /* 'x' */ + 144, /* 'y' */ + 118, /* 'z' */ + 170, /* '{' */ + 148, /* '|' */ + 170, /* '}' */ + 102, /* '~' */ + }, + /* ascent table for font BX */ + { + 108, /* ' ' */ + 132, /* '!' */ + 128, /* '"' */ + 128, /* '#' */ + 145, /* '$' */ + 132, /* '%' */ + 132, /* '&' */ + 132, /* ''' */ + 132, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 113, /* '+' */ + 44, /* ',' */ + 65, /* '-' */ + 43, /* '.' */ + 132, /* '/' */ + 132, /* '0' */ + 128, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 128, /* '4' */ + 128, /* '5' */ + 132, /* '6' */ + 128, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 102, /* ':' */ + 102, /* ';' */ + 121, /* '<' */ + 98, /* '=' */ + 121, /* '>' */ + 132, /* '?' */ + 132, /* '@' */ + 128, /* 'A' */ + 128, /* 'B' */ + 132, /* 'C' */ + 128, /* 'D' */ + 128, /* 'E' */ + 128, /* 'F' */ + 132, /* 'G' */ + 128, /* 'H' */ + 128, /* 'I' */ + 128, /* 'J' */ + 128, /* 'K' */ + 128, /* 'L' */ + 128, /* 'M' */ + 128, /* 'N' */ + 132, /* 'O' */ + 128, /* 'P' */ + 132, /* 'Q' */ + 128, /* 'R' */ + 132, /* 'S' */ + 128, /* 'T' */ + 128, /* 'U' */ + 128, /* 'V' */ + 128, /* 'W' */ + 128, /* 'X' */ + 128, /* 'Y' */ + 128, /* 'Z' */ + 132, /* '[' */ + 137, /* '\' */ + 132, /* ']' */ + 134, /* '^' */ + -2, /* '_' */ + 130, /* '`' */ + 102, /* 'a' */ + 136, /* 'b' */ + 102, /* 'c' */ + 136, /* 'd' */ + 102, /* 'e' */ + 138, /* 'f' */ + 102, /* 'g' */ + 136, /* 'h' */ + 141, /* 'i' */ + 141, /* 'j' */ + 136, /* 'k' */ + 136, /* 'l' */ + 102, /* 'm' */ + 102, /* 'n' */ + 102, /* 'o' */ + 102, /* 'p' */ + 102, /* 'q' */ + 102, /* 'r' */ + 102, /* 's' */ + 124, /* 't' */ + 98, /* 'u' */ + 102, /* 'v' */ + 102, /* 'w' */ + 102, /* 'x' */ + 98, /* 'y' */ + 102, /* 'z' */ + 132, /* '{' */ + 134, /* '|' */ + 132, /* '}' */ + 88, /* '~' */ + }, + + "Bookman-DemiItalic", + 0, + YES + }, { + /* width table for font NR */ + { + 46, /* ' ' */ + 49, /* '!' */ + 65, /* '"' */ + 93, /* '#' */ + 93, /* '$' */ + 139, /* '%' */ + 136, /* '&' */ + 34, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 46, /* '/' */ + 93, /* '0' */ + 93, /* '1' */ + 93, /* '2' */ + 93, /* '3' */ + 93, /* '4' */ + 93, /* '5' */ + 93, /* '6' */ + 93, /* '7' */ + 93, /* '8' */ + 93, /* '9' */ + 46, /* ':' */ + 46, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 74, /* '?' */ + 123, /* '@' */ + 120, /* 'A' */ + 120, /* 'B' */ + 120, /* 'C' */ + 130, /* 'D' */ + 120, /* 'E' */ + 111, /* 'F' */ + 130, /* 'G' */ + 139, /* 'H' */ + 68, /* 'I' */ + 93, /* 'J' */ + 130, /* 'K' */ + 111, /* 'L' */ + 157, /* 'M' */ + 136, /* 'N' */ + 130, /* 'O' */ + 111, /* 'P' */ + 130, /* 'Q' */ + 120, /* 'R' */ + 105, /* 'S' */ + 111, /* 'T' */ + 136, /* 'U' */ + 120, /* 'V' */ + 163, /* 'W' */ + 117, /* 'X' */ + 117, /* 'Y' */ + 102, /* 'Z' */ + 55, /* '[' */ + 101, /* '\' */ + 55, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 34, /* '`' */ + 93, /* 'a' */ + 93, /* 'b' */ + 74, /* 'c' */ + 96, /* 'd' */ + 83, /* 'e' */ + 55, /* 'f' */ + 89, /* 'g' */ + 102, /* 'h' */ + 52, /* 'i' */ + 49, /* 'j' */ + 99, /* 'k' */ + 52, /* 'l' */ + 148, /* 'm' */ + 102, /* 'n' */ + 83, /* 'o' */ + 96, /* 'p' */ + 93, /* 'q' */ + 74, /* 'r' */ + 77, /* 's' */ + 65, /* 't' */ + 102, /* 'u' */ + 89, /* 'v' */ + 130, /* 'w' */ + 89, /* 'x' */ + 89, /* 'y' */ + 80, /* 'z' */ + 55, /* '{' */ + 101, /* '|' */ + 55, /* '}' */ + 101, /* '~' */ + }, + /* height table for font NR */ + { + 153, /* ' ' */ + 154, /* '!' */ + 152, /* '"' */ + 142, /* '#' */ + 183, /* '$' */ + 149, /* '%' */ + 154, /* '&' */ + 152, /* ''' */ + 171, /* '(' */ + 171, /* ')' */ + 152, /* '*' */ + 112, /* '+' */ + 76, /* ',' */ + 72, /* '-' */ + 48, /* '.' */ + 154, /* '/' */ + 148, /* '0' */ + 145, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 145, /* '4' */ + 147, /* '5' */ + 148, /* '6' */ + 147, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 111, /* ':' */ + 136, /* ';' */ + 118, /* '<' */ + 92, /* '=' */ + 118, /* '>' */ + 154, /* '?' */ + 154, /* '@' */ + 152, /* 'A' */ + 149, /* 'B' */ + 154, /* 'C' */ + 149, /* 'D' */ + 149, /* 'E' */ + 149, /* 'F' */ + 154, /* 'G' */ + 149, /* 'H' */ + 149, /* 'I' */ + 151, /* 'J' */ + 149, /* 'K' */ + 149, /* 'L' */ + 149, /* 'M' */ + 151, /* 'N' */ + 154, /* 'O' */ + 149, /* 'P' */ + 184, /* 'Q' */ + 151, /* 'R' */ + 154, /* 'S' */ + 149, /* 'T' */ + 151, /* 'U' */ + 151, /* 'V' */ + 151, /* 'W' */ + 149, /* 'X' */ + 149, /* 'Y' */ + 149, /* 'Z' */ + 168, /* '[' */ + 152, /* '\' */ + 168, /* ']' */ + 149, /* '^' */ + 38, /* '_' */ + 150, /* '`' */ + 111, /* 'a' */ + 153, /* 'b' */ + 111, /* 'c' */ + 153, /* 'd' */ + 111, /* 'e' */ + 152, /* 'f' */ + 144, /* 'g' */ + 151, /* 'h' */ + 149, /* 'i' */ + 181, /* 'j' */ + 151, /* 'k' */ + 151, /* 'l' */ + 109, /* 'm' */ + 109, /* 'n' */ + 111, /* 'o' */ + 144, /* 'p' */ + 144, /* 'q' */ + 109, /* 'r' */ + 111, /* 's' */ + 141, /* 't' */ + 108, /* 'u' */ + 108, /* 'v' */ + 108, /* 'w' */ + 106, /* 'x' */ + 138, /* 'y' */ + 106, /* 'z' */ + 167, /* '{' */ + 149, /* '|' */ + 167, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font NR */ + { + 108, /* ' ' */ + 138, /* '!' */ + 138, /* '"' */ + 128, /* '#' */ + 147, /* '$' */ + 135, /* '%' */ + 138, /* '&' */ + 138, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 138, /* '*' */ + 98, /* '+' */ + 32, /* ',' */ + 58, /* '-' */ + 32, /* '.' */ + 138, /* '/' */ + 132, /* '0' */ + 131, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 131, /* '4' */ + 131, /* '5' */ + 132, /* '6' */ + 131, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 95, /* ':' */ + 92, /* ';' */ + 101, /* '<' */ + 78, /* '=' */ + 101, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 138, /* 'A' */ + 135, /* 'B' */ + 138, /* 'C' */ + 135, /* 'D' */ + 135, /* 'E' */ + 135, /* 'F' */ + 138, /* 'G' */ + 135, /* 'H' */ + 135, /* 'I' */ + 135, /* 'J' */ + 135, /* 'K' */ + 135, /* 'L' */ + 135, /* 'M' */ + 135, /* 'N' */ + 138, /* 'O' */ + 135, /* 'P' */ + 138, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 135, /* 'T' */ + 135, /* 'U' */ + 135, /* 'V' */ + 135, /* 'W' */ + 135, /* 'X' */ + 135, /* 'Y' */ + 135, /* 'Z' */ + 135, /* '[' */ + 138, /* '\' */ + 135, /* ']' */ + 135, /* '^' */ + 2, /* '_' */ + 137, /* '`' */ + 95, /* 'a' */ + 137, /* 'b' */ + 95, /* 'c' */ + 137, /* 'd' */ + 95, /* 'e' */ + 138, /* 'f' */ + 98, /* 'g' */ + 137, /* 'h' */ + 135, /* 'i' */ + 135, /* 'j' */ + 137, /* 'k' */ + 137, /* 'l' */ + 95, /* 'm' */ + 95, /* 'n' */ + 95, /* 'o' */ + 95, /* 'p' */ + 95, /* 'q' */ + 95, /* 'r' */ + 95, /* 's' */ + 125, /* 't' */ + 92, /* 'u' */ + 92, /* 'v' */ + 92, /* 'w' */ + 92, /* 'x' */ + 92, /* 'y' */ + 92, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 68, /* '~' */ + }, + + "NewCenturySchlbk-Roman", + 0, + NO + }, { + /* width table for font NI */ + { + 46, /* ' ' */ + 55, /* '!' */ + 67, /* '"' */ + 93, /* '#' */ + 93, /* '$' */ + 139, /* '%' */ + 142, /* '&' */ + 34, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 101, /* '/' */ + 93, /* '0' */ + 93, /* '1' */ + 93, /* '2' */ + 93, /* '3' */ + 93, /* '4' */ + 93, /* '5' */ + 93, /* '6' */ + 93, /* '7' */ + 93, /* '8' */ + 93, /* '9' */ + 46, /* ':' */ + 46, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 74, /* '?' */ + 124, /* '@' */ + 117, /* 'A' */ + 120, /* 'B' */ + 120, /* 'C' */ + 130, /* 'D' */ + 120, /* 'E' */ + 111, /* 'F' */ + 130, /* 'G' */ + 139, /* 'H' */ + 68, /* 'I' */ + 102, /* 'J' */ + 123, /* 'K' */ + 111, /* 'L' */ + 157, /* 'M' */ + 136, /* 'N' */ + 130, /* 'O' */ + 111, /* 'P' */ + 130, /* 'Q' */ + 123, /* 'R' */ + 111, /* 'S' */ + 114, /* 'T' */ + 136, /* 'U' */ + 117, /* 'V' */ + 154, /* 'W' */ + 117, /* 'X' */ + 114, /* 'Y' */ + 111, /* 'Z' */ + 55, /* '[' */ + 101, /* '\' */ + 55, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 34, /* '`' */ + 96, /* 'a' */ + 93, /* 'b' */ + 74, /* 'c' */ + 102, /* 'd' */ + 74, /* 'e' */ + 55, /* 'f' */ + 89, /* 'g' */ + 102, /* 'h' */ + 55, /* 'i' */ + 52, /* 'j' */ + 93, /* 'k' */ + 55, /* 'l' */ + 148, /* 'm' */ + 102, /* 'n' */ + 83, /* 'o' */ + 96, /* 'p' */ + 93, /* 'q' */ + 74, /* 'r' */ + 74, /* 's' */ + 59, /* 't' */ + 102, /* 'u' */ + 86, /* 'v' */ + 130, /* 'w' */ + 83, /* 'x' */ + 83, /* 'y' */ + 77, /* 'z' */ + 55, /* '{' */ + 101, /* '|' */ + 55, /* '}' */ + 101, /* '~' */ + }, + /* height table for font NI */ + { + 153, /* ' ' */ + 154, /* '!' */ + 152, /* '"' */ + 142, /* '#' */ + 182, /* '$' */ + 149, /* '%' */ + 154, /* '&' */ + 146, /* ''' */ + 171, /* '(' */ + 171, /* ')' */ + 145, /* '*' */ + 112, /* '+' */ + 74, /* ',' */ + 72, /* '-' */ + 48, /* '.' */ + 167, /* '/' */ + 148, /* '0' */ + 146, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 146, /* '4' */ + 147, /* '5' */ + 148, /* '6' */ + 147, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 108, /* ':' */ + 133, /* ';' */ + 118, /* '<' */ + 92, /* '=' */ + 118, /* '>' */ + 154, /* '?' */ + 154, /* '@' */ + 152, /* 'A' */ + 149, /* 'B' */ + 154, /* 'C' */ + 149, /* 'D' */ + 149, /* 'E' */ + 149, /* 'F' */ + 154, /* 'G' */ + 149, /* 'H' */ + 149, /* 'I' */ + 151, /* 'J' */ + 149, /* 'K' */ + 149, /* 'L' */ + 149, /* 'M' */ + 151, /* 'N' */ + 154, /* 'O' */ + 149, /* 'P' */ + 184, /* 'Q' */ + 151, /* 'R' */ + 154, /* 'S' */ + 149, /* 'T' */ + 151, /* 'U' */ + 151, /* 'V' */ + 151, /* 'W' */ + 149, /* 'X' */ + 149, /* 'Y' */ + 149, /* 'Z' */ + 168, /* '[' */ + 146, /* '\' */ + 168, /* ']' */ + 149, /* '^' */ + 34, /* '_' */ + 151, /* '`' */ + 108, /* 'a' */ + 153, /* 'b' */ + 108, /* 'c' */ + 153, /* 'd' */ + 108, /* 'e' */ + 186, /* 'f' */ + 144, /* 'g' */ + 153, /* 'h' */ + 148, /* 'i' */ + 181, /* 'j' */ + 153, /* 'k' */ + 153, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 138, /* 'p' */ + 138, /* 'q' */ + 106, /* 'r' */ + 107, /* 's' */ + 134, /* 't' */ + 108, /* 'u' */ + 108, /* 'v' */ + 108, /* 'w' */ + 108, /* 'x' */ + 138, /* 'y' */ + 108, /* 'z' */ + 167, /* '{' */ + 149, /* '|' */ + 167, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font NI */ + { + 108, /* ' ' */ + 138, /* '!' */ + 138, /* '"' */ + 128, /* '#' */ + 146, /* '$' */ + 135, /* '%' */ + 138, /* '&' */ + 132, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 131, /* '*' */ + 98, /* '+' */ + 32, /* ',' */ + 58, /* '-' */ + 32, /* '.' */ + 135, /* '/' */ + 132, /* '0' */ + 132, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 132, /* '4' */ + 131, /* '5' */ + 132, /* '6' */ + 131, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 92, /* ':' */ + 92, /* ';' */ + 101, /* '<' */ + 78, /* '=' */ + 101, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 138, /* 'A' */ + 135, /* 'B' */ + 138, /* 'C' */ + 135, /* 'D' */ + 135, /* 'E' */ + 135, /* 'F' */ + 138, /* 'G' */ + 135, /* 'H' */ + 135, /* 'I' */ + 135, /* 'J' */ + 135, /* 'K' */ + 135, /* 'L' */ + 135, /* 'M' */ + 135, /* 'N' */ + 138, /* 'O' */ + 135, /* 'P' */ + 138, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 135, /* 'T' */ + 135, /* 'U' */ + 135, /* 'V' */ + 135, /* 'W' */ + 135, /* 'X' */ + 135, /* 'Y' */ + 135, /* 'Z' */ + 135, /* '[' */ + 132, /* '\' */ + 135, /* ']' */ + 135, /* '^' */ + 2, /* '_' */ + 137, /* '`' */ + 92, /* 'a' */ + 137, /* 'b' */ + 92, /* 'c' */ + 137, /* 'd' */ + 92, /* 'e' */ + 138, /* 'f' */ + 98, /* 'g' */ + 137, /* 'h' */ + 132, /* 'i' */ + 132, /* 'j' */ + 137, /* 'k' */ + 137, /* 'l' */ + 92, /* 'm' */ + 92, /* 'n' */ + 92, /* 'o' */ + 92, /* 'p' */ + 92, /* 'q' */ + 92, /* 'r' */ + 91, /* 's' */ + 117, /* 't' */ + 92, /* 'u' */ + 92, /* 'v' */ + 92, /* 'w' */ + 92, /* 'x' */ + 92, /* 'y' */ + 92, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 68, /* '~' */ + }, + + "NewCenturySchlbk-Italic", + 0, + YES + }, { + /* width table for font NB */ + { + 48, /* ' ' */ + 49, /* '!' */ + 55, /* '"' */ + 96, /* '#' */ + 96, /* '$' */ + 139, /* '%' */ + 142, /* '&' */ + 40, /* ''' */ + 65, /* '(' */ + 65, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 46, /* ',' */ + 55, /* '-' */ + 46, /* '.' */ + 46, /* '/' */ + 96, /* '0' */ + 96, /* '1' */ + 96, /* '2' */ + 96, /* '3' */ + 96, /* '4' */ + 96, /* '5' */ + 96, /* '6' */ + 96, /* '7' */ + 96, /* '8' */ + 96, /* '9' */ + 46, /* ':' */ + 46, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 83, /* '?' */ + 124, /* '@' */ + 126, /* 'A' */ + 130, /* 'B' */ + 130, /* 'C' */ + 139, /* 'D' */ + 126, /* 'E' */ + 120, /* 'F' */ + 139, /* 'G' */ + 145, /* 'H' */ + 74, /* 'I' */ + 108, /* 'J' */ + 136, /* 'K' */ + 120, /* 'L' */ + 163, /* 'M' */ + 139, /* 'N' */ + 139, /* 'O' */ + 126, /* 'P' */ + 139, /* 'Q' */ + 136, /* 'R' */ + 111, /* 'S' */ + 120, /* 'T' */ + 139, /* 'U' */ + 126, /* 'V' */ + 163, /* 'W' */ + 120, /* 'X' */ + 120, /* 'Y' */ + 111, /* 'Z' */ + 65, /* '[' */ + 101, /* '\' */ + 65, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 40, /* '`' */ + 102, /* 'a' */ + 108, /* 'b' */ + 93, /* 'c' */ + 111, /* 'd' */ + 96, /* 'e' */ + 65, /* 'f' */ + 102, /* 'g' */ + 114, /* 'h' */ + 62, /* 'i' */ + 59, /* 'j' */ + 111, /* 'k' */ + 59, /* 'l' */ + 160, /* 'm' */ + 114, /* 'n' */ + 102, /* 'o' */ + 111, /* 'p' */ + 108, /* 'q' */ + 86, /* 'r' */ + 83, /* 's' */ + 71, /* 't' */ + 114, /* 'u' */ + 102, /* 'v' */ + 148, /* 'w' */ + 102, /* 'x' */ + 102, /* 'y' */ + 89, /* 'z' */ + 65, /* '{' */ + 101, /* '|' */ + 65, /* '}' */ + 101, /* '~' */ + }, + /* height table for font NB */ + { + 153, /* ' ' */ + 154, /* '!' */ + 152, /* '"' */ + 144, /* '#' */ + 184, /* '$' */ + 149, /* '%' */ + 154, /* '&' */ + 152, /* ''' */ + 170, /* '(' */ + 170, /* ')' */ + 152, /* '*' */ + 112, /* '+' */ + 87, /* ',' */ + 79, /* '-' */ + 59, /* '.' */ + 154, /* '/' */ + 148, /* '0' */ + 146, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 146, /* '4' */ + 148, /* '5' */ + 148, /* '6' */ + 148, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 111, /* ':' */ + 140, /* ';' */ + 120, /* '<' */ + 96, /* '=' */ + 120, /* '>' */ + 154, /* '?' */ + 154, /* '@' */ + 152, /* 'A' */ + 149, /* 'B' */ + 154, /* 'C' */ + 149, /* 'D' */ + 149, /* 'E' */ + 149, /* 'F' */ + 154, /* 'G' */ + 149, /* 'H' */ + 149, /* 'I' */ + 151, /* 'J' */ + 149, /* 'K' */ + 149, /* 'L' */ + 149, /* 'M' */ + 151, /* 'N' */ + 154, /* 'O' */ + 149, /* 'P' */ + 184, /* 'Q' */ + 151, /* 'R' */ + 154, /* 'S' */ + 149, /* 'T' */ + 151, /* 'U' */ + 151, /* 'V' */ + 151, /* 'W' */ + 149, /* 'X' */ + 149, /* 'Y' */ + 149, /* 'Z' */ + 168, /* '[' */ + 152, /* '\' */ + 168, /* ']' */ + 149, /* '^' */ + 44, /* '_' */ + 152, /* '`' */ + 111, /* 'a' */ + 153, /* 'b' */ + 111, /* 'c' */ + 153, /* 'd' */ + 111, /* 'e' */ + 152, /* 'f' */ + 154, /* 'g' */ + 151, /* 'h' */ + 152, /* 'i' */ + 188, /* 'j' */ + 151, /* 'k' */ + 151, /* 'l' */ + 109, /* 'm' */ + 109, /* 'n' */ + 111, /* 'o' */ + 144, /* 'p' */ + 144, /* 'q' */ + 109, /* 'r' */ + 111, /* 's' */ + 142, /* 't' */ + 109, /* 'u' */ + 108, /* 'v' */ + 108, /* 'w' */ + 106, /* 'x' */ + 138, /* 'y' */ + 106, /* 'z' */ + 167, /* '{' */ + 149, /* '|' */ + 167, /* '}' */ + 86, /* '~' */ + }, + /* ascent table for font NB */ + { + 108, /* ' ' */ + 138, /* '!' */ + 138, /* '"' */ + 131, /* '#' */ + 147, /* '$' */ + 135, /* '%' */ + 138, /* '&' */ + 138, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 138, /* '*' */ + 98, /* '+' */ + 42, /* ',' */ + 65, /* '-' */ + 43, /* '.' */ + 138, /* '/' */ + 132, /* '0' */ + 132, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 132, /* '4' */ + 132, /* '5' */ + 132, /* '6' */ + 132, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 95, /* ':' */ + 95, /* ';' */ + 102, /* '<' */ + 82, /* '=' */ + 102, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 138, /* 'A' */ + 135, /* 'B' */ + 138, /* 'C' */ + 135, /* 'D' */ + 135, /* 'E' */ + 135, /* 'F' */ + 138, /* 'G' */ + 135, /* 'H' */ + 135, /* 'I' */ + 135, /* 'J' */ + 135, /* 'K' */ + 135, /* 'L' */ + 135, /* 'M' */ + 135, /* 'N' */ + 138, /* 'O' */ + 135, /* 'P' */ + 138, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 135, /* 'T' */ + 135, /* 'U' */ + 135, /* 'V' */ + 135, /* 'W' */ + 135, /* 'X' */ + 135, /* 'Y' */ + 135, /* 'Z' */ + 135, /* '[' */ + 138, /* '\' */ + 135, /* ']' */ + 135, /* '^' */ + 5, /* '_' */ + 138, /* '`' */ + 95, /* 'a' */ + 137, /* 'b' */ + 95, /* 'c' */ + 137, /* 'd' */ + 95, /* 'e' */ + 138, /* 'f' */ + 105, /* 'g' */ + 137, /* 'h' */ + 138, /* 'i' */ + 138, /* 'j' */ + 137, /* 'k' */ + 137, /* 'l' */ + 95, /* 'm' */ + 95, /* 'n' */ + 95, /* 'o' */ + 95, /* 'p' */ + 95, /* 'q' */ + 95, /* 'r' */ + 95, /* 's' */ + 126, /* 't' */ + 93, /* 'u' */ + 92, /* 'v' */ + 92, /* 'w' */ + 92, /* 'x' */ + 92, /* 'y' */ + 92, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 72, /* '~' */ + }, + + "NewCenturySchlbk-Bold", + 0, + NO + }, { + /* width table for font NX */ + { + 48, /* ' ' */ + 55, /* '!' */ + 67, /* '"' */ + 96, /* '#' */ + 96, /* '$' */ + 148, /* '%' */ + 148, /* '&' */ + 43, /* ''' */ + 68, /* '(' */ + 68, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 48, /* ',' */ + 55, /* '-' */ + 48, /* '.' */ + 46, /* '/' */ + 96, /* '0' */ + 96, /* '1' */ + 96, /* '2' */ + 96, /* '3' */ + 96, /* '4' */ + 96, /* '5' */ + 96, /* '6' */ + 96, /* '7' */ + 96, /* '8' */ + 96, /* '9' */ + 48, /* ':' */ + 48, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 80, /* '?' */ + 124, /* '@' */ + 123, /* 'A' */ + 126, /* 'B' */ + 126, /* 'C' */ + 139, /* 'D' */ + 123, /* 'E' */ + 117, /* 'F' */ + 136, /* 'G' */ + 145, /* 'H' */ + 74, /* 'I' */ + 111, /* 'J' */ + 130, /* 'K' */ + 117, /* 'L' */ + 157, /* 'M' */ + 142, /* 'N' */ + 139, /* 'O' */ + 123, /* 'P' */ + 139, /* 'Q' */ + 133, /* 'R' */ + 114, /* 'S' */ + 120, /* 'T' */ + 139, /* 'U' */ + 123, /* 'V' */ + 157, /* 'W' */ + 123, /* 'X' */ + 117, /* 'Y' */ + 117, /* 'Z' */ + 68, /* '[' */ + 101, /* '\' */ + 68, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 43, /* '`' */ + 111, /* 'a' */ + 102, /* 'b' */ + 89, /* 'c' */ + 111, /* 'd' */ + 86, /* 'e' */ + 65, /* 'f' */ + 102, /* 'g' */ + 114, /* 'h' */ + 65, /* 'i' */ + 62, /* 'j' */ + 108, /* 'k' */ + 65, /* 'l' */ + 157, /* 'm' */ + 114, /* 'n' */ + 96, /* 'o' */ + 108, /* 'p' */ + 105, /* 'q' */ + 86, /* 'r' */ + 80, /* 's' */ + 68, /* 't' */ + 114, /* 'u' */ + 93, /* 'v' */ + 139, /* 'w' */ + 96, /* 'x' */ + 86, /* 'y' */ + 86, /* 'z' */ + 68, /* '{' */ + 101, /* '|' */ + 68, /* '}' */ + 101, /* '~' */ + }, + /* height table for font NX */ + { + 153, /* ' ' */ + 154, /* '!' */ + 152, /* '"' */ + 144, /* '#' */ + 184, /* '$' */ + 149, /* '%' */ + 154, /* '&' */ + 149, /* ''' */ + 170, /* '(' */ + 170, /* ')' */ + 152, /* '*' */ + 112, /* '+' */ + 85, /* ',' */ + 79, /* '-' */ + 56, /* '.' */ + 154, /* '/' */ + 148, /* '0' */ + 146, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 146, /* '4' */ + 148, /* '5' */ + 148, /* '6' */ + 147, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 111, /* ':' */ + 140, /* ';' */ + 120, /* '<' */ + 96, /* '=' */ + 120, /* '>' */ + 154, /* '?' */ + 154, /* '@' */ + 152, /* 'A' */ + 149, /* 'B' */ + 154, /* 'C' */ + 149, /* 'D' */ + 149, /* 'E' */ + 149, /* 'F' */ + 154, /* 'G' */ + 149, /* 'H' */ + 149, /* 'I' */ + 151, /* 'J' */ + 149, /* 'K' */ + 149, /* 'L' */ + 149, /* 'M' */ + 151, /* 'N' */ + 154, /* 'O' */ + 149, /* 'P' */ + 184, /* 'Q' */ + 151, /* 'R' */ + 154, /* 'S' */ + 149, /* 'T' */ + 151, /* 'U' */ + 151, /* 'V' */ + 151, /* 'W' */ + 149, /* 'X' */ + 149, /* 'Y' */ + 149, /* 'Z' */ + 168, /* '[' */ + 149, /* '\' */ + 168, /* ']' */ + 149, /* '^' */ + 38, /* '_' */ + 151, /* '`' */ + 111, /* 'a' */ + 154, /* 'b' */ + 111, /* 'c' */ + 154, /* 'd' */ + 111, /* 'e' */ + 186, /* 'f' */ + 149, /* 'g' */ + 154, /* 'h' */ + 154, /* 'i' */ + 184, /* 'j' */ + 154, /* 'k' */ + 154, /* 'l' */ + 111, /* 'm' */ + 111, /* 'n' */ + 111, /* 'o' */ + 141, /* 'p' */ + 141, /* 'q' */ + 109, /* 'r' */ + 111, /* 's' */ + 138, /* 't' */ + 111, /* 'u' */ + 111, /* 'v' */ + 111, /* 'w' */ + 111, /* 'x' */ + 144, /* 'y' */ + 111, /* 'z' */ + 167, /* '{' */ + 149, /* '|' */ + 167, /* '}' */ + 86, /* '~' */ + }, + /* ascent table for font NX */ + { + 108, /* ' ' */ + 138, /* '!' */ + 138, /* '"' */ + 131, /* '#' */ + 146, /* '$' */ + 135, /* '%' */ + 138, /* '&' */ + 135, /* ''' */ + 137, /* '(' */ + 137, /* ')' */ + 138, /* '*' */ + 98, /* '+' */ + 40, /* ',' */ + 65, /* '-' */ + 40, /* '.' */ + 138, /* '/' */ + 132, /* '0' */ + 132, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 132, /* '4' */ + 132, /* '5' */ + 132, /* '6' */ + 131, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 95, /* ':' */ + 95, /* ';' */ + 102, /* '<' */ + 82, /* '=' */ + 102, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 138, /* 'A' */ + 135, /* 'B' */ + 138, /* 'C' */ + 135, /* 'D' */ + 135, /* 'E' */ + 135, /* 'F' */ + 138, /* 'G' */ + 135, /* 'H' */ + 135, /* 'I' */ + 135, /* 'J' */ + 135, /* 'K' */ + 135, /* 'L' */ + 135, /* 'M' */ + 135, /* 'N' */ + 138, /* 'O' */ + 135, /* 'P' */ + 138, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 135, /* 'T' */ + 135, /* 'U' */ + 135, /* 'V' */ + 135, /* 'W' */ + 135, /* 'X' */ + 135, /* 'Y' */ + 135, /* 'Z' */ + 135, /* '[' */ + 135, /* '\' */ + 135, /* ']' */ + 135, /* '^' */ + 2, /* '_' */ + 137, /* '`' */ + 95, /* 'a' */ + 138, /* 'b' */ + 95, /* 'c' */ + 138, /* 'd' */ + 95, /* 'e' */ + 138, /* 'f' */ + 103, /* 'g' */ + 138, /* 'h' */ + 138, /* 'i' */ + 138, /* 'j' */ + 138, /* 'k' */ + 138, /* 'l' */ + 95, /* 'm' */ + 95, /* 'n' */ + 95, /* 'o' */ + 95, /* 'p' */ + 95, /* 'q' */ + 95, /* 'r' */ + 95, /* 's' */ + 122, /* 't' */ + 95, /* 'u' */ + 95, /* 'v' */ + 95, /* 'w' */ + 95, /* 'x' */ + 95, /* 'y' */ + 95, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 72, /* '~' */ + }, + + "NewCenturySchlbk-BoldItalic", + 0, + YES + }, { + /* width table for font PR */ + { + 42, /* ' ' */ + 46, /* '!' */ + 62, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 140, /* '%' */ + 130, /* '&' */ + 46, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 65, /* '*' */ + 101, /* '+' */ + 42, /* ',' */ + 55, /* '-' */ + 42, /* '.' */ + 101, /* '/' */ + 83, /* '0' */ + 83, /* '1' */ + 83, /* '2' */ + 83, /* '3' */ + 83, /* '4' */ + 83, /* '5' */ + 83, /* '6' */ + 83, /* '7' */ + 83, /* '8' */ + 83, /* '9' */ + 42, /* ':' */ + 42, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 74, /* '?' */ + 124, /* '@' */ + 130, /* 'A' */ + 102, /* 'B' */ + 118, /* 'C' */ + 129, /* 'D' */ + 102, /* 'E' */ + 93, /* 'F' */ + 127, /* 'G' */ + 139, /* 'H' */ + 56, /* 'I' */ + 55, /* 'J' */ + 121, /* 'K' */ + 102, /* 'L' */ + 158, /* 'M' */ + 138, /* 'N' */ + 131, /* 'O' */ + 101, /* 'P' */ + 131, /* 'Q' */ + 111, /* 'R' */ + 87, /* 'S' */ + 102, /* 'T' */ + 130, /* 'U' */ + 120, /* 'V' */ + 167, /* 'W' */ + 111, /* 'X' */ + 111, /* 'Y' */ + 111, /* 'Z' */ + 55, /* '[' */ + 101, /* '\' */ + 55, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 46, /* '`' */ + 83, /* 'a' */ + 92, /* 'b' */ + 74, /* 'c' */ + 102, /* 'd' */ + 80, /* 'e' */ + 55, /* 'f' */ + 93, /* 'g' */ + 97, /* 'h' */ + 48, /* 'i' */ + 39, /* 'j' */ + 93, /* 'k' */ + 48, /* 'l' */ + 147, /* 'm' */ + 97, /* 'n' */ + 91, /* 'o' */ + 100, /* 'p' */ + 93, /* 'q' */ + 66, /* 'r' */ + 71, /* 's' */ + 54, /* 't' */ + 100, /* 'u' */ + 94, /* 'v' */ + 139, /* 'w' */ + 86, /* 'x' */ + 93, /* 'y' */ + 83, /* 'z' */ + 55, /* '{' */ + 101, /* '|' */ + 55, /* '}' */ + 101, /* '~' */ + }, + /* height table for font PR */ + { + 153, /* ' ' */ + 142, /* '!' */ + 146, /* '"' */ + 142, /* '#' */ + 169, /* '$' */ + 149, /* '%' */ + 145, /* '&' */ + 146, /* ''' */ + 185, /* '(' */ + 185, /* ')' */ + 143, /* '*' */ + 113, /* '+' */ + 74, /* ',' */ + 76, /* '-' */ + 46, /* '.' */ + 169, /* '/' */ + 144, /* '0' */ + 144, /* '1' */ + 143, /* '2' */ + 144, /* '3' */ + 144, /* '4' */ + 145, /* '5' */ + 145, /* '6' */ + 143, /* '7' */ + 144, /* '8' */ + 146, /* '9' */ + 106, /* ':' */ + 131, /* ';' */ + 115, /* '<' */ + 92, /* '=' */ + 115, /* '>' */ + 142, /* '?' */ + 144, /* '@' */ + 146, /* 'A' */ + 143, /* 'B' */ + 148, /* 'C' */ + 143, /* 'D' */ + 143, /* 'E' */ + 143, /* 'F' */ + 148, /* 'G' */ + 143, /* 'H' */ + 143, /* 'I' */ + 175, /* 'J' */ + 143, /* 'K' */ + 143, /* 'L' */ + 145, /* 'M' */ + 146, /* 'N' */ + 148, /* 'O' */ + 143, /* 'P' */ + 175, /* 'Q' */ + 143, /* 'R' */ + 148, /* 'S' */ + 143, /* 'T' */ + 145, /* 'U' */ + 145, /* 'V' */ + 148, /* 'W' */ + 145, /* 'X' */ + 146, /* 'Y' */ + 144, /* 'Z' */ + 180, /* '[' */ + 149, /* '\' */ + 180, /* ']' */ + 143, /* '^' */ + 34, /* '_' */ + 146, /* '`' */ + 108, /* 'a' */ + 151, /* 'b' */ + 108, /* 'c' */ + 151, /* 'd' */ + 108, /* 'e' */ + 149, /* 'f' */ + 154, /* 'g' */ + 149, /* 'h' */ + 143, /* 'i' */ + 189, /* 'j' */ + 151, /* 'k' */ + 149, /* 'l' */ + 106, /* 'm' */ + 106, /* 'n' */ + 108, /* 'o' */ + 155, /* 'p' */ + 154, /* 'q' */ + 106, /* 'r' */ + 108, /* 's' */ + 133, /* 't' */ + 108, /* 'u' */ + 106, /* 'v' */ + 108, /* 'w' */ + 106, /* 'x' */ + 150, /* 'y' */ + 106, /* 'z' */ + 178, /* '{' */ + 149, /* '|' */ + 178, /* '}' */ + 85, /* '~' */ + }, + /* ascent table for font PR */ + { + 108, /* ' ' */ + 128, /* '!' */ + 132, /* '"' */ + 128, /* '#' */ + 136, /* '$' */ + 132, /* '%' */ + 128, /* '&' */ + 132, /* ''' */ + 135, /* '(' */ + 135, /* ')' */ + 129, /* '*' */ + 99, /* '+' */ + 34, /* ',' */ + 62, /* '-' */ + 32, /* '.' */ + 135, /* '/' */ + 128, /* '0' */ + 130, /* '1' */ + 128, /* '2' */ + 128, /* '3' */ + 130, /* '4' */ + 129, /* '5' */ + 129, /* '6' */ + 129, /* '7' */ + 128, /* '8' */ + 128, /* '9' */ + 92, /* ':' */ + 92, /* ';' */ + 101, /* '<' */ + 78, /* '=' */ + 101, /* '>' */ + 128, /* '?' */ + 128, /* '@' */ + 132, /* 'A' */ + 128, /* 'B' */ + 132, /* 'C' */ + 128, /* 'D' */ + 128, /* 'E' */ + 128, /* 'F' */ + 132, /* 'G' */ + 128, /* 'H' */ + 128, /* 'I' */ + 128, /* 'J' */ + 128, /* 'K' */ + 128, /* 'L' */ + 128, /* 'M' */ + 128, /* 'N' */ + 132, /* 'O' */ + 128, /* 'P' */ + 132, /* 'Q' */ + 128, /* 'R' */ + 132, /* 'S' */ + 129, /* 'T' */ + 128, /* 'U' */ + 129, /* 'V' */ + 132, /* 'W' */ + 131, /* 'X' */ + 131, /* 'Y' */ + 129, /* 'Z' */ + 135, /* '[' */ + 135, /* '\' */ + 135, /* ']' */ + 129, /* '^' */ + 2, /* '_' */ + 132, /* '`' */ + 92, /* 'a' */ + 135, /* 'b' */ + 92, /* 'c' */ + 135, /* 'd' */ + 92, /* 'e' */ + 135, /* 'f' */ + 92, /* 'g' */ + 135, /* 'h' */ + 128, /* 'i' */ + 128, /* 'j' */ + 135, /* 'k' */ + 135, /* 'l' */ + 92, /* 'm' */ + 92, /* 'n' */ + 92, /* 'o' */ + 92, /* 'p' */ + 92, /* 'q' */ + 92, /* 'r' */ + 92, /* 's' */ + 117, /* 't' */ + 92, /* 'u' */ + 90, /* 'v' */ + 92, /* 'w' */ + 92, /* 'x' */ + 90, /* 'y' */ + 92, /* 'z' */ + 135, /* '{' */ + 135, /* '|' */ + 135, /* '}' */ + 71, /* '~' */ + }, + + "Palatino-Roman", + 0, + NO + }, { + /* width table for font PI */ + { + 42, /* ' ' */ + 55, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 148, /* '%' */ + 130, /* '&' */ + 46, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 65, /* '*' */ + 101, /* '+' */ + 42, /* ',' */ + 55, /* '-' */ + 42, /* '.' */ + 49, /* '/' */ + 83, /* '0' */ + 83, /* '1' */ + 83, /* '2' */ + 83, /* '3' */ + 83, /* '4' */ + 83, /* '5' */ + 83, /* '6' */ + 83, /* '7' */ + 83, /* '8' */ + 83, /* '9' */ + 42, /* ':' */ + 42, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 83, /* '?' */ + 124, /* '@' */ + 120, /* 'A' */ + 102, /* 'B' */ + 111, /* 'C' */ + 130, /* 'D' */ + 102, /* 'E' */ + 93, /* 'F' */ + 120, /* 'G' */ + 130, /* 'H' */ + 55, /* 'I' */ + 55, /* 'J' */ + 111, /* 'K' */ + 93, /* 'L' */ + 157, /* 'M' */ + 130, /* 'N' */ + 130, /* 'O' */ + 102, /* 'P' */ + 130, /* 'Q' */ + 111, /* 'R' */ + 93, /* 'S' */ + 102, /* 'T' */ + 130, /* 'U' */ + 120, /* 'V' */ + 157, /* 'W' */ + 120, /* 'X' */ + 111, /* 'Y' */ + 111, /* 'Z' */ + 55, /* '[' */ + 101, /* '\' */ + 55, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 46, /* '`' */ + 74, /* 'a' */ + 77, /* 'b' */ + 68, /* 'c' */ + 83, /* 'd' */ + 65, /* 'e' */ + 46, /* 'f' */ + 83, /* 'g' */ + 83, /* 'h' */ + 46, /* 'i' */ + 46, /* 'j' */ + 74, /* 'k' */ + 46, /* 'l' */ + 130, /* 'm' */ + 93, /* 'n' */ + 74, /* 'o' */ + 83, /* 'p' */ + 77, /* 'q' */ + 65, /* 'r' */ + 65, /* 's' */ + 55, /* 't' */ + 93, /* 'u' */ + 83, /* 'v' */ + 120, /* 'w' */ + 83, /* 'x' */ + 83, /* 'y' */ + 74, /* 'z' */ + 55, /* '{' */ + 101, /* '|' */ + 55, /* '}' */ + 101, /* '~' */ + }, + /* height table for font PI */ + { + 153, /* ' ' */ + 152, /* '!' */ + 150, /* '"' */ + 142, /* '#' */ + 169, /* '$' */ + 148, /* '%' */ + 144, /* '&' */ + 150, /* ''' */ + 168, /* '(' */ + 168, /* ')' */ + 145, /* '*' */ + 112, /* '+' */ + 72, /* ',' */ + 76, /* '-' */ + 46, /* '.' */ + 170, /* '/' */ + 148, /* '0' */ + 145, /* '1' */ + 146, /* '2' */ + 148, /* '3' */ + 145, /* '4' */ + 145, /* '5' */ + 148, /* '6' */ + 143, /* '7' */ + 148, /* '8' */ + 148, /* '9' */ + 104, /* ':' */ + 128, /* ';' */ + 115, /* '<' */ + 92, /* '=' */ + 115, /* '>' */ + 148, /* '?' */ + 148, /* '@' */ + 146, /* 'A' */ + 143, /* 'B' */ + 148, /* 'C' */ + 142, /* 'D' */ + 143, /* 'E' */ + 143, /* 'F' */ + 148, /* 'G' */ + 142, /* 'H' */ + 142, /* 'I' */ + 178, /* 'J' */ + 143, /* 'K' */ + 142, /* 'L' */ + 144, /* 'M' */ + 145, /* 'N' */ + 148, /* 'O' */ + 143, /* 'P' */ + 178, /* 'Q' */ + 144, /* 'R' */ + 148, /* 'S' */ + 142, /* 'T' */ + 144, /* 'U' */ + 144, /* 'V' */ + 148, /* 'W' */ + 143, /* 'X' */ + 146, /* 'Y' */ + 144, /* 'Z' */ + 167, /* '[' */ + 150, /* '\' */ + 167, /* ']' */ + 143, /* '^' */ + 34, /* '_' */ + 150, /* '`' */ + 111, /* 'a' */ + 152, /* 'b' */ + 111, /* 'c' */ + 152, /* 'd' */ + 111, /* 'e' */ + 195, /* 'f' */ + 154, /* 'g' */ + 152, /* 'h' */ + 148, /* 'i' */ + 191, /* 'j' */ + 152, /* 'k' */ + 152, /* 'l' */ + 111, /* 'm' */ + 111, /* 'n' */ + 111, /* 'o' */ + 155, /* 'p' */ + 155, /* 'q' */ + 110, /* 'r' */ + 111, /* 's' */ + 138, /* 't' */ + 111, /* 'u' */ + 111, /* 'v' */ + 111, /* 'w' */ + 111, /* 'x' */ + 154, /* 'y' */ + 111, /* 'z' */ + 167, /* '{' */ + 150, /* '|' */ + 167, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font PI */ + { + 108, /* ' ' */ + 136, /* '!' */ + 136, /* '"' */ + 128, /* '#' */ + 136, /* '$' */ + 132, /* '%' */ + 128, /* '&' */ + 136, /* ''' */ + 136, /* '(' */ + 136, /* ')' */ + 132, /* '*' */ + 98, /* '+' */ + 34, /* ',' */ + 62, /* '-' */ + 33, /* '.' */ + 136, /* '/' */ + 132, /* '0' */ + 130, /* '1' */ + 132, /* '2' */ + 132, /* '3' */ + 130, /* '4' */ + 129, /* '5' */ + 132, /* '6' */ + 129, /* '7' */ + 132, /* '8' */ + 132, /* '9' */ + 90, /* ':' */ + 90, /* ';' */ + 101, /* '<' */ + 78, /* '=' */ + 101, /* '>' */ + 132, /* '?' */ + 132, /* '@' */ + 132, /* 'A' */ + 128, /* 'B' */ + 132, /* 'C' */ + 128, /* 'D' */ + 129, /* 'E' */ + 129, /* 'F' */ + 132, /* 'G' */ + 128, /* 'H' */ + 128, /* 'I' */ + 128, /* 'J' */ + 128, /* 'K' */ + 128, /* 'L' */ + 128, /* 'M' */ + 129, /* 'N' */ + 132, /* 'O' */ + 129, /* 'P' */ + 132, /* 'Q' */ + 129, /* 'R' */ + 132, /* 'S' */ + 128, /* 'T' */ + 128, /* 'U' */ + 128, /* 'V' */ + 132, /* 'W' */ + 128, /* 'X' */ + 132, /* 'Y' */ + 129, /* 'Z' */ + 136, /* '[' */ + 136, /* '\' */ + 136, /* ']' */ + 129, /* '^' */ + 2, /* '_' */ + 136, /* '`' */ + 95, /* 'a' */ + 136, /* 'b' */ + 95, /* 'c' */ + 136, /* 'd' */ + 95, /* 'e' */ + 136, /* 'f' */ + 95, /* 'g' */ + 136, /* 'h' */ + 132, /* 'i' */ + 132, /* 'j' */ + 136, /* 'k' */ + 136, /* 'l' */ + 95, /* 'm' */ + 95, /* 'n' */ + 95, /* 'o' */ + 95, /* 'p' */ + 95, /* 'q' */ + 95, /* 'r' */ + 95, /* 's' */ + 122, /* 't' */ + 95, /* 'u' */ + 95, /* 'v' */ + 95, /* 'w' */ + 95, /* 'x' */ + 95, /* 'y' */ + 95, /* 'z' */ + 136, /* '{' */ + 136, /* '|' */ + 136, /* '}' */ + 69, /* '~' */ + }, + + "Palatino-Italic", + 0, + YES + }, { + /* width table for font PB */ + { + 42, /* ' ' */ + 46, /* '!' */ + 67, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 148, /* '%' */ + 139, /* '&' */ + 46, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 74, /* '*' */ + 101, /* '+' */ + 42, /* ',' */ + 55, /* '-' */ + 42, /* '.' */ + 49, /* '/' */ + 83, /* '0' */ + 83, /* '1' */ + 83, /* '2' */ + 83, /* '3' */ + 83, /* '4' */ + 83, /* '5' */ + 83, /* '6' */ + 83, /* '7' */ + 83, /* '8' */ + 83, /* '9' */ + 42, /* ':' */ + 42, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 74, /* '?' */ + 124, /* '@' */ + 130, /* 'A' */ + 111, /* 'B' */ + 120, /* 'C' */ + 139, /* 'D' */ + 102, /* 'E' */ + 93, /* 'F' */ + 139, /* 'G' */ + 139, /* 'H' */ + 65, /* 'I' */ + 65, /* 'J' */ + 130, /* 'K' */ + 102, /* 'L' */ + 167, /* 'M' */ + 139, /* 'N' */ + 139, /* 'O' */ + 102, /* 'P' */ + 139, /* 'Q' */ + 120, /* 'R' */ + 102, /* 'S' */ + 111, /* 'T' */ + 130, /* 'U' */ + 130, /* 'V' */ + 167, /* 'W' */ + 111, /* 'X' */ + 111, /* 'Y' */ + 111, /* 'Z' */ + 55, /* '[' */ + 101, /* '\' */ + 55, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 46, /* '`' */ + 83, /* 'a' */ + 102, /* 'b' */ + 74, /* 'c' */ + 102, /* 'd' */ + 83, /* 'e' */ + 65, /* 'f' */ + 93, /* 'g' */ + 102, /* 'h' */ + 55, /* 'i' */ + 55, /* 'j' */ + 102, /* 'k' */ + 55, /* 'l' */ + 148, /* 'm' */ + 102, /* 'n' */ + 93, /* 'o' */ + 102, /* 'p' */ + 102, /* 'q' */ + 65, /* 'r' */ + 74, /* 's' */ + 55, /* 't' */ + 102, /* 'u' */ + 93, /* 'v' */ + 139, /* 'w' */ + 83, /* 'x' */ + 93, /* 'y' */ + 83, /* 'z' */ + 52, /* '{' */ + 101, /* '|' */ + 52, /* '}' */ + 101, /* '~' */ + }, + /* height table for font PB */ + { + 153, /* ' ' */ + 148, /* '!' */ + 146, /* '"' */ + 140, /* '#' */ + 167, /* '$' */ + 149, /* '%' */ + 144, /* '&' */ + 144, /* ''' */ + 166, /* '(' */ + 166, /* ')' */ + 144, /* '*' */ + 112, /* '+' */ + 79, /* ',' */ + 79, /* '-' */ + 54, /* '.' */ + 150, /* '/' */ + 141, /* '0' */ + 139, /* '1' */ + 139, /* '2' */ + 141, /* '3' */ + 140, /* '4' */ + 139, /* '5' */ + 140, /* '6' */ + 139, /* '7' */ + 141, /* '8' */ + 141, /* '9' */ + 104, /* ':' */ + 130, /* ';' */ + 118, /* '<' */ + 92, /* '=' */ + 118, /* '>' */ + 144, /* '?' */ + 144, /* '@' */ + 143, /* 'A' */ + 143, /* 'B' */ + 148, /* 'C' */ + 143, /* 'D' */ + 143, /* 'E' */ + 143, /* 'F' */ + 148, /* 'G' */ + 143, /* 'H' */ + 143, /* 'I' */ + 178, /* 'J' */ + 143, /* 'K' */ + 143, /* 'L' */ + 144, /* 'M' */ + 145, /* 'N' */ + 148, /* 'O' */ + 143, /* 'P' */ + 176, /* 'Q' */ + 143, /* 'R' */ + 148, /* 'S' */ + 143, /* 'T' */ + 144, /* 'U' */ + 142, /* 'V' */ + 142, /* 'W' */ + 144, /* 'X' */ + 144, /* 'Y' */ + 143, /* 'Z' */ + 166, /* '[' */ + 148, /* '\' */ + 166, /* ']' */ + 141, /* '^' */ + 34, /* '_' */ + 144, /* '`' */ + 108, /* 'a' */ + 150, /* 'b' */ + 108, /* 'c' */ + 150, /* 'd' */ + 108, /* 'e' */ + 148, /* 'f' */ + 148, /* 'g' */ + 148, /* 'h' */ + 146, /* 'i' */ + 191, /* 'j' */ + 148, /* 'k' */ + 148, /* 'l' */ + 107, /* 'm' */ + 107, /* 'n' */ + 108, /* 'o' */ + 149, /* 'p' */ + 148, /* 'q' */ + 106, /* 'r' */ + 108, /* 's' */ + 135, /* 't' */ + 108, /* 'u' */ + 104, /* 'v' */ + 106, /* 'w' */ + 107, /* 'x' */ + 150, /* 'y' */ + 105, /* 'z' */ + 168, /* '{' */ + 148, /* '|' */ + 168, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font PB */ + { + 108, /* ' ' */ + 132, /* '!' */ + 132, /* '"' */ + 126, /* '#' */ + 134, /* '$' */ + 133, /* '%' */ + 128, /* '&' */ + 130, /* ''' */ + 134, /* '(' */ + 134, /* ')' */ + 130, /* '*' */ + 98, /* '+' */ + 37, /* ',' */ + 65, /* '-' */ + 38, /* '.' */ + 134, /* '/' */ + 125, /* '0' */ + 126, /* '1' */ + 125, /* '2' */ + 125, /* '3' */ + 126, /* '4' */ + 123, /* '5' */ + 124, /* '6' */ + 125, /* '7' */ + 125, /* '8' */ + 125, /* '9' */ + 88, /* ':' */ + 88, /* ';' */ + 101, /* '<' */ + 78, /* '=' */ + 101, /* '>' */ + 128, /* '?' */ + 128, /* '@' */ + 128, /* 'A' */ + 128, /* 'B' */ + 132, /* 'C' */ + 128, /* 'D' */ + 128, /* 'E' */ + 128, /* 'F' */ + 132, /* 'G' */ + 128, /* 'H' */ + 128, /* 'I' */ + 128, /* 'J' */ + 128, /* 'K' */ + 128, /* 'L' */ + 128, /* 'M' */ + 128, /* 'N' */ + 132, /* 'O' */ + 128, /* 'P' */ + 132, /* 'Q' */ + 128, /* 'R' */ + 132, /* 'S' */ + 128, /* 'T' */ + 128, /* 'U' */ + 128, /* 'V' */ + 128, /* 'W' */ + 130, /* 'X' */ + 130, /* 'Y' */ + 128, /* 'Z' */ + 135, /* '[' */ + 134, /* '\' */ + 135, /* ']' */ + 127, /* '^' */ + 2, /* '_' */ + 130, /* '`' */ + 92, /* 'a' */ + 134, /* 'b' */ + 92, /* 'c' */ + 134, /* 'd' */ + 92, /* 'e' */ + 134, /* 'f' */ + 92, /* 'g' */ + 134, /* 'h' */ + 132, /* 'i' */ + 132, /* 'j' */ + 134, /* 'k' */ + 134, /* 'l' */ + 92, /* 'm' */ + 92, /* 'n' */ + 92, /* 'o' */ + 92, /* 'p' */ + 92, /* 'q' */ + 92, /* 'r' */ + 92, /* 's' */ + 119, /* 't' */ + 92, /* 'u' */ + 90, /* 'v' */ + 92, /* 'w' */ + 92, /* 'x' */ + 90, /* 'y' */ + 90, /* 'z' */ + 135, /* '{' */ + 134, /* '|' */ + 135, /* '}' */ + 68, /* '~' */ + }, + + "Palatino-Bold", + 0, + NO + }, { + /* width table for font PX */ + { + 42, /* ' ' */ + 55, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 148, /* '%' */ + 139, /* '&' */ + 46, /* ''' */ + 55, /* '(' */ + 55, /* ')' */ + 74, /* '*' */ + 101, /* '+' */ + 42, /* ',' */ + 65, /* '-' */ + 42, /* '.' */ + 52, /* '/' */ + 83, /* '0' */ + 83, /* '1' */ + 83, /* '2' */ + 83, /* '3' */ + 83, /* '4' */ + 83, /* '5' */ + 83, /* '6' */ + 83, /* '7' */ + 83, /* '8' */ + 83, /* '9' */ + 42, /* ':' */ + 42, /* ';' */ + 101, /* '<' */ + 101, /* '=' */ + 101, /* '>' */ + 74, /* '?' */ + 139, /* '@' */ + 120, /* 'A' */ + 111, /* 'B' */ + 114, /* 'C' */ + 130, /* 'D' */ + 102, /* 'E' */ + 93, /* 'F' */ + 130, /* 'G' */ + 130, /* 'H' */ + 65, /* 'I' */ + 65, /* 'J' */ + 120, /* 'K' */ + 102, /* 'L' */ + 157, /* 'M' */ + 130, /* 'N' */ + 139, /* 'O' */ + 111, /* 'P' */ + 139, /* 'Q' */ + 120, /* 'R' */ + 93, /* 'S' */ + 102, /* 'T' */ + 130, /* 'U' */ + 111, /* 'V' */ + 167, /* 'W' */ + 120, /* 'X' */ + 102, /* 'Y' */ + 111, /* 'Z' */ + 55, /* '[' */ + 101, /* '\' */ + 55, /* ']' */ + 101, /* '^' */ + 83, /* '_' */ + 46, /* '`' */ + 93, /* 'a' */ + 89, /* 'b' */ + 74, /* 'c' */ + 93, /* 'd' */ + 74, /* 'e' */ + 55, /* 'f' */ + 83, /* 'g' */ + 93, /* 'h' */ + 55, /* 'i' */ + 55, /* 'j' */ + 93, /* 'k' */ + 55, /* 'l' */ + 139, /* 'm' */ + 93, /* 'n' */ + 93, /* 'o' */ + 93, /* 'p' */ + 89, /* 'q' */ + 65, /* 'r' */ + 74, /* 's' */ + 65, /* 't' */ + 93, /* 'u' */ + 93, /* 'v' */ + 139, /* 'w' */ + 83, /* 'x' */ + 93, /* 'y' */ + 83, /* 'z' */ + 55, /* '{' */ + 101, /* '|' */ + 55, /* '}' */ + 101, /* '~' */ + }, + /* height table for font PX */ + { + 153, /* ' ' */ + 146, /* '!' */ + 148, /* '"' */ + 140, /* '#' */ + 169, /* '$' */ + 148, /* '%' */ + 148, /* '&' */ + 148, /* ''' */ + 170, /* '(' */ + 170, /* ')' */ + 144, /* '*' */ + 111, /* '+' */ + 80, /* ',' */ + 79, /* '-' */ + 52, /* '.' */ + 150, /* '/' */ + 144, /* '0' */ + 141, /* '1' */ + 143, /* '2' */ + 144, /* '3' */ + 142, /* '4' */ + 143, /* '5' */ + 144, /* '6' */ + 140, /* '7' */ + 144, /* '8' */ + 144, /* '9' */ + 104, /* ':' */ + 130, /* ';' */ + 118, /* '<' */ + 92, /* '=' */ + 118, /* '>' */ + 148, /* '?' */ + 144, /* '@' */ + 143, /* 'A' */ + 143, /* 'B' */ + 148, /* 'C' */ + 143, /* 'D' */ + 143, /* 'E' */ + 143, /* 'F' */ + 148, /* 'G' */ + 143, /* 'H' */ + 143, /* 'I' */ + 178, /* 'J' */ + 143, /* 'K' */ + 143, /* 'L' */ + 144, /* 'M' */ + 143, /* 'N' */ + 148, /* 'O' */ + 143, /* 'P' */ + 181, /* 'Q' */ + 143, /* 'R' */ + 148, /* 'S' */ + 143, /* 'T' */ + 144, /* 'U' */ + 142, /* 'V' */ + 146, /* 'W' */ + 143, /* 'X' */ + 146, /* 'Y' */ + 142, /* 'Z' */ + 165, /* '[' */ + 148, /* '\' */ + 165, /* ']' */ + 141, /* '^' */ + 34, /* '_' */ + 148, /* '`' */ + 108, /* 'a' */ + 151, /* 'b' */ + 108, /* 'c' */ + 151, /* 'd' */ + 108, /* 'e' */ + 194, /* 'f' */ + 151, /* 'g' */ + 151, /* 'h' */ + 148, /* 'i' */ + 191, /* 'j' */ + 151, /* 'k' */ + 151, /* 'l' */ + 108, /* 'm' */ + 108, /* 'n' */ + 108, /* 'o' */ + 151, /* 'p' */ + 151, /* 'q' */ + 108, /* 'r' */ + 108, /* 's' */ + 136, /* 't' */ + 108, /* 'u' */ + 108, /* 'v' */ + 108, /* 'w' */ + 108, /* 'x' */ + 151, /* 'y' */ + 108, /* 'z' */ + 165, /* '{' */ + 148, /* '|' */ + 165, /* '}' */ + 82, /* '~' */ + }, + /* ascent table for font PX */ + { + 108, /* ' ' */ + 130, /* '!' */ + 134, /* '"' */ + 126, /* '#' */ + 137, /* '$' */ + 132, /* '%' */ + 132, /* '&' */ + 134, /* ''' */ + 134, /* '(' */ + 134, /* ')' */ + 130, /* '*' */ + 97, /* '+' */ + 38, /* ',' */ + 65, /* '-' */ + 36, /* '.' */ + 134, /* '/' */ + 128, /* '0' */ + 127, /* '1' */ + 128, /* '2' */ + 128, /* '3' */ + 128, /* '4' */ + 126, /* '5' */ + 128, /* '6' */ + 126, /* '7' */ + 128, /* '8' */ + 128, /* '9' */ + 88, /* ':' */ + 88, /* ';' */ + 101, /* '<' */ + 78, /* '=' */ + 101, /* '>' */ + 132, /* '?' */ + 128, /* '@' */ + 128, /* 'A' */ + 128, /* 'B' */ + 132, /* 'C' */ + 128, /* 'D' */ + 128, /* 'E' */ + 128, /* 'F' */ + 132, /* 'G' */ + 128, /* 'H' */ + 128, /* 'I' */ + 128, /* 'J' */ + 128, /* 'K' */ + 128, /* 'L' */ + 128, /* 'M' */ + 128, /* 'N' */ + 132, /* 'O' */ + 128, /* 'P' */ + 132, /* 'Q' */ + 128, /* 'R' */ + 132, /* 'S' */ + 128, /* 'T' */ + 128, /* 'U' */ + 128, /* 'V' */ + 132, /* 'W' */ + 128, /* 'X' */ + 132, /* 'Y' */ + 128, /* 'Z' */ + 134, /* '[' */ + 134, /* '\' */ + 134, /* ']' */ + 127, /* '^' */ + 2, /* '_' */ + 134, /* '`' */ + 92, /* 'a' */ + 135, /* 'b' */ + 92, /* 'c' */ + 135, /* 'd' */ + 92, /* 'e' */ + 135, /* 'f' */ + 92, /* 'g' */ + 135, /* 'h' */ + 132, /* 'i' */ + 132, /* 'j' */ + 135, /* 'k' */ + 135, /* 'l' */ + 92, /* 'm' */ + 92, /* 'n' */ + 92, /* 'o' */ + 92, /* 'p' */ + 92, /* 'q' */ + 92, /* 'r' */ + 92, /* 's' */ + 120, /* 't' */ + 92, /* 'u' */ + 92, /* 'v' */ + 92, /* 'w' */ + 92, /* 'x' */ + 92, /* 'y' */ + 92, /* 'z' */ + 134, /* '{' */ + 134, /* '|' */ + 134, /* '}' */ + 68, /* '~' */ + }, + + "Palatino-BoldItalic", + 0, + YES + }, { +#ifdef EXTCHAR + /* width table for font XTR */ + { + 55, /* ' ' */ + 83, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 74, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 58, /* '+' */ + 74, /* ',' */ + 74, /* '-' */ + 74, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 148, /* ';' */ + 111, /* '<' */ + 46, /* '=' */ + 52, /* '>' */ + 102, /* '?' */ + 46, /* '@' */ + 120, /* 'A' */ + 83, /* 'B' */ + 148, /* 'C' */ + 120, /* 'D' */ + 46, /* 'E' */ + 83, /* 'F' */ + 120, /* 'G' */ + 74, /* 'H' */ + 120, /* 'I' */ + 74, /* 'J' */ + 120, /* 'K' */ + 74, /* 'L' */ + 120, /* 'M' */ + 74, /* 'N' */ + 120, /* 'O' */ + 74, /* 'P' */ + 120, /* 'Q' */ + 74, /* 'R' */ + 111, /* 'S' */ + 74, /* 'T' */ + 102, /* 'U' */ + 74, /* 'V' */ + 102, /* 'W' */ + 74, /* 'X' */ + 102, /* 'Y' */ + 74, /* 'Z' */ + 102, /* '[' */ + 74, /* '\' */ + 55, /* ']' */ + 46, /* '^' */ + 55, /* '_' */ + 46, /* '`' */ + 55, /* 'a' */ + 46, /* 'b' */ + 55, /* 'c' */ + 46, /* 'd' */ + 120, /* 'e' */ + 83, /* 'f' */ + 120, /* 'g' */ + 83, /* 'h' */ + 120, /* 'i' */ + 83, /* 'j' */ + 120, /* 'k' */ + 83, /* 'l' */ + 120, /* 'm' */ + 83, /* 'n' */ + 120, /* 'o' */ + 83, /* 'p' */ + 93, /* 'q' */ + 65, /* 'r' */ + 120, /* 's' */ + 83, /* 't' */ + 120, /* 'u' */ + 83, /* 'v' */ + 120, /* 'w' */ + 83, /* 'x' */ + 120, /* 'y' */ + 83, /* 'z' */ + 120, /* '{' */ + 83, /* '|' */ + 102, /* '}' */ + 74, /* '~' */ + 42, /* ' ' */ + }, + /* height table for font XTR */ + { + 266, /* ' ' */ + 147, /* '!' */ + 144, /* '"' */ + 139, /* '#' */ + 140, /* '$' */ + 97, /* '%' */ + 97, /* '&' */ + 97, /* ''' */ + 97, /* '(' */ + 167, /* ')' */ + 168, /* '*' */ + 106, /* '+' */ + 69, /* ',' */ + 142, /* '-' */ + 141, /* '.' */ + 142, /* '/' */ + 142, /* '0' */ + 129, /* '1' */ + 139, /* '2' */ + 131, /* '3' */ + 131, /* '4' */ + 146, /* '5' */ + 63, /* '6' */ + 142, /* '7' */ + 57, /* '8' */ + 142, /* '9' */ + 69, /* ':' */ + 139, /* ';' */ + 108, /* '<' */ + 142, /* '=' */ + 142, /* '>' */ + 139, /* '?' */ + 142, /* '@' */ + 163, /* 'A' */ + 138, /* 'B' */ + 139, /* 'C' */ + 108, /* 'D' */ + 104, /* 'E' */ + 144, /* 'F' */ + 176, /* 'G' */ + 144, /* 'H' */ + 175, /* 'I' */ + 144, /* 'J' */ + 167, /* 'K' */ + 134, /* 'L' */ + 176, /* 'M' */ + 144, /* 'N' */ + 181, /* 'O' */ + 150, /* 'P' */ + 169, /* 'Q' */ + 136, /* 'R' */ + 178, /* 'S' */ + 141, /* 'T' */ + 176, /* 'U' */ + 144, /* 'V' */ + 175, /* 'W' */ + 144, /* 'X' */ + 167, /* 'Y' */ + 134, /* 'Z' */ + 176, /* '[' */ + 144, /* '\' */ + 176, /* ']' */ + 142, /* '^' */ + 175, /* '_' */ + 142, /* '`' */ + 167, /* 'a' */ + 132, /* 'b' */ + 176, /* 'c' */ + 142, /* 'd' */ + 172, /* 'e' */ + 134, /* 'f' */ + 178, /* 'g' */ + 144, /* 'h' */ + 178, /* 'i' */ + 144, /* 'j' */ + 169, /* 'k' */ + 134, /* 'l' */ + 178, /* 'm' */ + 144, /* 'n' */ + 172, /* 'o' */ + 136, /* 'p' */ + 178, /* 'q' */ + 144, /* 'r' */ + 178, /* 's' */ + 144, /* 't' */ + 178, /* 'u' */ + 144, /* 'v' */ + 169, /* 'w' */ + 134, /* 'x' */ + 178, /* 'y' */ + 144, /* 'z' */ + 167, /* '{' */ + 167, /* '|' */ + 175, /* '}' */ + 142, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XTR */ + { + 186, /* ' ' */ + 110, /* '!' */ + 128, /* '"' */ + 125, /* '#' */ + 127, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 83, /* ''' */ + 83, /* '(' */ + 128, /* ')' */ + 128, /* '*' */ + 92, /* '+' */ + 32, /* ',' */ + 128, /* '-' */ + 92, /* '.' */ + 128, /* '/' */ + 128, /* '0' */ + 115, /* '1' */ + 125, /* '2' */ + 118, /* '3' */ + 118, /* '4' */ + 132, /* '5' */ + 14, /* '6' */ + 128, /* '7' */ + 14, /* '8' */ + 128, /* '9' */ + 55, /* ':' */ + 125, /* ';' */ + 92, /* '<' */ + 128, /* '=' */ + 128, /* '>' */ + 125, /* '?' */ + 128, /* '@' */ + 136, /* 'A' */ + 106, /* 'B' */ + 125, /* 'C' */ + 92, /* 'D' */ + 91, /* 'E' */ + 128, /* 'F' */ + 162, /* 'G' */ + 128, /* 'H' */ + 162, /* 'I' */ + 128, /* 'J' */ + 153, /* 'K' */ + 118, /* 'L' */ + 162, /* 'M' */ + 128, /* 'N' */ + 167, /* 'O' */ + 134, /* 'P' */ + 156, /* 'Q' */ + 120, /* 'R' */ + 128, /* 'S' */ + 92, /* 'T' */ + 162, /* 'U' */ + 128, /* 'V' */ + 162, /* 'W' */ + 128, /* 'X' */ + 153, /* 'Y' */ + 118, /* 'Z' */ + 162, /* '[' */ + 128, /* '\' */ + 162, /* ']' */ + 128, /* '^' */ + 162, /* '_' */ + 128, /* '`' */ + 153, /* 'a' */ + 118, /* 'b' */ + 162, /* 'c' */ + 128, /* 'd' */ + 156, /* 'e' */ + 120, /* 'f' */ + 162, /* 'g' */ + 128, /* 'h' */ + 162, /* 'i' */ + 128, /* 'j' */ + 153, /* 'k' */ + 118, /* 'l' */ + 162, /* 'm' */ + 128, /* 'n' */ + 156, /* 'o' */ + 120, /* 'p' */ + 162, /* 'q' */ + 128, /* 'r' */ + 162, /* 's' */ + 128, /* 't' */ + 162, /* 'u' */ + 128, /* 'v' */ + 153, /* 'w' */ + 118, /* 'x' */ + 162, /* 'y' */ + 128, /* 'z' */ + 153, /* '{' */ + 118, /* '|' */ + 162, /* '}' */ + 128, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Times-Roman", + 0, + NO + }, { + /* width table for font XTI */ + { + 65, /* ' ' */ + 83, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 93, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 58, /* '+' */ + 93, /* ',' */ + 93, /* '-' */ + 83, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 148, /* ':' */ + 148, /* ';' */ + 111, /* '<' */ + 46, /* '=' */ + 52, /* '>' */ + 93, /* '?' */ + 46, /* '@' */ + 120, /* 'A' */ + 83, /* 'B' */ + 157, /* 'C' */ + 111, /* 'D' */ + 46, /* 'E' */ + 83, /* 'F' */ + 102, /* 'G' */ + 83, /* 'H' */ + 102, /* 'I' */ + 83, /* 'J' */ + 102, /* 'K' */ + 83, /* 'L' */ + 102, /* 'M' */ + 83, /* 'N' */ + 102, /* 'O' */ + 83, /* 'P' */ + 102, /* 'Q' */ + 83, /* 'R' */ + 111, /* 'S' */ + 74, /* 'T' */ + 102, /* 'U' */ + 74, /* 'V' */ + 102, /* 'W' */ + 74, /* 'X' */ + 102, /* 'Y' */ + 74, /* 'Z' */ + 102, /* '[' */ + 74, /* '\' */ + 55, /* ']' */ + 46, /* '^' */ + 55, /* '_' */ + 46, /* '`' */ + 55, /* 'a' */ + 46, /* 'b' */ + 55, /* 'c' */ + 46, /* 'd' */ + 111, /* 'e' */ + 83, /* 'f' */ + 120, /* 'g' */ + 83, /* 'h' */ + 120, /* 'i' */ + 83, /* 'j' */ + 120, /* 'k' */ + 83, /* 'l' */ + 120, /* 'm' */ + 83, /* 'n' */ + 120, /* 'o' */ + 83, /* 'p' */ + 83, /* 'q' */ + 65, /* 'r' */ + 120, /* 's' */ + 83, /* 't' */ + 120, /* 'u' */ + 83, /* 'v' */ + 120, /* 'w' */ + 83, /* 'x' */ + 120, /* 'y' */ + 83, /* 'z' */ + 93, /* '{' */ + 74, /* '|' */ + 93, /* '}' */ + 65, /* '~' */ + 42, /* ' ' */ + }, + /* height table for font XTI */ + { + 265, /* ' ' */ + 145, /* '!' */ + 139, /* '"' */ + 136, /* '#' */ + 139, /* '$' */ + 95, /* '%' */ + 95, /* '&' */ + 95, /* ''' */ + 95, /* '(' */ + 165, /* ')' */ + 163, /* '*' */ + 105, /* '+' */ + 66, /* ',' */ + 139, /* '-' */ + 141, /* '.' */ + 139, /* '/' */ + 139, /* '0' */ + 126, /* '1' */ + 136, /* '2' */ + 129, /* '3' */ + 129, /* '4' */ + 146, /* '5' */ + 63, /* '6' */ + 139, /* '7' */ + 63, /* '8' */ + 139, /* '9' */ + 69, /* ':' */ + 136, /* ';' */ + 104, /* '<' */ + 140, /* '=' */ + 139, /* '>' */ + 136, /* '?' */ + 144, /* '@' */ + 166, /* 'A' */ + 143, /* 'B' */ + 141, /* 'C' */ + 104, /* 'D' */ + 103, /* 'E' */ + 178, /* 'F' */ + 174, /* 'G' */ + 141, /* 'H' */ + 173, /* 'I' */ + 141, /* 'J' */ + 164, /* 'K' */ + 131, /* 'L' */ + 174, /* 'M' */ + 141, /* 'N' */ + 180, /* 'O' */ + 148, /* 'P' */ + 167, /* 'Q' */ + 134, /* 'R' */ + 174, /* 'S' */ + 138, /* 'T' */ + 174, /* 'U' */ + 141, /* 'V' */ + 173, /* 'W' */ + 141, /* 'X' */ + 164, /* 'Y' */ + 131, /* 'Z' */ + 174, /* '[' */ + 141, /* '\' */ + 174, /* ']' */ + 141, /* '^' */ + 173, /* '_' */ + 141, /* '`' */ + 166, /* 'a' */ + 131, /* 'b' */ + 174, /* 'c' */ + 141, /* 'd' */ + 169, /* 'e' */ + 134, /* 'f' */ + 176, /* 'g' */ + 141, /* 'h' */ + 176, /* 'i' */ + 141, /* 'j' */ + 166, /* 'k' */ + 131, /* 'l' */ + 176, /* 'm' */ + 141, /* 'n' */ + 169, /* 'o' */ + 134, /* 'p' */ + 175, /* 'q' */ + 141, /* 'r' */ + 176, /* 's' */ + 141, /* 't' */ + 176, /* 'u' */ + 141, /* 'v' */ + 166, /* 'w' */ + 131, /* 'x' */ + 176, /* 'y' */ + 141, /* 'z' */ + 164, /* '{' */ + 163, /* '|' */ + 173, /* '}' */ + 151, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XTI */ + { + 186, /* ' ' */ + 107, /* '!' */ + 125, /* '"' */ + 122, /* '#' */ + 125, /* '$' */ + 81, /* '%' */ + 81, /* '&' */ + 81, /* ''' */ + 81, /* '(' */ + 125, /* ')' */ + 125, /* '*' */ + 91, /* '+' */ + 31, /* ',' */ + 125, /* '-' */ + 92, /* '.' */ + 125, /* '/' */ + 125, /* '0' */ + 112, /* '1' */ + 122, /* '2' */ + 115, /* '3' */ + 115, /* '4' */ + 132, /* '5' */ + 14, /* '6' */ + 125, /* '7' */ + 21, /* '8' */ + 125, /* '9' */ + 55, /* ':' */ + 122, /* ';' */ + 88, /* '<' */ + 126, /* '=' */ + 125, /* '>' */ + 122, /* '?' */ + 128, /* '@' */ + 134, /* 'A' */ + 106, /* 'B' */ + 125, /* 'C' */ + 88, /* 'D' */ + 87, /* 'E' */ + 128, /* 'F' */ + 160, /* 'G' */ + 125, /* 'H' */ + 159, /* 'I' */ + 125, /* 'J' */ + 150, /* 'K' */ + 115, /* 'L' */ + 160, /* 'M' */ + 125, /* 'N' */ + 166, /* 'O' */ + 132, /* 'P' */ + 153, /* 'Q' */ + 118, /* 'R' */ + 125, /* 'S' */ + 88, /* 'T' */ + 160, /* 'U' */ + 125, /* 'V' */ + 159, /* 'W' */ + 125, /* 'X' */ + 150, /* 'Y' */ + 115, /* 'Z' */ + 160, /* '[' */ + 125, /* '\' */ + 160, /* ']' */ + 125, /* '^' */ + 159, /* '_' */ + 125, /* '`' */ + 152, /* 'a' */ + 115, /* 'b' */ + 160, /* 'c' */ + 125, /* 'd' */ + 153, /* 'e' */ + 118, /* 'f' */ + 160, /* 'g' */ + 125, /* 'h' */ + 159, /* 'i' */ + 125, /* 'j' */ + 150, /* 'k' */ + 115, /* 'l' */ + 160, /* 'm' */ + 125, /* 'n' */ + 153, /* 'o' */ + 118, /* 'p' */ + 159, /* 'q' */ + 125, /* 'r' */ + 160, /* 's' */ + 125, /* 't' */ + 159, /* 'u' */ + 125, /* 'v' */ + 150, /* 'w' */ + 115, /* 'x' */ + 160, /* 'y' */ + 125, /* 'z' */ + 150, /* '{' */ + 115, /* '|' */ + 159, /* '}' */ + 125, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Times-Italic", + 0, + YES + }, { + /* width table for font XTB */ + { + 55, /* ' ' */ + 83, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 58, /* '+' */ + 83, /* ',' */ + 83, /* '-' */ + 83, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 167, /* ';' */ + 120, /* '<' */ + 50, /* '=' */ + 55, /* '>' */ + 111, /* '?' */ + 46, /* '@' */ + 130, /* 'A' */ + 83, /* 'B' */ + 167, /* 'C' */ + 120, /* 'D' */ + 46, /* 'E' */ + 93, /* 'F' */ + 120, /* 'G' */ + 83, /* 'H' */ + 120, /* 'I' */ + 83, /* 'J' */ + 120, /* 'K' */ + 83, /* 'L' */ + 120, /* 'M' */ + 83, /* 'N' */ + 120, /* 'O' */ + 83, /* 'P' */ + 120, /* 'Q' */ + 83, /* 'R' */ + 120, /* 'S' */ + 74, /* 'T' */ + 111, /* 'U' */ + 74, /* 'V' */ + 111, /* 'W' */ + 74, /* 'X' */ + 111, /* 'Y' */ + 74, /* 'Z' */ + 111, /* '[' */ + 74, /* '\' */ + 65, /* ']' */ + 46, /* '^' */ + 65, /* '_' */ + 46, /* '`' */ + 65, /* 'a' */ + 46, /* 'b' */ + 65, /* 'c' */ + 46, /* 'd' */ + 120, /* 'e' */ + 93, /* 'f' */ + 130, /* 'g' */ + 83, /* 'h' */ + 130, /* 'i' */ + 83, /* 'j' */ + 130, /* 'k' */ + 83, /* 'l' */ + 130, /* 'm' */ + 83, /* 'n' */ + 130, /* 'o' */ + 83, /* 'p' */ + 93, /* 'q' */ + 65, /* 'r' */ + 120, /* 's' */ + 93, /* 't' */ + 120, /* 'u' */ + 93, /* 'v' */ + 120, /* 'w' */ + 93, /* 'x' */ + 120, /* 'y' */ + 93, /* 'z' */ + 120, /* '{' */ + 83, /* '|' */ + 111, /* '}' */ + 74, /* '~' */ + 42, /* ' ' */ + }, + /* height table for font XTB */ + { + 268, /* ' ' */ + 149, /* '!' */ + 144, /* '"' */ + 139, /* '#' */ + 143, /* '$' */ + 97, /* '%' */ + 97, /* '&' */ + 97, /* ''' */ + 97, /* '(' */ + 165, /* ')' */ + 164, /* '*' */ + 109, /* '+' */ + 86, /* ',' */ + 142, /* '-' */ + 141, /* '.' */ + 147, /* '/' */ + 147, /* '0' */ + 132, /* '1' */ + 142, /* '2' */ + 139, /* '3' */ + 139, /* '4' */ + 152, /* '5' */ + 63, /* '6' */ + 147, /* '7' */ + 64, /* '8' */ + 145, /* '9' */ + 72, /* ':' */ + 139, /* ';' */ + 111, /* '<' */ + 142, /* '=' */ + 142, /* '>' */ + 139, /* '?' */ + 139, /* '@' */ + 163, /* 'A' */ + 135, /* 'B' */ + 143, /* 'C' */ + 111, /* 'D' */ + 106, /* 'E' */ + 144, /* 'F' */ + 182, /* 'G' */ + 149, /* 'H' */ + 180, /* 'I' */ + 147, /* 'J' */ + 174, /* 'K' */ + 141, /* 'L' */ + 182, /* 'M' */ + 149, /* 'N' */ + 184, /* 'O' */ + 154, /* 'P' */ + 176, /* 'Q' */ + 142, /* 'R' */ + 178, /* 'S' */ + 144, /* 'T' */ + 182, /* 'U' */ + 149, /* 'V' */ + 180, /* 'W' */ + 147, /* 'X' */ + 174, /* 'Y' */ + 141, /* 'Z' */ + 182, /* '[' */ + 149, /* '\' */ + 182, /* ']' */ + 147, /* '^' */ + 180, /* '_' */ + 145, /* '`' */ + 172, /* 'a' */ + 139, /* 'b' */ + 182, /* 'c' */ + 147, /* 'd' */ + 178, /* 'e' */ + 140, /* 'f' */ + 184, /* 'g' */ + 149, /* 'h' */ + 182, /* 'i' */ + 147, /* 'j' */ + 176, /* 'k' */ + 141, /* 'l' */ + 184, /* 'm' */ + 149, /* 'n' */ + 178, /* 'o' */ + 142, /* 'p' */ + 182, /* 'q' */ + 147, /* 'r' */ + 184, /* 's' */ + 149, /* 't' */ + 182, /* 'u' */ + 147, /* 'v' */ + 176, /* 'w' */ + 141, /* 'x' */ + 184, /* 'y' */ + 149, /* 'z' */ + 174, /* '{' */ + 174, /* '|' */ + 180, /* '}' */ + 145, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XTB */ + { + 189, /* ' ' */ + 112, /* '!' */ + 128, /* '"' */ + 125, /* '#' */ + 129, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 83, /* ''' */ + 83, /* '(' */ + 128, /* ')' */ + 128, /* '*' */ + 95, /* '+' */ + 42, /* ',' */ + 128, /* '-' */ + 95, /* '.' */ + 133, /* '/' */ + 133, /* '0' */ + 118, /* '1' */ + 128, /* '2' */ + 125, /* '3' */ + 125, /* '4' */ + 138, /* '5' */ + 14, /* '6' */ + 133, /* '7' */ + 21, /* '8' */ + 131, /* '9' */ + 58, /* ':' */ + 125, /* ';' */ + 95, /* '<' */ + 128, /* '=' */ + 128, /* '>' */ + 125, /* '?' */ + 125, /* '@' */ + 137, /* 'A' */ + 105, /* 'B' */ + 128, /* 'C' */ + 95, /* 'D' */ + 92, /* 'E' */ + 128, /* 'F' */ + 168, /* 'G' */ + 133, /* 'H' */ + 166, /* 'I' */ + 131, /* 'J' */ + 160, /* 'K' */ + 125, /* 'L' */ + 168, /* 'M' */ + 133, /* 'N' */ + 170, /* 'O' */ + 138, /* 'P' */ + 162, /* 'Q' */ + 126, /* 'R' */ + 128, /* 'S' */ + 95, /* 'T' */ + 168, /* 'U' */ + 133, /* 'V' */ + 166, /* 'W' */ + 131, /* 'X' */ + 160, /* 'Y' */ + 125, /* 'Z' */ + 168, /* '[' */ + 133, /* '\' */ + 168, /* ']' */ + 133, /* '^' */ + 166, /* '_' */ + 131, /* '`' */ + 158, /* 'a' */ + 125, /* 'b' */ + 168, /* 'c' */ + 133, /* 'd' */ + 162, /* 'e' */ + 126, /* 'f' */ + 168, /* 'g' */ + 133, /* 'h' */ + 166, /* 'i' */ + 131, /* 'j' */ + 160, /* 'k' */ + 125, /* 'l' */ + 168, /* 'm' */ + 133, /* 'n' */ + 162, /* 'o' */ + 126, /* 'p' */ + 166, /* 'q' */ + 131, /* 'r' */ + 168, /* 's' */ + 133, /* 't' */ + 166, /* 'u' */ + 131, /* 'v' */ + 160, /* 'w' */ + 125, /* 'x' */ + 168, /* 'y' */ + 133, /* 'z' */ + 160, /* '{' */ + 125, /* '|' */ + 166, /* '}' */ + 131, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Times-Bold", + 0, + NO + }, { + /* width table for font XTX */ + { + 65, /* ' ' */ + 83, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 58, /* '+' */ + 83, /* ',' */ + 83, /* '-' */ + 83, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 157, /* ';' */ + 120, /* '<' */ + 44, /* '=' */ + 50, /* '>' */ + 102, /* '?' */ + 46, /* '@' */ + 120, /* 'A' */ + 83, /* 'B' */ + 157, /* 'C' */ + 120, /* 'D' */ + 46, /* 'E' */ + 83, /* 'F' */ + 111, /* 'G' */ + 83, /* 'H' */ + 111, /* 'I' */ + 83, /* 'J' */ + 111, /* 'K' */ + 83, /* 'L' */ + 111, /* 'M' */ + 83, /* 'N' */ + 111, /* 'O' */ + 83, /* 'P' */ + 111, /* 'Q' */ + 83, /* 'R' */ + 111, /* 'S' */ + 74, /* 'T' */ + 111, /* 'U' */ + 74, /* 'V' */ + 111, /* 'W' */ + 74, /* 'X' */ + 111, /* 'Y' */ + 74, /* 'Z' */ + 111, /* '[' */ + 74, /* '\' */ + 65, /* ']' */ + 46, /* '^' */ + 65, /* '_' */ + 46, /* '`' */ + 65, /* 'a' */ + 46, /* 'b' */ + 65, /* 'c' */ + 46, /* 'd' */ + 120, /* 'e' */ + 93, /* 'f' */ + 120, /* 'g' */ + 83, /* 'h' */ + 120, /* 'i' */ + 83, /* 'j' */ + 120, /* 'k' */ + 83, /* 'l' */ + 120, /* 'm' */ + 83, /* 'n' */ + 120, /* 'o' */ + 83, /* 'p' */ + 93, /* 'q' */ + 65, /* 'r' */ + 120, /* 's' */ + 93, /* 't' */ + 120, /* 'u' */ + 93, /* 'v' */ + 120, /* 'w' */ + 93, /* 'x' */ + 120, /* 'y' */ + 93, /* 'z' */ + 102, /* '{' */ + 74, /* '|' */ + 102, /* '}' */ + 65, /* '~' */ + 42, /* ' ' */ + }, + /* height table for font XTX */ + { + 269, /* ' ' */ + 148, /* '!' */ + 144, /* '"' */ + 139, /* '#' */ + 142, /* '$' */ + 97, /* '%' */ + 97, /* '&' */ + 97, /* ''' */ + 97, /* '(' */ + 166, /* ')' */ + 165, /* '*' */ + 115, /* '+' */ + 80, /* ',' */ + 142, /* '-' */ + 144, /* '.' */ + 144, /* '/' */ + 144, /* '0' */ + 132, /* '1' */ + 142, /* '2' */ + 137, /* '3' */ + 137, /* '4' */ + 152, /* '5' */ + 64, /* '6' */ + 144, /* '7' */ + 64, /* '8' */ + 143, /* '9' */ + 72, /* ':' */ + 139, /* ';' */ + 108, /* '<' */ + 142, /* '=' */ + 142, /* '>' */ + 139, /* '?' */ + 147, /* '@' */ + 176, /* 'A' */ + 141, /* 'B' */ + 144, /* 'C' */ + 108, /* 'D' */ + 107, /* 'E' */ + 181, /* 'F' */ + 178, /* 'G' */ + 146, /* 'H' */ + 177, /* 'I' */ + 145, /* 'J' */ + 171, /* 'K' */ + 139, /* 'L' */ + 178, /* 'M' */ + 146, /* 'N' */ + 187, /* 'O' */ + 154, /* 'P' */ + 172, /* 'Q' */ + 141, /* 'R' */ + 178, /* 'S' */ + 141, /* 'T' */ + 178, /* 'U' */ + 146, /* 'V' */ + 177, /* 'W' */ + 145, /* 'X' */ + 171, /* 'Y' */ + 139, /* 'Z' */ + 178, /* '[' */ + 146, /* '\' */ + 179, /* ']' */ + 146, /* '^' */ + 177, /* '_' */ + 145, /* '`' */ + 172, /* 'a' */ + 141, /* 'b' */ + 178, /* 'c' */ + 146, /* 'd' */ + 174, /* 'e' */ + 141, /* 'f' */ + 181, /* 'g' */ + 146, /* 'h' */ + 180, /* 'i' */ + 145, /* 'j' */ + 174, /* 'k' */ + 139, /* 'l' */ + 181, /* 'm' */ + 146, /* 'n' */ + 174, /* 'o' */ + 141, /* 'p' */ + 180, /* 'q' */ + 145, /* 'r' */ + 181, /* 's' */ + 146, /* 't' */ + 179, /* 'u' */ + 145, /* 'v' */ + 174, /* 'w' */ + 139, /* 'x' */ + 181, /* 'y' */ + 146, /* 'z' */ + 171, /* '{' */ + 173, /* '|' */ + 177, /* '}' */ + 155, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XTX */ + { + 189, /* ' ' */ + 110, /* '!' */ + 128, /* '"' */ + 125, /* '#' */ + 128, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 83, /* ''' */ + 83, /* '(' */ + 128, /* ')' */ + 128, /* '*' */ + 101, /* '+' */ + 36, /* ',' */ + 128, /* '-' */ + 95, /* '.' */ + 130, /* '/' */ + 130, /* '0' */ + 118, /* '1' */ + 128, /* '2' */ + 123, /* '3' */ + 123, /* '4' */ + 138, /* '5' */ + 15, /* '6' */ + 130, /* '7' */ + 21, /* '8' */ + 129, /* '9' */ + 58, /* ':' */ + 125, /* ';' */ + 92, /* '<' */ + 128, /* '=' */ + 128, /* '>' */ + 125, /* '?' */ + 130, /* '@' */ + 141, /* 'A' */ + 107, /* 'B' */ + 128, /* 'C' */ + 92, /* 'D' */ + 91, /* 'E' */ + 132, /* 'F' */ + 165, /* 'G' */ + 130, /* 'H' */ + 163, /* 'I' */ + 129, /* 'J' */ + 158, /* 'K' */ + 123, /* 'L' */ + 165, /* 'M' */ + 130, /* 'N' */ + 173, /* 'O' */ + 138, /* 'P' */ + 158, /* 'Q' */ + 125, /* 'R' */ + 128, /* 'S' */ + 92, /* 'T' */ + 165, /* 'U' */ + 130, /* 'V' */ + 163, /* 'W' */ + 129, /* 'X' */ + 158, /* 'Y' */ + 123, /* 'Z' */ + 165, /* '[' */ + 130, /* '\' */ + 165, /* ']' */ + 130, /* '^' */ + 163, /* '_' */ + 129, /* '`' */ + 158, /* 'a' */ + 125, /* 'b' */ + 165, /* 'c' */ + 130, /* 'd' */ + 158, /* 'e' */ + 125, /* 'f' */ + 165, /* 'g' */ + 130, /* 'h' */ + 163, /* 'i' */ + 129, /* 'j' */ + 158, /* 'k' */ + 123, /* 'l' */ + 165, /* 'm' */ + 130, /* 'n' */ + 158, /* 'o' */ + 125, /* 'p' */ + 163, /* 'q' */ + 129, /* 'r' */ + 165, /* 's' */ + 130, /* 't' */ + 163, /* 'u' */ + 129, /* 'v' */ + 158, /* 'w' */ + 123, /* 'x' */ + 165, /* 'y' */ + 130, /* 'z' */ + 158, /* '{' */ + 123, /* '|' */ + 163, /* '}' */ + 129, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Times-BoldItalic", + 0, + YES + }, { + /* width table for font XAR */ + { + 49, /* ' ' */ + 92, /* '!' */ + 92, /* '"' */ + 92, /* '#' */ + 84, /* '$' */ + 71, /* '%' */ + 71, /* '&' */ + 42, /* ''' */ + 42, /* '(' */ + 92, /* ')' */ + 92, /* '*' */ + 101, /* '+' */ + 84, /* ',' */ + 81, /* '-' */ + 98, /* '.' */ + 63, /* '/' */ + 62, /* '0' */ + 81, /* '1' */ + 75, /* '2' */ + 37, /* '3' */ + 61, /* '4' */ + 55, /* '5' */ + 54, /* '6' */ + 92, /* '7' */ + 50, /* '8' */ + 84, /* '9' */ + 167, /* ':' */ + 165, /* ';' */ + 193, /* '<' */ + 61, /* '=' */ + 61, /* '>' */ + 86, /* '?' */ + 50, /* '@' */ + 145, /* 'A' */ + 109, /* 'B' */ + 199, /* 'C' */ + 189, /* 'D' */ + 33, /* 'E' */ + 92, /* 'F' */ + 123, /* 'G' */ + 114, /* 'H' */ + 123, /* 'I' */ + 114, /* 'J' */ + 123, /* 'K' */ + 114, /* 'L' */ + 123, /* 'M' */ + 114, /* 'N' */ + 123, /* 'O' */ + 114, /* 'P' */ + 123, /* 'Q' */ + 114, /* 'R' */ + 135, /* 'S' */ + 108, /* 'T' */ + 89, /* 'U' */ + 108, /* 'V' */ + 89, /* 'W' */ + 108, /* 'X' */ + 89, /* 'Y' */ + 108, /* 'Z' */ + 89, /* '[' */ + 108, /* '\' */ + 38, /* ']' */ + 33, /* '^' */ + 38, /* '_' */ + 33, /* '`' */ + 38, /* 'a' */ + 33, /* 'b' */ + 38, /* 'c' */ + 33, /* 'd' */ + 123, /* 'e' */ + 102, /* 'f' */ + 145, /* 'g' */ + 109, /* 'h' */ + 145, /* 'i' */ + 109, /* 'j' */ + 145, /* 'k' */ + 109, /* 'l' */ + 145, /* 'm' */ + 109, /* 'n' */ + 145, /* 'o' */ + 109, /* 'p' */ + 83, /* 'q' */ + 65, /* 'r' */ + 109, /* 's' */ + 101, /* 't' */ + 109, /* 'u' */ + 101, /* 'v' */ + 109, /* 'w' */ + 101, /* 'x' */ + 109, /* 'y' */ + 101, /* 'z' */ + 99, /* '{' */ + 89, /* '|' */ + 80, /* '}' */ + 71, /* '~' */ + 46, /* ' ' */ + }, + /* height table for font XAR */ + { + 276, /* ' ' */ + 146, /* '!' */ + 156, /* '"' */ + 152, /* '#' */ + 152, /* '$' */ + 111, /* '%' */ + 111, /* '&' */ + 111, /* ''' */ + 111, /* '(' */ + 174, /* ')' */ + 174, /* '*' */ + 109, /* '+' */ + 60, /* ',' */ + 152, /* '-' */ + 151, /* '.' */ + 157, /* '/' */ + 158, /* '0' */ + 146, /* '1' */ + 152, /* '2' */ + 156, /* '3' */ + 156, /* '4' */ + 159, /* '5' */ + 63, /* '6' */ + 158, /* '7' */ + 60, /* '8' */ + 156, /* '9' */ + 76, /* ':' */ + 152, /* ';' */ + 124, /* '<' */ + 152, /* '=' */ + 152, /* '>' */ + 152, /* '?' */ + 152, /* '@' */ + 178, /* 'A' */ + 133, /* 'B' */ + 158, /* 'C' */ + 124, /* 'D' */ + 119, /* 'E' */ + 158, /* 'F' */ + 188, /* 'G' */ + 160, /* 'H' */ + 183, /* 'I' */ + 158, /* 'J' */ + 182, /* 'K' */ + 158, /* 'L' */ + 187, /* 'M' */ + 159, /* 'N' */ + 189, /* 'O' */ + 161, /* 'P' */ + 179, /* 'Q' */ + 151, /* 'R' */ + 194, /* 'S' */ + 158, /* 'T' */ + 188, /* 'U' */ + 160, /* 'V' */ + 183, /* 'W' */ + 158, /* 'X' */ + 182, /* 'Y' */ + 158, /* 'Z' */ + 187, /* '[' */ + 159, /* '\' */ + 188, /* ']' */ + 158, /* '^' */ + 183, /* '_' */ + 156, /* '`' */ + 182, /* 'a' */ + 156, /* 'b' */ + 187, /* 'c' */ + 157, /* 'd' */ + 179, /* 'e' */ + 149, /* 'f' */ + 191, /* 'g' */ + 160, /* 'h' */ + 185, /* 'i' */ + 158, /* 'j' */ + 184, /* 'k' */ + 158, /* 'l' */ + 190, /* 'm' */ + 159, /* 'n' */ + 182, /* 'o' */ + 151, /* 'p' */ + 185, /* 'q' */ + 158, /* 'r' */ + 191, /* 's' */ + 160, /* 't' */ + 185, /* 'u' */ + 158, /* 'v' */ + 184, /* 'w' */ + 158, /* 'x' */ + 190, /* 'y' */ + 159, /* 'z' */ + 182, /* '{' */ + 188, /* '|' */ + 183, /* '}' */ + 156, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XAR */ + { + 199, /* ' ' */ + 132, /* '!' */ + 142, /* '"' */ + 138, /* '#' */ + 138, /* '$' */ + 97, /* '%' */ + 97, /* '&' */ + 97, /* ''' */ + 97, /* '(' */ + 138, /* ')' */ + 138, /* '*' */ + 95, /* '+' */ + 35, /* ',' */ + 138, /* '-' */ + 105, /* '.' */ + 143, /* '/' */ + 144, /* '0' */ + 132, /* '1' */ + 138, /* '2' */ + 142, /* '3' */ + 142, /* '4' */ + 145, /* '5' */ + 14, /* '6' */ + 144, /* '7' */ + 14, /* '8' */ + 142, /* '9' */ + 62, /* ':' */ + 138, /* ';' */ + 108, /* '<' */ + 138, /* '=' */ + 138, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 151, /* 'A' */ + 113, /* 'B' */ + 142, /* 'C' */ + 108, /* 'D' */ + 105, /* 'E' */ + 142, /* 'F' */ + 175, /* 'G' */ + 144, /* 'H' */ + 169, /* 'I' */ + 142, /* 'J' */ + 168, /* 'K' */ + 142, /* 'L' */ + 174, /* 'M' */ + 143, /* 'N' */ + 175, /* 'O' */ + 145, /* 'P' */ + 166, /* 'Q' */ + 135, /* 'R' */ + 142, /* 'S' */ + 108, /* 'T' */ + 175, /* 'U' */ + 144, /* 'V' */ + 169, /* 'W' */ + 142, /* 'X' */ + 168, /* 'Y' */ + 142, /* 'Z' */ + 174, /* '[' */ + 143, /* '\' */ + 175, /* ']' */ + 144, /* '^' */ + 169, /* '_' */ + 142, /* '`' */ + 168, /* 'a' */ + 142, /* 'b' */ + 174, /* 'c' */ + 143, /* 'd' */ + 166, /* 'e' */ + 135, /* 'f' */ + 175, /* 'g' */ + 144, /* 'h' */ + 169, /* 'i' */ + 142, /* 'j' */ + 168, /* 'k' */ + 142, /* 'l' */ + 174, /* 'm' */ + 143, /* 'n' */ + 166, /* 'o' */ + 135, /* 'p' */ + 169, /* 'q' */ + 142, /* 'r' */ + 175, /* 's' */ + 144, /* 't' */ + 169, /* 'u' */ + 142, /* 'v' */ + 168, /* 'w' */ + 142, /* 'x' */ + 174, /* 'y' */ + 143, /* 'z' */ + 168, /* '{' */ + 142, /* '|' */ + 169, /* '}' */ + 142, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-AvantGarde-Book", + 0, + NO + }, { + /* width table for font XAI */ + { + 49, /* ' ' */ + 92, /* '!' */ + 92, /* '"' */ + 92, /* '#' */ + 84, /* '$' */ + 71, /* '%' */ + 71, /* '&' */ + 42, /* ''' */ + 42, /* '(' */ + 92, /* ')' */ + 92, /* '*' */ + 101, /* '+' */ + 84, /* ',' */ + 81, /* '-' */ + 98, /* '.' */ + 63, /* '/' */ + 62, /* '0' */ + 81, /* '1' */ + 75, /* '2' */ + 37, /* '3' */ + 61, /* '4' */ + 55, /* '5' */ + 54, /* '6' */ + 92, /* '7' */ + 50, /* '8' */ + 84, /* '9' */ + 167, /* ':' */ + 165, /* ';' */ + 193, /* '<' */ + 61, /* '=' */ + 61, /* '>' */ + 86, /* '?' */ + 50, /* '@' */ + 145, /* 'A' */ + 109, /* 'B' */ + 199, /* 'C' */ + 189, /* 'D' */ + 33, /* 'E' */ + 92, /* 'F' */ + 123, /* 'G' */ + 114, /* 'H' */ + 123, /* 'I' */ + 114, /* 'J' */ + 123, /* 'K' */ + 114, /* 'L' */ + 123, /* 'M' */ + 114, /* 'N' */ + 123, /* 'O' */ + 114, /* 'P' */ + 123, /* 'Q' */ + 114, /* 'R' */ + 135, /* 'S' */ + 108, /* 'T' */ + 89, /* 'U' */ + 108, /* 'V' */ + 89, /* 'W' */ + 108, /* 'X' */ + 89, /* 'Y' */ + 108, /* 'Z' */ + 89, /* '[' */ + 108, /* '\' */ + 38, /* ']' */ + 33, /* '^' */ + 38, /* '_' */ + 33, /* '`' */ + 38, /* 'a' */ + 33, /* 'b' */ + 38, /* 'c' */ + 33, /* 'd' */ + 123, /* 'e' */ + 102, /* 'f' */ + 145, /* 'g' */ + 109, /* 'h' */ + 145, /* 'i' */ + 109, /* 'j' */ + 145, /* 'k' */ + 109, /* 'l' */ + 145, /* 'm' */ + 109, /* 'n' */ + 145, /* 'o' */ + 109, /* 'p' */ + 83, /* 'q' */ + 65, /* 'r' */ + 109, /* 's' */ + 101, /* 't' */ + 109, /* 'u' */ + 101, /* 'v' */ + 109, /* 'w' */ + 101, /* 'x' */ + 109, /* 'y' */ + 101, /* 'z' */ + 99, /* '{' */ + 89, /* '|' */ + 80, /* '}' */ + 71, /* '~' */ + 46, /* ' ' */ + }, + /* height table for font XAI */ + { + 276, /* ' ' */ + 146, /* '!' */ + 156, /* '"' */ + 152, /* '#' */ + 152, /* '$' */ + 111, /* '%' */ + 111, /* '&' */ + 111, /* ''' */ + 111, /* '(' */ + 174, /* ')' */ + 174, /* '*' */ + 109, /* '+' */ + 60, /* ',' */ + 152, /* '-' */ + 151, /* '.' */ + 157, /* '/' */ + 158, /* '0' */ + 146, /* '1' */ + 152, /* '2' */ + 156, /* '3' */ + 156, /* '4' */ + 159, /* '5' */ + 67, /* '6' */ + 158, /* '7' */ + 60, /* '8' */ + 156, /* '9' */ + 76, /* ':' */ + 152, /* ';' */ + 124, /* '<' */ + 152, /* '=' */ + 152, /* '>' */ + 152, /* '?' */ + 152, /* '@' */ + 178, /* 'A' */ + 133, /* 'B' */ + 158, /* 'C' */ + 124, /* 'D' */ + 119, /* 'E' */ + 158, /* 'F' */ + 188, /* 'G' */ + 160, /* 'H' */ + 183, /* 'I' */ + 158, /* 'J' */ + 182, /* 'K' */ + 158, /* 'L' */ + 188, /* 'M' */ + 160, /* 'N' */ + 189, /* 'O' */ + 161, /* 'P' */ + 180, /* 'Q' */ + 152, /* 'R' */ + 194, /* 'S' */ + 161, /* 'T' */ + 188, /* 'U' */ + 160, /* 'V' */ + 183, /* 'W' */ + 158, /* 'X' */ + 182, /* 'Y' */ + 158, /* 'Z' */ + 188, /* '[' */ + 160, /* '\' */ + 188, /* ']' */ + 158, /* '^' */ + 183, /* '_' */ + 156, /* '`' */ + 182, /* 'a' */ + 156, /* 'b' */ + 188, /* 'c' */ + 157, /* 'd' */ + 180, /* 'e' */ + 150, /* 'f' */ + 191, /* 'g' */ + 160, /* 'h' */ + 185, /* 'i' */ + 158, /* 'j' */ + 184, /* 'k' */ + 158, /* 'l' */ + 190, /* 'm' */ + 160, /* 'n' */ + 183, /* 'o' */ + 152, /* 'p' */ + 185, /* 'q' */ + 158, /* 'r' */ + 191, /* 's' */ + 160, /* 't' */ + 185, /* 'u' */ + 158, /* 'v' */ + 184, /* 'w' */ + 158, /* 'x' */ + 190, /* 'y' */ + 160, /* 'z' */ + 182, /* '{' */ + 188, /* '|' */ + 183, /* '}' */ + 156, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XAI */ + { + 199, /* ' ' */ + 132, /* '!' */ + 142, /* '"' */ + 138, /* '#' */ + 138, /* '$' */ + 97, /* '%' */ + 97, /* '&' */ + 97, /* ''' */ + 97, /* '(' */ + 138, /* ')' */ + 138, /* '*' */ + 95, /* '+' */ + 35, /* ',' */ + 138, /* '-' */ + 105, /* '.' */ + 144, /* '/' */ + 144, /* '0' */ + 132, /* '1' */ + 138, /* '2' */ + 142, /* '3' */ + 142, /* '4' */ + 145, /* '5' */ + 14, /* '6' */ + 144, /* '7' */ + 14, /* '8' */ + 142, /* '9' */ + 62, /* ':' */ + 138, /* ';' */ + 108, /* '<' */ + 138, /* '=' */ + 138, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 151, /* 'A' */ + 113, /* 'B' */ + 142, /* 'C' */ + 108, /* 'D' */ + 105, /* 'E' */ + 142, /* 'F' */ + 175, /* 'G' */ + 144, /* 'H' */ + 169, /* 'I' */ + 142, /* 'J' */ + 168, /* 'K' */ + 142, /* 'L' */ + 174, /* 'M' */ + 144, /* 'N' */ + 175, /* 'O' */ + 145, /* 'P' */ + 167, /* 'Q' */ + 136, /* 'R' */ + 142, /* 'S' */ + 108, /* 'T' */ + 175, /* 'U' */ + 144, /* 'V' */ + 169, /* 'W' */ + 142, /* 'X' */ + 168, /* 'Y' */ + 142, /* 'Z' */ + 174, /* '[' */ + 144, /* '\' */ + 175, /* ']' */ + 144, /* '^' */ + 169, /* '_' */ + 142, /* '`' */ + 168, /* 'a' */ + 142, /* 'b' */ + 174, /* 'c' */ + 144, /* 'd' */ + 167, /* 'e' */ + 136, /* 'f' */ + 175, /* 'g' */ + 144, /* 'h' */ + 169, /* 'i' */ + 142, /* 'j' */ + 168, /* 'k' */ + 142, /* 'l' */ + 174, /* 'm' */ + 144, /* 'n' */ + 167, /* 'o' */ + 136, /* 'p' */ + 169, /* 'q' */ + 142, /* 'r' */ + 175, /* 's' */ + 144, /* 't' */ + 169, /* 'u' */ + 142, /* 'v' */ + 168, /* 'w' */ + 142, /* 'x' */ + 174, /* 'y' */ + 144, /* 'z' */ + 168, /* '{' */ + 142, /* '|' */ + 169, /* '}' */ + 142, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-AvantGarde-BookOblique", + 0, + YES + }, { + /* width table for font XAB */ + { + 47, /* ' ' */ + 93, /* '!' */ + 93, /* '"' */ + 93, /* '#' */ + 80, /* '$' */ + 77, /* '%' */ + 77, /* '&' */ + 40, /* ''' */ + 40, /* '(' */ + 93, /* ')' */ + 93, /* '*' */ + 100, /* '+' */ + 80, /* ',' */ + 80, /* '-' */ + 93, /* '.' */ + 70, /* '/' */ + 70, /* '0' */ + 70, /* '1' */ + 80, /* '2' */ + 47, /* '3' */ + 83, /* '4' */ + 60, /* '5' */ + 57, /* '6' */ + 117, /* '7' */ + 57, /* '8' */ + 90, /* '9' */ + 167, /* ':' */ + 150, /* ';' */ + 180, /* '<' */ + 60, /* '=' */ + 60, /* '>' */ + 80, /* '?' */ + 53, /* '@' */ + 140, /* 'A' */ + 110, /* 'B' */ + 177, /* 'C' */ + 180, /* 'D' */ + 40, /* 'E' */ + 100, /* 'F' */ + 123, /* 'G' */ + 110, /* 'H' */ + 123, /* 'I' */ + 110, /* 'J' */ + 123, /* 'K' */ + 110, /* 'L' */ + 123, /* 'M' */ + 110, /* 'N' */ + 123, /* 'O' */ + 110, /* 'P' */ + 123, /* 'Q' */ + 110, /* 'R' */ + 130, /* 'S' */ + 107, /* 'T' */ + 87, /* 'U' */ + 107, /* 'V' */ + 87, /* 'W' */ + 107, /* 'X' */ + 87, /* 'Y' */ + 107, /* 'Z' */ + 87, /* '[' */ + 107, /* '\' */ + 47, /* ']' */ + 40, /* '^' */ + 47, /* '_' */ + 40, /* '`' */ + 47, /* 'a' */ + 40, /* 'b' */ + 47, /* 'c' */ + 40, /* 'd' */ + 123, /* 'e' */ + 100, /* 'f' */ + 140, /* 'g' */ + 107, /* 'h' */ + 140, /* 'i' */ + 107, /* 'j' */ + 140, /* 'k' */ + 107, /* 'l' */ + 140, /* 'm' */ + 107, /* 'n' */ + 140, /* 'o' */ + 107, /* 'p' */ + 87, /* 'q' */ + 73, /* 'r' */ + 107, /* 's' */ + 100, /* 't' */ + 107, /* 'u' */ + 100, /* 'v' */ + 107, /* 'w' */ + 100, /* 'x' */ + 107, /* 'y' */ + 100, /* 'z' */ + 103, /* '{' */ + 97, /* '|' */ + 83, /* '}' */ + 77, /* '~' */ + 47, /* ' ' */ + }, + /* height table for font XAB */ + { + 276, /* ' ' */ + 146, /* '!' */ + 156, /* '"' */ + 152, /* '#' */ + 152, /* '$' */ + 106, /* '%' */ + 106, /* '&' */ + 106, /* ''' */ + 106, /* '(' */ + 174, /* ')' */ + 174, /* '*' */ + 108, /* '+' */ + 72, /* ',' */ + 152, /* '-' */ + 151, /* '.' */ + 165, /* '/' */ + 165, /* '0' */ + 156, /* '1' */ + 156, /* '2' */ + 156, /* '3' */ + 156, /* '4' */ + 162, /* '5' */ + 70, /* '6' */ + 165, /* '7' */ + 63, /* '8' */ + 156, /* '9' */ + 86, /* ':' */ + 152, /* ';' */ + 124, /* '<' */ + 156, /* '=' */ + 156, /* '>' */ + 152, /* '?' */ + 152, /* '@' */ + 173, /* 'A' */ + 143, /* 'B' */ + 158, /* 'C' */ + 124, /* 'D' */ + 119, /* 'E' */ + 158, /* 'F' */ + 194, /* 'G' */ + 168, /* 'H' */ + 185, /* 'I' */ + 158, /* 'J' */ + 186, /* 'K' */ + 158, /* 'L' */ + 194, /* 'M' */ + 168, /* 'N' */ + 192, /* 'O' */ + 164, /* 'P' */ + 186, /* 'Q' */ + 159, /* 'R' */ + 198, /* 'S' */ + 164, /* 'T' */ + 194, /* 'U' */ + 168, /* 'V' */ + 185, /* 'W' */ + 158, /* 'X' */ + 186, /* 'Y' */ + 158, /* 'Z' */ + 194, /* '[' */ + 168, /* '\' */ + 194, /* ']' */ + 165, /* '^' */ + 185, /* '_' */ + 156, /* '`' */ + 186, /* 'a' */ + 156, /* 'b' */ + 194, /* 'c' */ + 165, /* 'd' */ + 186, /* 'e' */ + 156, /* 'f' */ + 197, /* 'g' */ + 167, /* 'h' */ + 187, /* 'i' */ + 158, /* 'j' */ + 188, /* 'k' */ + 158, /* 'l' */ + 197, /* 'm' */ + 167, /* 'n' */ + 188, /* 'o' */ + 159, /* 'p' */ + 187, /* 'q' */ + 158, /* 'r' */ + 197, /* 's' */ + 168, /* 't' */ + 187, /* 'u' */ + 158, /* 'v' */ + 188, /* 'w' */ + 158, /* 'x' */ + 197, /* 'y' */ + 167, /* 'z' */ + 186, /* '{' */ + 188, /* '|' */ + 185, /* '}' */ + 156, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XAB */ + { + 199, /* ' ' */ + 132, /* '!' */ + 142, /* '"' */ + 138, /* '#' */ + 138, /* '$' */ + 92, /* '%' */ + 92, /* '&' */ + 92, /* ''' */ + 92, /* '(' */ + 138, /* ')' */ + 138, /* '*' */ + 95, /* '+' */ + 35, /* ',' */ + 138, /* '-' */ + 105, /* '.' */ + 151, /* '/' */ + 151, /* '0' */ + 142, /* '1' */ + 142, /* '2' */ + 142, /* '3' */ + 142, /* '4' */ + 148, /* '5' */ + 14, /* '6' */ + 151, /* '7' */ + 14, /* '8' */ + 142, /* '9' */ + 72, /* ':' */ + 138, /* ';' */ + 108, /* '<' */ + 142, /* '=' */ + 142, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 149, /* 'A' */ + 118, /* 'B' */ + 142, /* 'C' */ + 108, /* 'D' */ + 105, /* 'E' */ + 142, /* 'F' */ + 181, /* 'G' */ + 151, /* 'H' */ + 171, /* 'I' */ + 142, /* 'J' */ + 172, /* 'K' */ + 142, /* 'L' */ + 181, /* 'M' */ + 151, /* 'N' */ + 178, /* 'O' */ + 148, /* 'P' */ + 172, /* 'Q' */ + 143, /* 'R' */ + 142, /* 'S' */ + 108, /* 'T' */ + 181, /* 'U' */ + 151, /* 'V' */ + 171, /* 'W' */ + 142, /* 'X' */ + 172, /* 'Y' */ + 142, /* 'Z' */ + 181, /* '[' */ + 151, /* '\' */ + 181, /* ']' */ + 151, /* '^' */ + 171, /* '_' */ + 142, /* '`' */ + 172, /* 'a' */ + 142, /* 'b' */ + 181, /* 'c' */ + 151, /* 'd' */ + 172, /* 'e' */ + 143, /* 'f' */ + 181, /* 'g' */ + 151, /* 'h' */ + 171, /* 'i' */ + 142, /* 'j' */ + 172, /* 'k' */ + 142, /* 'l' */ + 181, /* 'm' */ + 151, /* 'n' */ + 172, /* 'o' */ + 143, /* 'p' */ + 171, /* 'q' */ + 142, /* 'r' */ + 181, /* 's' */ + 151, /* 't' */ + 171, /* 'u' */ + 142, /* 'v' */ + 172, /* 'w' */ + 142, /* 'x' */ + 181, /* 'y' */ + 151, /* 'z' */ + 172, /* '{' */ + 142, /* '|' */ + 171, /* '}' */ + 142, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-AvantGarde-Demi", + 0, + NO + }, { + /* width table for font XAX */ + { + 47, /* ' ' */ + 93, /* '!' */ + 93, /* '"' */ + 93, /* '#' */ + 80, /* '$' */ + 77, /* '%' */ + 77, /* '&' */ + 40, /* ''' */ + 40, /* '(' */ + 93, /* ')' */ + 93, /* '*' */ + 100, /* '+' */ + 80, /* ',' */ + 80, /* '-' */ + 93, /* '.' */ + 70, /* '/' */ + 70, /* '0' */ + 70, /* '1' */ + 80, /* '2' */ + 47, /* '3' */ + 83, /* '4' */ + 60, /* '5' */ + 57, /* '6' */ + 117, /* '7' */ + 57, /* '8' */ + 90, /* '9' */ + 167, /* ':' */ + 150, /* ';' */ + 180, /* '<' */ + 60, /* '=' */ + 60, /* '>' */ + 80, /* '?' */ + 53, /* '@' */ + 140, /* 'A' */ + 110, /* 'B' */ + 177, /* 'C' */ + 180, /* 'D' */ + 40, /* 'E' */ + 100, /* 'F' */ + 123, /* 'G' */ + 110, /* 'H' */ + 123, /* 'I' */ + 110, /* 'J' */ + 123, /* 'K' */ + 110, /* 'L' */ + 123, /* 'M' */ + 110, /* 'N' */ + 123, /* 'O' */ + 110, /* 'P' */ + 123, /* 'Q' */ + 110, /* 'R' */ + 130, /* 'S' */ + 107, /* 'T' */ + 87, /* 'U' */ + 107, /* 'V' */ + 87, /* 'W' */ + 107, /* 'X' */ + 87, /* 'Y' */ + 107, /* 'Z' */ + 87, /* '[' */ + 107, /* '\' */ + 47, /* ']' */ + 40, /* '^' */ + 47, /* '_' */ + 40, /* '`' */ + 47, /* 'a' */ + 40, /* 'b' */ + 47, /* 'c' */ + 40, /* 'd' */ + 123, /* 'e' */ + 100, /* 'f' */ + 140, /* 'g' */ + 107, /* 'h' */ + 140, /* 'i' */ + 107, /* 'j' */ + 140, /* 'k' */ + 107, /* 'l' */ + 140, /* 'm' */ + 107, /* 'n' */ + 140, /* 'o' */ + 107, /* 'p' */ + 87, /* 'q' */ + 73, /* 'r' */ + 107, /* 's' */ + 100, /* 't' */ + 107, /* 'u' */ + 100, /* 'v' */ + 107, /* 'w' */ + 100, /* 'x' */ + 107, /* 'y' */ + 100, /* 'z' */ + 103, /* '{' */ + 97, /* '|' */ + 83, /* '}' */ + 77, /* '~' */ + 47, /* ' ' */ + }, + /* height table for font XAX */ + { + 276, /* ' ' */ + 146, /* '!' */ + 156, /* '"' */ + 152, /* '#' */ + 152, /* '$' */ + 106, /* '%' */ + 106, /* '&' */ + 106, /* ''' */ + 106, /* '(' */ + 174, /* ')' */ + 174, /* '*' */ + 109, /* '+' */ + 73, /* ',' */ + 152, /* '-' */ + 151, /* '.' */ + 166, /* '/' */ + 166, /* '0' */ + 156, /* '1' */ + 155, /* '2' */ + 156, /* '3' */ + 156, /* '4' */ + 166, /* '5' */ + 70, /* '6' */ + 167, /* '7' */ + 63, /* '8' */ + 156, /* '9' */ + 86, /* ':' */ + 152, /* ';' */ + 124, /* '<' */ + 156, /* '=' */ + 156, /* '>' */ + 152, /* '?' */ + 152, /* '@' */ + 179, /* 'A' */ + 142, /* 'B' */ + 158, /* 'C' */ + 124, /* 'D' */ + 119, /* 'E' */ + 158, /* 'F' */ + 196, /* 'G' */ + 169, /* 'H' */ + 186, /* 'I' */ + 158, /* 'J' */ + 186, /* 'K' */ + 158, /* 'L' */ + 196, /* 'M' */ + 169, /* 'N' */ + 192, /* 'O' */ + 168, /* 'P' */ + 185, /* 'Q' */ + 158, /* 'R' */ + 198, /* 'S' */ + 164, /* 'T' */ + 196, /* 'U' */ + 169, /* 'V' */ + 186, /* 'W' */ + 158, /* 'X' */ + 186, /* 'Y' */ + 158, /* 'Z' */ + 196, /* '[' */ + 169, /* '\' */ + 196, /* ']' */ + 166, /* '^' */ + 186, /* '_' */ + 156, /* '`' */ + 186, /* 'a' */ + 156, /* 'b' */ + 196, /* 'c' */ + 166, /* 'd' */ + 185, /* 'e' */ + 156, /* 'f' */ + 198, /* 'g' */ + 169, /* 'h' */ + 188, /* 'i' */ + 158, /* 'j' */ + 188, /* 'k' */ + 158, /* 'l' */ + 198, /* 'm' */ + 169, /* 'n' */ + 188, /* 'o' */ + 158, /* 'p' */ + 188, /* 'q' */ + 158, /* 'r' */ + 198, /* 's' */ + 169, /* 't' */ + 188, /* 'u' */ + 158, /* 'v' */ + 188, /* 'w' */ + 158, /* 'x' */ + 198, /* 'y' */ + 169, /* 'z' */ + 186, /* '{' */ + 188, /* '|' */ + 186, /* '}' */ + 156, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XAX */ + { + 199, /* ' ' */ + 132, /* '!' */ + 142, /* '"' */ + 138, /* '#' */ + 138, /* '$' */ + 92, /* '%' */ + 92, /* '&' */ + 92, /* ''' */ + 92, /* '(' */ + 138, /* ')' */ + 138, /* '*' */ + 95, /* '+' */ + 35, /* ',' */ + 138, /* '-' */ + 105, /* '.' */ + 153, /* '/' */ + 153, /* '0' */ + 142, /* '1' */ + 142, /* '2' */ + 142, /* '3' */ + 142, /* '4' */ + 152, /* '5' */ + 14, /* '6' */ + 154, /* '7' */ + 14, /* '8' */ + 142, /* '9' */ + 72, /* ':' */ + 138, /* ';' */ + 108, /* '<' */ + 142, /* '=' */ + 142, /* '>' */ + 138, /* '?' */ + 138, /* '@' */ + 152, /* 'A' */ + 117, /* 'B' */ + 142, /* 'C' */ + 108, /* 'D' */ + 105, /* 'E' */ + 142, /* 'F' */ + 182, /* 'G' */ + 153, /* 'H' */ + 172, /* 'I' */ + 142, /* 'J' */ + 172, /* 'K' */ + 142, /* 'L' */ + 182, /* 'M' */ + 153, /* 'N' */ + 178, /* 'O' */ + 152, /* 'P' */ + 172, /* 'Q' */ + 142, /* 'R' */ + 142, /* 'S' */ + 108, /* 'T' */ + 182, /* 'U' */ + 153, /* 'V' */ + 172, /* 'W' */ + 142, /* 'X' */ + 172, /* 'Y' */ + 142, /* 'Z' */ + 182, /* '[' */ + 153, /* '\' */ + 182, /* ']' */ + 153, /* '^' */ + 172, /* '_' */ + 142, /* '`' */ + 172, /* 'a' */ + 142, /* 'b' */ + 182, /* 'c' */ + 153, /* 'd' */ + 172, /* 'e' */ + 142, /* 'f' */ + 182, /* 'g' */ + 153, /* 'h' */ + 172, /* 'i' */ + 142, /* 'j' */ + 172, /* 'k' */ + 142, /* 'l' */ + 182, /* 'm' */ + 153, /* 'n' */ + 171, /* 'o' */ + 142, /* 'p' */ + 172, /* 'q' */ + 142, /* 'r' */ + 182, /* 's' */ + 153, /* 't' */ + 172, /* 'u' */ + 142, /* 'v' */ + 172, /* 'w' */ + 142, /* 'x' */ + 182, /* 'y' */ + 153, /* 'z' */ + 172, /* '{' */ + 142, /* '|' */ + 172, /* '}' */ + 142, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-AvantGarde-DemiOblique", + 0, + YES + }, { + /* width table for font XCR */ + { + 100, /* ' ' */ + 100, /* '!' */ + 100, /* '"' */ + 100, /* '#' */ + 100, /* '$' */ + 100, /* '%' */ + 100, /* '&' */ + 100, /* ''' */ + 100, /* '(' */ + 100, /* ')' */ + 100, /* '*' */ + 100, /* '+' */ + 100, /* ',' */ + 100, /* '-' */ + 100, /* '.' */ + 100, /* '/' */ + 100, /* '0' */ + 100, /* '1' */ + 100, /* '2' */ + 100, /* '3' */ + 100, /* '4' */ + 100, /* '5' */ + 100, /* '6' */ + 100, /* '7' */ + 100, /* '8' */ + 100, /* '9' */ + 100, /* ':' */ + 100, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 100, /* '?' */ + 100, /* '@' */ + 100, /* 'A' */ + 100, /* 'B' */ + 100, /* 'C' */ + 100, /* 'D' */ + 100, /* 'E' */ + 100, /* 'F' */ + 100, /* 'G' */ + 100, /* 'H' */ + 100, /* 'I' */ + 100, /* 'J' */ + 100, /* 'K' */ + 100, /* 'L' */ + 100, /* 'M' */ + 100, /* 'N' */ + 100, /* 'O' */ + 100, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 100, /* 'S' */ + 100, /* 'T' */ + 100, /* 'U' */ + 100, /* 'V' */ + 100, /* 'W' */ + 100, /* 'X' */ + 100, /* 'Y' */ + 100, /* 'Z' */ + 100, /* '[' */ + 100, /* '\' */ + 100, /* ']' */ + 100, /* '^' */ + 100, /* '_' */ + 100, /* '`' */ + 100, /* 'a' */ + 100, /* 'b' */ + 100, /* 'c' */ + 100, /* 'd' */ + 100, /* 'e' */ + 100, /* 'f' */ + 100, /* 'g' */ + 100, /* 'h' */ + 100, /* 'i' */ + 100, /* 'j' */ + 100, /* 'k' */ + 100, /* 'l' */ + 100, /* 'm' */ + 100, /* 'n' */ + 100, /* 'o' */ + 100, /* 'p' */ + 100, /* 'q' */ + 100, /* 'r' */ + 100, /* 's' */ + 100, /* 't' */ + 100, /* 'u' */ + 100, /* 'v' */ + 100, /* 'w' */ + 100, /* 'x' */ + 100, /* 'y' */ + 100, /* 'z' */ + 100, /* '{' */ + 100, /* '|' */ + 100, /* '}' */ + 100, /* '~' */ + 100, /* ' ' */ + }, + /* height table for font XCR */ + { + 260, /* ' ' */ + 134, /* '!' */ + 126, /* '"' */ + 122, /* '#' */ + 128, /* '$' */ + 99, /* '%' */ + 99, /* '&' */ + 99, /* ''' */ + 99, /* '(' */ + 139, /* ')' */ + 139, /* '*' */ + 84, /* '+' */ + 71, /* ',' */ + 128, /* '-' */ + 128, /* '.' */ + 134, /* '/' */ + 134, /* '0' */ + 126, /* '1' */ + 131, /* '2' */ + 130, /* '3' */ + 130, /* '4' */ + 139, /* '5' */ + 58, /* '6' */ + 133, /* '7' */ + 53, /* '8' */ + 134, /* '9' */ + 79, /* ':' */ + 122, /* ';' */ + 104, /* '<' */ + 126, /* '=' */ + 126, /* '>' */ + 122, /* '?' */ + 129, /* '@' */ + 136, /* 'A' */ + 111, /* 'B' */ + 122, /* 'C' */ + 104, /* 'D' */ + 99, /* 'E' */ + 131, /* 'F' */ + 159, /* 'G' */ + 137, /* 'H' */ + 159, /* 'I' */ + 137, /* 'J' */ + 155, /* 'K' */ + 132, /* 'L' */ + 159, /* 'M' */ + 136, /* 'N' */ + 162, /* 'O' */ + 141, /* 'P' */ + 152, /* 'Q' */ + 131, /* 'R' */ + 154, /* 'S' */ + 131, /* 'T' */ + 159, /* 'U' */ + 136, /* 'V' */ + 159, /* 'W' */ + 136, /* 'X' */ + 155, /* 'Y' */ + 132, /* 'Z' */ + 159, /* '[' */ + 136, /* '\' */ + 159, /* ']' */ + 134, /* '^' */ + 159, /* '_' */ + 134, /* '`' */ + 156, /* 'a' */ + 132, /* 'b' */ + 159, /* 'c' */ + 134, /* 'd' */ + 152, /* 'e' */ + 129, /* 'f' */ + 161, /* 'g' */ + 137, /* 'h' */ + 161, /* 'i' */ + 137, /* 'j' */ + 157, /* 'k' */ + 132, /* 'l' */ + 161, /* 'm' */ + 137, /* 'n' */ + 154, /* 'o' */ + 131, /* 'p' */ + 161, /* 'q' */ + 136, /* 'r' */ + 161, /* 's' */ + 136, /* 't' */ + 161, /* 'u' */ + 136, /* 'v' */ + 157, /* 'w' */ + 132, /* 'x' */ + 161, /* 'y' */ + 136, /* 'z' */ + 155, /* '{' */ + 159, /* '|' */ + 159, /* '}' */ + 134, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XCR */ + { + 179, /* ' ' */ + 118, /* '!' */ + 112, /* '"' */ + 108, /* '#' */ + 115, /* '$' */ + 85, /* '%' */ + 85, /* '&' */ + 85, /* ''' */ + 85, /* '(' */ + 115, /* ')' */ + 115, /* '*' */ + 70, /* '+' */ + 38, /* ',' */ + 115, /* '-' */ + 85, /* '.' */ + 120, /* '/' */ + 120, /* '0' */ + 112, /* '1' */ + 117, /* '2' */ + 116, /* '3' */ + 116, /* '4' */ + 125, /* '5' */ + 15, /* '6' */ + 119, /* '7' */ + 14, /* '8' */ + 120, /* '9' */ + 65, /* ':' */ + 108, /* ';' */ + 88, /* '<' */ + 112, /* '=' */ + 112, /* '>' */ + 108, /* '?' */ + 115, /* '@' */ + 115, /* 'A' */ + 90, /* 'B' */ + 108, /* 'C' */ + 88, /* 'D' */ + 85, /* 'E' */ + 115, /* 'F' */ + 145, /* 'G' */ + 120, /* 'H' */ + 145, /* 'I' */ + 120, /* 'J' */ + 141, /* 'K' */ + 116, /* 'L' */ + 145, /* 'M' */ + 120, /* 'N' */ + 148, /* 'O' */ + 125, /* 'P' */ + 138, /* 'Q' */ + 115, /* 'R' */ + 112, /* 'S' */ + 88, /* 'T' */ + 145, /* 'U' */ + 120, /* 'V' */ + 145, /* 'W' */ + 120, /* 'X' */ + 141, /* 'Y' */ + 116, /* 'Z' */ + 145, /* '[' */ + 120, /* '\' */ + 145, /* ']' */ + 120, /* '^' */ + 145, /* '_' */ + 120, /* '`' */ + 142, /* 'a' */ + 118, /* 'b' */ + 145, /* 'c' */ + 120, /* 'd' */ + 138, /* 'e' */ + 115, /* 'f' */ + 145, /* 'g' */ + 120, /* 'h' */ + 145, /* 'i' */ + 120, /* 'j' */ + 141, /* 'k' */ + 116, /* 'l' */ + 145, /* 'm' */ + 120, /* 'n' */ + 138, /* 'o' */ + 115, /* 'p' */ + 145, /* 'q' */ + 120, /* 'r' */ + 145, /* 's' */ + 120, /* 't' */ + 145, /* 'u' */ + 120, /* 'v' */ + 141, /* 'w' */ + 116, /* 'x' */ + 145, /* 'y' */ + 120, /* 'z' */ + 141, /* '{' */ + 116, /* '|' */ + 145, /* '}' */ + 120, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Courier", + 0, + NO + }, { + /* width table for font XCI */ + { + 100, /* ' ' */ + 100, /* '!' */ + 100, /* '"' */ + 100, /* '#' */ + 100, /* '$' */ + 100, /* '%' */ + 100, /* '&' */ + 100, /* ''' */ + 100, /* '(' */ + 100, /* ')' */ + 100, /* '*' */ + 100, /* '+' */ + 100, /* ',' */ + 100, /* '-' */ + 100, /* '.' */ + 100, /* '/' */ + 100, /* '0' */ + 100, /* '1' */ + 100, /* '2' */ + 100, /* '3' */ + 100, /* '4' */ + 100, /* '5' */ + 100, /* '6' */ + 100, /* '7' */ + 100, /* '8' */ + 100, /* '9' */ + 100, /* ':' */ + 100, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 100, /* '?' */ + 100, /* '@' */ + 100, /* 'A' */ + 100, /* 'B' */ + 100, /* 'C' */ + 100, /* 'D' */ + 100, /* 'E' */ + 100, /* 'F' */ + 100, /* 'G' */ + 100, /* 'H' */ + 100, /* 'I' */ + 100, /* 'J' */ + 100, /* 'K' */ + 100, /* 'L' */ + 100, /* 'M' */ + 100, /* 'N' */ + 100, /* 'O' */ + 100, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 100, /* 'S' */ + 100, /* 'T' */ + 100, /* 'U' */ + 100, /* 'V' */ + 100, /* 'W' */ + 100, /* 'X' */ + 100, /* 'Y' */ + 100, /* 'Z' */ + 100, /* '[' */ + 100, /* '\' */ + 100, /* ']' */ + 100, /* '^' */ + 100, /* '_' */ + 100, /* '`' */ + 100, /* 'a' */ + 100, /* 'b' */ + 100, /* 'c' */ + 100, /* 'd' */ + 100, /* 'e' */ + 100, /* 'f' */ + 100, /* 'g' */ + 100, /* 'h' */ + 100, /* 'i' */ + 100, /* 'j' */ + 100, /* 'k' */ + 100, /* 'l' */ + 100, /* 'm' */ + 100, /* 'n' */ + 100, /* 'o' */ + 100, /* 'p' */ + 100, /* 'q' */ + 100, /* 'r' */ + 100, /* 's' */ + 100, /* 't' */ + 100, /* 'u' */ + 100, /* 'v' */ + 100, /* 'w' */ + 100, /* 'x' */ + 100, /* 'y' */ + 100, /* 'z' */ + 100, /* '{' */ + 100, /* '|' */ + 100, /* '}' */ + 100, /* '~' */ + 100, /* ' ' */ + }, + /* height table for font XCI */ + { + 260, /* ' ' */ + 134, /* '!' */ + 126, /* '"' */ + 122, /* '#' */ + 129, /* '$' */ + 99, /* '%' */ + 99, /* '&' */ + 99, /* ''' */ + 99, /* '(' */ + 139, /* ')' */ + 139, /* '*' */ + 84, /* '+' */ + 71, /* ',' */ + 128, /* '-' */ + 128, /* '.' */ + 134, /* '/' */ + 134, /* '0' */ + 126, /* '1' */ + 131, /* '2' */ + 130, /* '3' */ + 130, /* '4' */ + 139, /* '5' */ + 57, /* '6' */ + 133, /* '7' */ + 53, /* '8' */ + 134, /* '9' */ + 79, /* ':' */ + 122, /* ';' */ + 104, /* '<' */ + 126, /* '=' */ + 126, /* '>' */ + 122, /* '?' */ + 129, /* '@' */ + 136, /* 'A' */ + 111, /* 'B' */ + 122, /* 'C' */ + 104, /* 'D' */ + 99, /* 'E' */ + 131, /* 'F' */ + 159, /* 'G' */ + 137, /* 'H' */ + 159, /* 'I' */ + 137, /* 'J' */ + 155, /* 'K' */ + 132, /* 'L' */ + 159, /* 'M' */ + 137, /* 'N' */ + 162, /* 'O' */ + 141, /* 'P' */ + 152, /* 'Q' */ + 131, /* 'R' */ + 154, /* 'S' */ + 131, /* 'T' */ + 159, /* 'U' */ + 136, /* 'V' */ + 159, /* 'W' */ + 136, /* 'X' */ + 155, /* 'Y' */ + 132, /* 'Z' */ + 159, /* '[' */ + 136, /* '\' */ + 159, /* ']' */ + 134, /* '^' */ + 159, /* '_' */ + 134, /* '`' */ + 155, /* 'a' */ + 130, /* 'b' */ + 159, /* 'c' */ + 134, /* 'd' */ + 152, /* 'e' */ + 129, /* 'f' */ + 161, /* 'g' */ + 136, /* 'h' */ + 161, /* 'i' */ + 136, /* 'j' */ + 157, /* 'k' */ + 132, /* 'l' */ + 161, /* 'm' */ + 136, /* 'n' */ + 154, /* 'o' */ + 131, /* 'p' */ + 162, /* 'q' */ + 136, /* 'r' */ + 161, /* 's' */ + 136, /* 't' */ + 161, /* 'u' */ + 136, /* 'v' */ + 157, /* 'w' */ + 132, /* 'x' */ + 161, /* 'y' */ + 137, /* 'z' */ + 155, /* '{' */ + 159, /* '|' */ + 159, /* '}' */ + 134, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XCI */ + { + 179, /* ' ' */ + 118, /* '!' */ + 112, /* '"' */ + 108, /* '#' */ + 115, /* '$' */ + 85, /* '%' */ + 85, /* '&' */ + 85, /* ''' */ + 85, /* '(' */ + 115, /* ')' */ + 115, /* '*' */ + 70, /* '+' */ + 38, /* ',' */ + 115, /* '-' */ + 85, /* '.' */ + 120, /* '/' */ + 120, /* '0' */ + 112, /* '1' */ + 117, /* '2' */ + 116, /* '3' */ + 116, /* '4' */ + 125, /* '5' */ + 14, /* '6' */ + 119, /* '7' */ + 14, /* '8' */ + 120, /* '9' */ + 65, /* ':' */ + 108, /* ';' */ + 88, /* '<' */ + 112, /* '=' */ + 112, /* '>' */ + 108, /* '?' */ + 115, /* '@' */ + 115, /* 'A' */ + 90, /* 'B' */ + 108, /* 'C' */ + 88, /* 'D' */ + 85, /* 'E' */ + 115, /* 'F' */ + 145, /* 'G' */ + 120, /* 'H' */ + 145, /* 'I' */ + 120, /* 'J' */ + 141, /* 'K' */ + 116, /* 'L' */ + 145, /* 'M' */ + 120, /* 'N' */ + 148, /* 'O' */ + 125, /* 'P' */ + 138, /* 'Q' */ + 115, /* 'R' */ + 112, /* 'S' */ + 88, /* 'T' */ + 145, /* 'U' */ + 120, /* 'V' */ + 145, /* 'W' */ + 120, /* 'X' */ + 141, /* 'Y' */ + 116, /* 'Z' */ + 145, /* '[' */ + 120, /* '\' */ + 145, /* ']' */ + 120, /* '^' */ + 145, /* '_' */ + 120, /* '`' */ + 141, /* 'a' */ + 116, /* 'b' */ + 145, /* 'c' */ + 120, /* 'd' */ + 138, /* 'e' */ + 115, /* 'f' */ + 145, /* 'g' */ + 120, /* 'h' */ + 145, /* 'i' */ + 120, /* 'j' */ + 141, /* 'k' */ + 116, /* 'l' */ + 145, /* 'm' */ + 120, /* 'n' */ + 138, /* 'o' */ + 115, /* 'p' */ + 145, /* 'q' */ + 120, /* 'r' */ + 145, /* 's' */ + 120, /* 't' */ + 145, /* 'u' */ + 120, /* 'v' */ + 141, /* 'w' */ + 116, /* 'x' */ + 145, /* 'y' */ + 120, /* 'z' */ + 141, /* '{' */ + 116, /* '|' */ + 145, /* '}' */ + 120, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Courier-Italic", + 0, + YES + }, { + /* width table for font XCB */ + { + 100, /* ' ' */ + 100, /* '!' */ + 100, /* '"' */ + 100, /* '#' */ + 100, /* '$' */ + 100, /* '%' */ + 100, /* '&' */ + 100, /* ''' */ + 100, /* '(' */ + 100, /* ')' */ + 100, /* '*' */ + 100, /* '+' */ + 100, /* ',' */ + 100, /* '-' */ + 100, /* '.' */ + 100, /* '/' */ + 100, /* '0' */ + 100, /* '1' */ + 100, /* '2' */ + 100, /* '3' */ + 100, /* '4' */ + 100, /* '5' */ + 100, /* '6' */ + 100, /* '7' */ + 100, /* '8' */ + 100, /* '9' */ + 100, /* ':' */ + 100, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 100, /* '?' */ + 100, /* '@' */ + 100, /* 'A' */ + 100, /* 'B' */ + 100, /* 'C' */ + 100, /* 'D' */ + 100, /* 'E' */ + 100, /* 'F' */ + 100, /* 'G' */ + 100, /* 'H' */ + 100, /* 'I' */ + 100, /* 'J' */ + 100, /* 'K' */ + 100, /* 'L' */ + 100, /* 'M' */ + 100, /* 'N' */ + 100, /* 'O' */ + 100, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 100, /* 'S' */ + 100, /* 'T' */ + 100, /* 'U' */ + 100, /* 'V' */ + 100, /* 'W' */ + 100, /* 'X' */ + 100, /* 'Y' */ + 100, /* 'Z' */ + 100, /* '[' */ + 100, /* '\' */ + 100, /* ']' */ + 100, /* '^' */ + 100, /* '_' */ + 100, /* '`' */ + 100, /* 'a' */ + 100, /* 'b' */ + 100, /* 'c' */ + 100, /* 'd' */ + 100, /* 'e' */ + 100, /* 'f' */ + 100, /* 'g' */ + 100, /* 'h' */ + 100, /* 'i' */ + 100, /* 'j' */ + 100, /* 'k' */ + 100, /* 'l' */ + 100, /* 'm' */ + 100, /* 'n' */ + 100, /* 'o' */ + 100, /* 'p' */ + 100, /* 'q' */ + 100, /* 'r' */ + 100, /* 's' */ + 100, /* 't' */ + 100, /* 'u' */ + 100, /* 'v' */ + 100, /* 'w' */ + 100, /* 'x' */ + 100, /* 'y' */ + 100, /* 'z' */ + 100, /* '{' */ + 100, /* '|' */ + 100, /* '}' */ + 100, /* '~' */ + 100, /* ' ' */ + }, + /* height table for font XCB */ + { + 263, /* ' ' */ + 148, /* '!' */ + 129, /* '"' */ + 124, /* '#' */ + 129, /* '$' */ + 97, /* '%' */ + 97, /* '&' */ + 97, /* ''' */ + 97, /* '(' */ + 147, /* ')' */ + 147, /* '*' */ + 106, /* '+' */ + 70, /* ',' */ + 129, /* '-' */ + 131, /* '.' */ + 144, /* '/' */ + 144, /* '0' */ + 132, /* '1' */ + 142, /* '2' */ + 137, /* '3' */ + 137, /* '4' */ + 149, /* '5' */ + 68, /* '6' */ + 143, /* '7' */ + 63, /* '8' */ + 144, /* '9' */ + 82, /* ':' */ + 126, /* ';' */ + 108, /* '<' */ + 129, /* '=' */ + 129, /* '>' */ + 126, /* '?' */ + 132, /* '@' */ + 146, /* 'A' */ + 122, /* 'B' */ + 126, /* 'C' */ + 108, /* 'D' */ + 102, /* 'E' */ + 134, /* 'F' */ + 168, /* 'G' */ + 146, /* 'H' */ + 168, /* 'I' */ + 146, /* 'J' */ + 161, /* 'K' */ + 139, /* 'L' */ + 168, /* 'M' */ + 146, /* 'N' */ + 172, /* 'O' */ + 151, /* 'P' */ + 161, /* 'Q' */ + 139, /* 'R' */ + 168, /* 'S' */ + 144, /* 'T' */ + 168, /* 'U' */ + 146, /* 'V' */ + 168, /* 'W' */ + 146, /* 'X' */ + 161, /* 'Y' */ + 139, /* 'Z' */ + 168, /* '[' */ + 146, /* '\' */ + 168, /* ']' */ + 144, /* '^' */ + 168, /* '_' */ + 144, /* '`' */ + 162, /* 'a' */ + 136, /* 'b' */ + 168, /* 'c' */ + 144, /* 'd' */ + 161, /* 'e' */ + 137, /* 'f' */ + 170, /* 'g' */ + 146, /* 'h' */ + 170, /* 'i' */ + 146, /* 'j' */ + 163, /* 'k' */ + 139, /* 'l' */ + 170, /* 'm' */ + 146, /* 'n' */ + 163, /* 'o' */ + 139, /* 'p' */ + 170, /* 'q' */ + 146, /* 'r' */ + 170, /* 's' */ + 146, /* 't' */ + 170, /* 'u' */ + 146, /* 'v' */ + 163, /* 'w' */ + 139, /* 'x' */ + 170, /* 'y' */ + 146, /* 'z' */ + 161, /* '{' */ + 172, /* '|' */ + 168, /* '}' */ + 144, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XCB */ + { + 179, /* ' ' */ + 125, /* '!' */ + 115, /* '"' */ + 111, /* '#' */ + 115, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 83, /* ''' */ + 83, /* '(' */ + 118, /* ')' */ + 118, /* '*' */ + 92, /* '+' */ + 36, /* ',' */ + 115, /* '-' */ + 78, /* '.' */ + 130, /* '/' */ + 130, /* '0' */ + 118, /* '1' */ + 128, /* '2' */ + 123, /* '3' */ + 123, /* '4' */ + 135, /* '5' */ + 15, /* '6' */ + 130, /* '7' */ + 14, /* '8' */ + 130, /* '9' */ + 68, /* ':' */ + 112, /* ';' */ + 92, /* '<' */ + 115, /* '=' */ + 115, /* '>' */ + 112, /* '?' */ + 118, /* '@' */ + 120, /* 'A' */ + 96, /* 'B' */ + 112, /* 'C' */ + 92, /* 'D' */ + 88, /* 'E' */ + 118, /* 'F' */ + 154, /* 'G' */ + 130, /* 'H' */ + 154, /* 'I' */ + 130, /* 'J' */ + 147, /* 'K' */ + 123, /* 'L' */ + 154, /* 'M' */ + 130, /* 'N' */ + 158, /* 'O' */ + 135, /* 'P' */ + 147, /* 'Q' */ + 123, /* 'R' */ + 115, /* 'S' */ + 92, /* 'T' */ + 154, /* 'U' */ + 130, /* 'V' */ + 154, /* 'W' */ + 130, /* 'X' */ + 147, /* 'Y' */ + 123, /* 'Z' */ + 154, /* '[' */ + 130, /* '\' */ + 154, /* ']' */ + 130, /* '^' */ + 154, /* '_' */ + 130, /* '`' */ + 148, /* 'a' */ + 122, /* 'b' */ + 154, /* 'c' */ + 130, /* 'd' */ + 147, /* 'e' */ + 123, /* 'f' */ + 154, /* 'g' */ + 130, /* 'h' */ + 154, /* 'i' */ + 130, /* 'j' */ + 147, /* 'k' */ + 123, /* 'l' */ + 154, /* 'm' */ + 130, /* 'n' */ + 147, /* 'o' */ + 123, /* 'p' */ + 154, /* 'q' */ + 130, /* 'r' */ + 154, /* 's' */ + 130, /* 't' */ + 154, /* 'u' */ + 130, /* 'v' */ + 147, /* 'w' */ + 123, /* 'x' */ + 154, /* 'y' */ + 130, /* 'z' */ + 147, /* '{' */ + 123, /* '|' */ + 154, /* '}' */ + 130, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Courier-Bold", + 0, + NO + }, { + /* width table for font XCX */ + { + 100, /* ' ' */ + 100, /* '!' */ + 100, /* '"' */ + 100, /* '#' */ + 100, /* '$' */ + 100, /* '%' */ + 100, /* '&' */ + 100, /* ''' */ + 100, /* '(' */ + 100, /* ')' */ + 100, /* '*' */ + 100, /* '+' */ + 100, /* ',' */ + 100, /* '-' */ + 100, /* '.' */ + 100, /* '/' */ + 100, /* '0' */ + 100, /* '1' */ + 100, /* '2' */ + 100, /* '3' */ + 100, /* '4' */ + 100, /* '5' */ + 100, /* '6' */ + 100, /* '7' */ + 100, /* '8' */ + 100, /* '9' */ + 100, /* ':' */ + 100, /* ';' */ + 100, /* '<' */ + 100, /* '=' */ + 100, /* '>' */ + 100, /* '?' */ + 100, /* '@' */ + 100, /* 'A' */ + 100, /* 'B' */ + 100, /* 'C' */ + 100, /* 'D' */ + 100, /* 'E' */ + 100, /* 'F' */ + 100, /* 'G' */ + 100, /* 'H' */ + 100, /* 'I' */ + 100, /* 'J' */ + 100, /* 'K' */ + 100, /* 'L' */ + 100, /* 'M' */ + 100, /* 'N' */ + 100, /* 'O' */ + 100, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 100, /* 'S' */ + 100, /* 'T' */ + 100, /* 'U' */ + 100, /* 'V' */ + 100, /* 'W' */ + 100, /* 'X' */ + 100, /* 'Y' */ + 100, /* 'Z' */ + 100, /* '[' */ + 100, /* '\' */ + 100, /* ']' */ + 100, /* '^' */ + 100, /* '_' */ + 100, /* '`' */ + 100, /* 'a' */ + 100, /* 'b' */ + 100, /* 'c' */ + 100, /* 'd' */ + 100, /* 'e' */ + 100, /* 'f' */ + 100, /* 'g' */ + 100, /* 'h' */ + 100, /* 'i' */ + 100, /* 'j' */ + 100, /* 'k' */ + 100, /* 'l' */ + 100, /* 'm' */ + 100, /* 'n' */ + 100, /* 'o' */ + 100, /* 'p' */ + 100, /* 'q' */ + 100, /* 'r' */ + 100, /* 's' */ + 100, /* 't' */ + 100, /* 'u' */ + 100, /* 'v' */ + 100, /* 'w' */ + 100, /* 'x' */ + 100, /* 'y' */ + 100, /* 'z' */ + 100, /* '{' */ + 100, /* '|' */ + 100, /* '}' */ + 100, /* '~' */ + 100, /* ' ' */ + }, + /* height table for font XCX */ + { + 263, /* ' ' */ + 148, /* '!' */ + 129, /* '"' */ + 126, /* '#' */ + 129, /* '$' */ + 97, /* '%' */ + 97, /* '&' */ + 97, /* ''' */ + 97, /* '(' */ + 147, /* ')' */ + 147, /* '*' */ + 106, /* '+' */ + 70, /* ',' */ + 129, /* '-' */ + 131, /* '.' */ + 144, /* '/' */ + 144, /* '0' */ + 132, /* '1' */ + 142, /* '2' */ + 137, /* '3' */ + 137, /* '4' */ + 149, /* '5' */ + 68, /* '6' */ + 143, /* '7' */ + 63, /* '8' */ + 144, /* '9' */ + 82, /* ':' */ + 126, /* ';' */ + 108, /* '<' */ + 129, /* '=' */ + 129, /* '>' */ + 126, /* '?' */ + 132, /* '@' */ + 146, /* 'A' */ + 122, /* 'B' */ + 126, /* 'C' */ + 108, /* 'D' */ + 102, /* 'E' */ + 134, /* 'F' */ + 168, /* 'G' */ + 146, /* 'H' */ + 168, /* 'I' */ + 146, /* 'J' */ + 161, /* 'K' */ + 139, /* 'L' */ + 168, /* 'M' */ + 146, /* 'N' */ + 172, /* 'O' */ + 151, /* 'P' */ + 161, /* 'Q' */ + 139, /* 'R' */ + 168, /* 'S' */ + 144, /* 'T' */ + 168, /* 'U' */ + 146, /* 'V' */ + 168, /* 'W' */ + 146, /* 'X' */ + 161, /* 'Y' */ + 139, /* 'Z' */ + 168, /* '[' */ + 146, /* '\' */ + 168, /* ']' */ + 144, /* '^' */ + 168, /* '_' */ + 144, /* '`' */ + 161, /* 'a' */ + 137, /* 'b' */ + 168, /* 'c' */ + 144, /* 'd' */ + 161, /* 'e' */ + 137, /* 'f' */ + 170, /* 'g' */ + 146, /* 'h' */ + 170, /* 'i' */ + 146, /* 'j' */ + 163, /* 'k' */ + 139, /* 'l' */ + 170, /* 'm' */ + 146, /* 'n' */ + 163, /* 'o' */ + 139, /* 'p' */ + 170, /* 'q' */ + 146, /* 'r' */ + 170, /* 's' */ + 146, /* 't' */ + 170, /* 'u' */ + 146, /* 'v' */ + 163, /* 'w' */ + 139, /* 'x' */ + 170, /* 'y' */ + 146, /* 'z' */ + 161, /* '{' */ + 172, /* '|' */ + 168, /* '}' */ + 144, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XCX */ + { + 179, /* ' ' */ + 125, /* '!' */ + 115, /* '"' */ + 112, /* '#' */ + 115, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 83, /* ''' */ + 83, /* '(' */ + 118, /* ')' */ + 118, /* '*' */ + 92, /* '+' */ + 36, /* ',' */ + 115, /* '-' */ + 78, /* '.' */ + 130, /* '/' */ + 130, /* '0' */ + 118, /* '1' */ + 128, /* '2' */ + 123, /* '3' */ + 123, /* '4' */ + 135, /* '5' */ + 15, /* '6' */ + 130, /* '7' */ + 14, /* '8' */ + 130, /* '9' */ + 68, /* ':' */ + 112, /* ';' */ + 92, /* '<' */ + 115, /* '=' */ + 115, /* '>' */ + 112, /* '?' */ + 118, /* '@' */ + 120, /* 'A' */ + 96, /* 'B' */ + 112, /* 'C' */ + 92, /* 'D' */ + 88, /* 'E' */ + 118, /* 'F' */ + 154, /* 'G' */ + 130, /* 'H' */ + 154, /* 'I' */ + 130, /* 'J' */ + 147, /* 'K' */ + 123, /* 'L' */ + 154, /* 'M' */ + 130, /* 'N' */ + 158, /* 'O' */ + 135, /* 'P' */ + 147, /* 'Q' */ + 123, /* 'R' */ + 115, /* 'S' */ + 92, /* 'T' */ + 154, /* 'U' */ + 130, /* 'V' */ + 154, /* 'W' */ + 130, /* 'X' */ + 147, /* 'Y' */ + 123, /* 'Z' */ + 154, /* '[' */ + 130, /* '\' */ + 154, /* ']' */ + 130, /* '^' */ + 154, /* '_' */ + 130, /* '`' */ + 147, /* 'a' */ + 123, /* 'b' */ + 154, /* 'c' */ + 130, /* 'd' */ + 147, /* 'e' */ + 123, /* 'f' */ + 154, /* 'g' */ + 130, /* 'h' */ + 154, /* 'i' */ + 130, /* 'j' */ + 147, /* 'k' */ + 123, /* 'l' */ + 154, /* 'm' */ + 130, /* 'n' */ + 147, /* 'o' */ + 123, /* 'p' */ + 154, /* 'q' */ + 130, /* 'r' */ + 154, /* 's' */ + 130, /* 't' */ + 154, /* 'u' */ + 130, /* 'v' */ + 147, /* 'w' */ + 123, /* 'x' */ + 154, /* 'y' */ + 130, /* 'z' */ + 147, /* '{' */ + 123, /* '|' */ + 154, /* '}' */ + 130, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Courier-BoldItalic", + 0, + YES + }, { + /* width table for font XHR */ + { + 55, /* ' ' */ + 93, /* '!' */ + 93, /* '"' */ + 93, /* '#' */ + 55, /* '$' */ + 93, /* '%' */ + 93, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 93, /* ')' */ + 93, /* '*' */ + 58, /* '+' */ + 55, /* ',' */ + 55, /* '-' */ + 102, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 167, /* ';' */ + 148, /* '<' */ + 62, /* '=' */ + 61, /* '>' */ + 93, /* '?' */ + 37, /* '@' */ + 130, /* 'A' */ + 102, /* 'B' */ + 167, /* 'C' */ + 157, /* 'D' */ + 46, /* 'E' */ + 102, /* 'F' */ + 111, /* 'G' */ + 93, /* 'H' */ + 111, /* 'I' */ + 93, /* 'J' */ + 111, /* 'K' */ + 93, /* 'L' */ + 111, /* 'M' */ + 93, /* 'N' */ + 111, /* 'O' */ + 93, /* 'P' */ + 111, /* 'Q' */ + 93, /* 'R' */ + 120, /* 'S' */ + 83, /* 'T' */ + 111, /* 'U' */ + 93, /* 'V' */ + 111, /* 'W' */ + 93, /* 'X' */ + 111, /* 'Y' */ + 93, /* 'Z' */ + 111, /* '[' */ + 93, /* '\' */ + 46, /* ']' */ + 46, /* '^' */ + 46, /* '_' */ + 46, /* '`' */ + 46, /* 'a' */ + 46, /* 'b' */ + 46, /* 'c' */ + 46, /* 'd' */ + 120, /* 'e' */ + 93, /* 'f' */ + 130, /* 'g' */ + 93, /* 'h' */ + 130, /* 'i' */ + 93, /* 'j' */ + 130, /* 'k' */ + 93, /* 'l' */ + 130, /* 'm' */ + 93, /* 'n' */ + 130, /* 'o' */ + 93, /* 'p' */ + 111, /* 'q' */ + 83, /* 'r' */ + 120, /* 's' */ + 93, /* 't' */ + 120, /* 'u' */ + 93, /* 'v' */ + 120, /* 'w' */ + 93, /* 'x' */ + 120, /* 'y' */ + 93, /* 'z' */ + 111, /* '{' */ + 83, /* '|' */ + 102, /* '}' */ + 83, /* '~' */ + 46, /* ' ' */ + }, + /* height table for font XHR */ + { + 275, /* ' ' */ + 152, /* '!' */ + 152, /* '"' */ + 146, /* '#' */ + 146, /* '$' */ + 101, /* '%' */ + 101, /* '&' */ + 101, /* ''' */ + 101, /* '(' */ + 175, /* ')' */ + 175, /* '*' */ + 106, /* '+' */ + 67, /* ',' */ + 146, /* '-' */ + 151, /* '.' */ + 152, /* '/' */ + 152, /* '0' */ + 146, /* '1' */ + 149, /* '2' */ + 146, /* '3' */ + 146, /* '4' */ + 152, /* '5' */ + 61, /* '6' */ + 152, /* '7' */ + 60, /* '8' */ + 152, /* '9' */ + 79, /* ':' */ + 149, /* ';' */ + 122, /* '<' */ + 152, /* '=' */ + 152, /* '>' */ + 149, /* '?' */ + 149, /* '@' */ + 156, /* 'A' */ + 124, /* 'B' */ + 154, /* 'C' */ + 122, /* 'D' */ + 116, /* 'E' */ + 152, /* 'F' */ + 184, /* 'G' */ + 155, /* 'H' */ + 184, /* 'I' */ + 155, /* 'J' */ + 179, /* 'K' */ + 148, /* 'L' */ + 184, /* 'M' */ + 155, /* 'N' */ + 186, /* 'O' */ + 155, /* 'P' */ + 180, /* 'Q' */ + 150, /* 'R' */ + 188, /* 'S' */ + 154, /* 'T' */ + 184, /* 'U' */ + 155, /* 'V' */ + 184, /* 'W' */ + 155, /* 'X' */ + 179, /* 'Y' */ + 148, /* 'Z' */ + 184, /* '[' */ + 155, /* '\' */ + 184, /* ']' */ + 152, /* '^' */ + 184, /* '_' */ + 152, /* '`' */ + 179, /* 'a' */ + 146, /* 'b' */ + 184, /* 'c' */ + 152, /* 'd' */ + 180, /* 'e' */ + 147, /* 'f' */ + 187, /* 'g' */ + 155, /* 'h' */ + 187, /* 'i' */ + 155, /* 'j' */ + 182, /* 'k' */ + 148, /* 'l' */ + 187, /* 'm' */ + 155, /* 'n' */ + 183, /* 'o' */ + 150, /* 'p' */ + 187, /* 'q' */ + 155, /* 'r' */ + 187, /* 's' */ + 155, /* 't' */ + 187, /* 'u' */ + 155, /* 'v' */ + 182, /* 'w' */ + 148, /* 'x' */ + 187, /* 'y' */ + 155, /* 'z' */ + 179, /* '{' */ + 181, /* '|' */ + 184, /* '}' */ + 152, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XHR */ + { + 196, /* ' ' */ + 119, /* '!' */ + 135, /* '"' */ + 132, /* '#' */ + 132, /* '$' */ + 87, /* '%' */ + 87, /* '&' */ + 87, /* ''' */ + 87, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 92, /* '+' */ + 32, /* ',' */ + 132, /* '-' */ + 102, /* '.' */ + 138, /* '/' */ + 138, /* '0' */ + 132, /* '1' */ + 135, /* '2' */ + 132, /* '3' */ + 132, /* '4' */ + 138, /* '5' */ + 12, /* '6' */ + 138, /* '7' */ + 14, /* '8' */ + 138, /* '9' */ + 65, /* ':' */ + 135, /* ';' */ + 105, /* '<' */ + 138, /* '=' */ + 138, /* '>' */ + 135, /* '?' */ + 135, /* '@' */ + 140, /* 'A' */ + 105, /* 'B' */ + 138, /* 'C' */ + 105, /* 'D' */ + 102, /* 'E' */ + 135, /* 'F' */ + 170, /* 'G' */ + 138, /* 'H' */ + 171, /* 'I' */ + 138, /* 'J' */ + 165, /* 'K' */ + 132, /* 'L' */ + 170, /* 'M' */ + 138, /* 'N' */ + 172, /* 'O' */ + 138, /* 'P' */ + 167, /* 'Q' */ + 133, /* 'R' */ + 138, /* 'S' */ + 105, /* 'T' */ + 170, /* 'U' */ + 138, /* 'V' */ + 171, /* 'W' */ + 138, /* 'X' */ + 165, /* 'Y' */ + 132, /* 'Z' */ + 170, /* '[' */ + 138, /* '\' */ + 170, /* ']' */ + 138, /* '^' */ + 171, /* '_' */ + 138, /* '`' */ + 165, /* 'a' */ + 132, /* 'b' */ + 170, /* 'c' */ + 138, /* 'd' */ + 167, /* 'e' */ + 133, /* 'f' */ + 170, /* 'g' */ + 138, /* 'h' */ + 171, /* 'i' */ + 138, /* 'j' */ + 165, /* 'k' */ + 132, /* 'l' */ + 170, /* 'm' */ + 138, /* 'n' */ + 167, /* 'o' */ + 133, /* 'p' */ + 171, /* 'q' */ + 138, /* 'r' */ + 170, /* 's' */ + 138, /* 't' */ + 171, /* 'u' */ + 138, /* 'v' */ + 165, /* 'w' */ + 132, /* 'x' */ + 170, /* 'y' */ + 138, /* 'z' */ + 165, /* '{' */ + 132, /* '|' */ + 171, /* '}' */ + 138, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Helvetica", + 0, + NO + }, { + /* width table for font XHI */ + { + 55, /* ' ' */ + 93, /* '!' */ + 93, /* '"' */ + 93, /* '#' */ + 55, /* '$' */ + 93, /* '%' */ + 93, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 93, /* ')' */ + 93, /* '*' */ + 58, /* '+' */ + 55, /* ',' */ + 55, /* '-' */ + 102, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 167, /* ';' */ + 148, /* '<' */ + 62, /* '=' */ + 61, /* '>' */ + 93, /* '?' */ + 37, /* '@' */ + 130, /* 'A' */ + 102, /* 'B' */ + 167, /* 'C' */ + 157, /* 'D' */ + 46, /* 'E' */ + 102, /* 'F' */ + 111, /* 'G' */ + 93, /* 'H' */ + 111, /* 'I' */ + 93, /* 'J' */ + 111, /* 'K' */ + 93, /* 'L' */ + 111, /* 'M' */ + 93, /* 'N' */ + 111, /* 'O' */ + 93, /* 'P' */ + 111, /* 'Q' */ + 93, /* 'R' */ + 120, /* 'S' */ + 83, /* 'T' */ + 111, /* 'U' */ + 93, /* 'V' */ + 111, /* 'W' */ + 93, /* 'X' */ + 111, /* 'Y' */ + 93, /* 'Z' */ + 111, /* '[' */ + 93, /* '\' */ + 46, /* ']' */ + 46, /* '^' */ + 46, /* '_' */ + 46, /* '`' */ + 46, /* 'a' */ + 46, /* 'b' */ + 46, /* 'c' */ + 46, /* 'd' */ + 120, /* 'e' */ + 93, /* 'f' */ + 130, /* 'g' */ + 93, /* 'h' */ + 130, /* 'i' */ + 93, /* 'j' */ + 130, /* 'k' */ + 93, /* 'l' */ + 130, /* 'm' */ + 93, /* 'n' */ + 130, /* 'o' */ + 93, /* 'p' */ + 111, /* 'q' */ + 83, /* 'r' */ + 120, /* 's' */ + 93, /* 't' */ + 120, /* 'u' */ + 93, /* 'v' */ + 120, /* 'w' */ + 93, /* 'x' */ + 120, /* 'y' */ + 93, /* 'z' */ + 111, /* '{' */ + 83, /* '|' */ + 102, /* '}' */ + 83, /* '~' */ + 46, /* ' ' */ + }, + /* height table for font XHI */ + { + 275, /* ' ' */ + 152, /* '!' */ + 152, /* '"' */ + 146, /* '#' */ + 146, /* '$' */ + 101, /* '%' */ + 101, /* '&' */ + 101, /* ''' */ + 101, /* '(' */ + 175, /* ')' */ + 175, /* '*' */ + 106, /* '+' */ + 67, /* ',' */ + 146, /* '-' */ + 151, /* '.' */ + 152, /* '/' */ + 152, /* '0' */ + 146, /* '1' */ + 149, /* '2' */ + 146, /* '3' */ + 146, /* '4' */ + 152, /* '5' */ + 63, /* '6' */ + 152, /* '7' */ + 60, /* '8' */ + 152, /* '9' */ + 79, /* ':' */ + 149, /* ';' */ + 122, /* '<' */ + 152, /* '=' */ + 152, /* '>' */ + 149, /* '?' */ + 149, /* '@' */ + 156, /* 'A' */ + 124, /* 'B' */ + 155, /* 'C' */ + 122, /* 'D' */ + 116, /* 'E' */ + 152, /* 'F' */ + 184, /* 'G' */ + 155, /* 'H' */ + 184, /* 'I' */ + 155, /* 'J' */ + 179, /* 'K' */ + 149, /* 'L' */ + 184, /* 'M' */ + 155, /* 'N' */ + 186, /* 'O' */ + 155, /* 'P' */ + 182, /* 'Q' */ + 152, /* 'R' */ + 188, /* 'S' */ + 154, /* 'T' */ + 184, /* 'U' */ + 155, /* 'V' */ + 184, /* 'W' */ + 155, /* 'X' */ + 179, /* 'Y' */ + 148, /* 'Z' */ + 184, /* '[' */ + 155, /* '\' */ + 184, /* ']' */ + 152, /* '^' */ + 184, /* '_' */ + 152, /* '`' */ + 178, /* 'a' */ + 144, /* 'b' */ + 184, /* 'c' */ + 152, /* 'd' */ + 182, /* 'e' */ + 149, /* 'f' */ + 187, /* 'g' */ + 155, /* 'h' */ + 187, /* 'i' */ + 155, /* 'j' */ + 182, /* 'k' */ + 148, /* 'l' */ + 187, /* 'm' */ + 155, /* 'n' */ + 185, /* 'o' */ + 152, /* 'p' */ + 187, /* 'q' */ + 155, /* 'r' */ + 187, /* 's' */ + 155, /* 't' */ + 187, /* 'u' */ + 155, /* 'v' */ + 182, /* 'w' */ + 148, /* 'x' */ + 187, /* 'y' */ + 155, /* 'z' */ + 179, /* '{' */ + 181, /* '|' */ + 184, /* '}' */ + 152, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XHI */ + { + 196, /* ' ' */ + 119, /* '!' */ + 135, /* '"' */ + 132, /* '#' */ + 132, /* '$' */ + 87, /* '%' */ + 87, /* '&' */ + 87, /* ''' */ + 87, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 92, /* '+' */ + 32, /* ',' */ + 132, /* '-' */ + 102, /* '.' */ + 138, /* '/' */ + 138, /* '0' */ + 132, /* '1' */ + 135, /* '2' */ + 132, /* '3' */ + 132, /* '4' */ + 138, /* '5' */ + 14, /* '6' */ + 138, /* '7' */ + 14, /* '8' */ + 138, /* '9' */ + 65, /* ':' */ + 135, /* ';' */ + 105, /* '<' */ + 138, /* '=' */ + 138, /* '>' */ + 135, /* '?' */ + 135, /* '@' */ + 138, /* 'A' */ + 105, /* 'B' */ + 138, /* 'C' */ + 105, /* 'D' */ + 102, /* 'E' */ + 135, /* 'F' */ + 170, /* 'G' */ + 138, /* 'H' */ + 171, /* 'I' */ + 138, /* 'J' */ + 165, /* 'K' */ + 132, /* 'L' */ + 170, /* 'M' */ + 138, /* 'N' */ + 172, /* 'O' */ + 138, /* 'P' */ + 168, /* 'Q' */ + 135, /* 'R' */ + 138, /* 'S' */ + 105, /* 'T' */ + 170, /* 'U' */ + 138, /* 'V' */ + 171, /* 'W' */ + 138, /* 'X' */ + 165, /* 'Y' */ + 132, /* 'Z' */ + 170, /* '[' */ + 138, /* '\' */ + 170, /* ']' */ + 138, /* '^' */ + 171, /* '_' */ + 138, /* '`' */ + 164, /* 'a' */ + 131, /* 'b' */ + 170, /* 'c' */ + 138, /* 'd' */ + 168, /* 'e' */ + 135, /* 'f' */ + 170, /* 'g' */ + 138, /* 'h' */ + 171, /* 'i' */ + 138, /* 'j' */ + 165, /* 'k' */ + 132, /* 'l' */ + 170, /* 'm' */ + 138, /* 'n' */ + 168, /* 'o' */ + 135, /* 'p' */ + 170, /* 'q' */ + 138, /* 'r' */ + 170, /* 's' */ + 138, /* 't' */ + 171, /* 'u' */ + 138, /* 'v' */ + 165, /* 'w' */ + 132, /* 'x' */ + 170, /* 'y' */ + 138, /* 'z' */ + 165, /* '{' */ + 132, /* '|' */ + 170, /* '}' */ + 138, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Helvetica-Oblique", + 0, + YES + }, { + /* width table for font XHB */ + { + 55, /* ' ' */ + 93, /* '!' */ + 93, /* '"' */ + 93, /* '#' */ + 83, /* '$' */ + 93, /* '%' */ + 93, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 93, /* ')' */ + 93, /* '*' */ + 58, /* '+' */ + 83, /* ',' */ + 83, /* '-' */ + 102, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 167, /* ';' */ + 148, /* '<' */ + 62, /* '=' */ + 61, /* '>' */ + 102, /* '?' */ + 46, /* '@' */ + 130, /* 'A' */ + 102, /* 'B' */ + 167, /* 'C' */ + 157, /* 'D' */ + 46, /* 'E' */ + 102, /* 'F' */ + 120, /* 'G' */ + 93, /* 'H' */ + 120, /* 'I' */ + 93, /* 'J' */ + 120, /* 'K' */ + 93, /* 'L' */ + 120, /* 'M' */ + 93, /* 'N' */ + 120, /* 'O' */ + 93, /* 'P' */ + 120, /* 'Q' */ + 93, /* 'R' */ + 120, /* 'S' */ + 93, /* 'T' */ + 111, /* 'U' */ + 93, /* 'V' */ + 111, /* 'W' */ + 93, /* 'X' */ + 111, /* 'Y' */ + 93, /* 'Z' */ + 111, /* '[' */ + 93, /* '\' */ + 46, /* ']' */ + 46, /* '^' */ + 46, /* '_' */ + 46, /* '`' */ + 46, /* 'a' */ + 46, /* 'b' */ + 46, /* 'c' */ + 46, /* 'd' */ + 120, /* 'e' */ + 102, /* 'f' */ + 130, /* 'g' */ + 102, /* 'h' */ + 130, /* 'i' */ + 102, /* 'j' */ + 130, /* 'k' */ + 102, /* 'l' */ + 130, /* 'm' */ + 102, /* 'n' */ + 130, /* 'o' */ + 102, /* 'p' */ + 111, /* 'q' */ + 93, /* 'r' */ + 120, /* 's' */ + 102, /* 't' */ + 120, /* 'u' */ + 102, /* 'v' */ + 120, /* 'w' */ + 102, /* 'x' */ + 120, /* 'y' */ + 102, /* 'z' */ + 111, /* '{' */ + 93, /* '|' */ + 102, /* '}' */ + 83, /* '~' */ + 46, /* ' ' */ + }, + /* height table for font XHB */ + { + 275, /* ' ' */ + 154, /* '!' */ + 152, /* '"' */ + 145, /* '#' */ + 149, /* '$' */ + 108, /* '%' */ + 108, /* '&' */ + 108, /* ''' */ + 108, /* '(' */ + 178, /* ')' */ + 178, /* '*' */ + 99, /* '+' */ + 71, /* ',' */ + 149, /* '-' */ + 154, /* '.' */ + 154, /* '/' */ + 154, /* '0' */ + 149, /* '1' */ + 152, /* '2' */ + 152, /* '3' */ + 152, /* '4' */ + 156, /* '5' */ + 67, /* '6' */ + 154, /* '7' */ + 67, /* '8' */ + 154, /* '9' */ + 79, /* ':' */ + 149, /* ';' */ + 128, /* '<' */ + 149, /* '=' */ + 149, /* '>' */ + 149, /* '?' */ + 149, /* '@' */ + 159, /* 'A' */ + 129, /* 'B' */ + 155, /* 'C' */ + 125, /* 'D' */ + 119, /* 'E' */ + 151, /* 'F' */ + 184, /* 'G' */ + 157, /* 'H' */ + 184, /* 'I' */ + 157, /* 'J' */ + 182, /* 'K' */ + 155, /* 'L' */ + 184, /* 'M' */ + 157, /* 'N' */ + 186, /* 'O' */ + 158, /* 'P' */ + 182, /* 'Q' */ + 155, /* 'R' */ + 191, /* 'S' */ + 161, /* 'T' */ + 184, /* 'U' */ + 157, /* 'V' */ + 184, /* 'W' */ + 157, /* 'X' */ + 182, /* 'Y' */ + 155, /* 'Z' */ + 184, /* '[' */ + 157, /* '\' */ + 184, /* ']' */ + 154, /* '^' */ + 184, /* '_' */ + 154, /* '`' */ + 182, /* 'a' */ + 152, /* 'b' */ + 184, /* 'c' */ + 154, /* 'd' */ + 182, /* 'e' */ + 152, /* 'f' */ + 186, /* 'g' */ + 157, /* 'h' */ + 186, /* 'i' */ + 157, /* 'j' */ + 185, /* 'k' */ + 155, /* 'l' */ + 186, /* 'm' */ + 157, /* 'n' */ + 185, /* 'o' */ + 155, /* 'p' */ + 186, /* 'q' */ + 157, /* 'r' */ + 186, /* 's' */ + 157, /* 't' */ + 186, /* 'u' */ + 157, /* 'v' */ + 185, /* 'w' */ + 155, /* 'x' */ + 186, /* 'y' */ + 157, /* 'z' */ + 182, /* '{' */ + 188, /* '|' */ + 184, /* '}' */ + 154, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XHB */ + { + 199, /* ' ' */ + 120, /* '!' */ + 135, /* '"' */ + 131, /* '#' */ + 135, /* '$' */ + 94, /* '%' */ + 94, /* '&' */ + 94, /* ''' */ + 94, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 85, /* '+' */ + 35, /* ',' */ + 135, /* '-' */ + 105, /* '.' */ + 140, /* '/' */ + 140, /* '0' */ + 135, /* '1' */ + 138, /* '2' */ + 138, /* '3' */ + 138, /* '4' */ + 142, /* '5' */ + 14, /* '6' */ + 140, /* '7' */ + 14, /* '8' */ + 140, /* '9' */ + 65, /* ':' */ + 135, /* ';' */ + 108, /* '<' */ + 135, /* '=' */ + 135, /* '>' */ + 135, /* '?' */ + 135, /* '@' */ + 139, /* 'A' */ + 108, /* 'B' */ + 138, /* 'C' */ + 108, /* 'D' */ + 105, /* 'E' */ + 135, /* 'F' */ + 170, /* 'G' */ + 140, /* 'H' */ + 170, /* 'I' */ + 140, /* 'J' */ + 168, /* 'K' */ + 138, /* 'L' */ + 170, /* 'M' */ + 140, /* 'N' */ + 172, /* 'O' */ + 142, /* 'P' */ + 169, /* 'Q' */ + 138, /* 'R' */ + 138, /* 'S' */ + 108, /* 'T' */ + 170, /* 'U' */ + 140, /* 'V' */ + 170, /* 'W' */ + 140, /* 'X' */ + 168, /* 'Y' */ + 138, /* 'Z' */ + 170, /* '[' */ + 140, /* '\' */ + 170, /* ']' */ + 140, /* '^' */ + 170, /* '_' */ + 140, /* '`' */ + 168, /* 'a' */ + 138, /* 'b' */ + 170, /* 'c' */ + 140, /* 'd' */ + 169, /* 'e' */ + 138, /* 'f' */ + 170, /* 'g' */ + 140, /* 'h' */ + 170, /* 'i' */ + 140, /* 'j' */ + 168, /* 'k' */ + 138, /* 'l' */ + 170, /* 'm' */ + 140, /* 'n' */ + 169, /* 'o' */ + 138, /* 'p' */ + 170, /* 'q' */ + 140, /* 'r' */ + 170, /* 's' */ + 140, /* 't' */ + 170, /* 'u' */ + 140, /* 'v' */ + 168, /* 'w' */ + 138, /* 'x' */ + 170, /* 'y' */ + 140, /* 'z' */ + 168, /* '{' */ + 138, /* '|' */ + 170, /* '}' */ + 140, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Helvetica-Bold", + 0, + NO + }, { + /* width table for font XHX */ + { + 55, /* ' ' */ + 93, /* '!' */ + 93, /* '"' */ + 93, /* '#' */ + 83, /* '$' */ + 93, /* '%' */ + 93, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 93, /* ')' */ + 93, /* '*' */ + 58, /* '+' */ + 83, /* ',' */ + 83, /* '-' */ + 102, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 167, /* ';' */ + 148, /* '<' */ + 62, /* '=' */ + 61, /* '>' */ + 102, /* '?' */ + 46, /* '@' */ + 130, /* 'A' */ + 102, /* 'B' */ + 167, /* 'C' */ + 157, /* 'D' */ + 46, /* 'E' */ + 102, /* 'F' */ + 120, /* 'G' */ + 93, /* 'H' */ + 120, /* 'I' */ + 93, /* 'J' */ + 120, /* 'K' */ + 93, /* 'L' */ + 120, /* 'M' */ + 93, /* 'N' */ + 120, /* 'O' */ + 93, /* 'P' */ + 120, /* 'Q' */ + 93, /* 'R' */ + 120, /* 'S' */ + 93, /* 'T' */ + 111, /* 'U' */ + 93, /* 'V' */ + 111, /* 'W' */ + 93, /* 'X' */ + 111, /* 'Y' */ + 93, /* 'Z' */ + 111, /* '[' */ + 93, /* '\' */ + 46, /* ']' */ + 46, /* '^' */ + 46, /* '_' */ + 46, /* '`' */ + 46, /* 'a' */ + 46, /* 'b' */ + 46, /* 'c' */ + 46, /* 'd' */ + 120, /* 'e' */ + 102, /* 'f' */ + 130, /* 'g' */ + 102, /* 'h' */ + 130, /* 'i' */ + 102, /* 'j' */ + 130, /* 'k' */ + 102, /* 'l' */ + 130, /* 'm' */ + 102, /* 'n' */ + 130, /* 'o' */ + 102, /* 'p' */ + 111, /* 'q' */ + 93, /* 'r' */ + 120, /* 's' */ + 102, /* 't' */ + 120, /* 'u' */ + 102, /* 'v' */ + 120, /* 'w' */ + 102, /* 'x' */ + 120, /* 'y' */ + 102, /* 'z' */ + 111, /* '{' */ + 93, /* '|' */ + 102, /* '}' */ + 83, /* '~' */ + 46, /* ' ' */ + }, + /* height table for font XHX */ + { + 275, /* ' ' */ + 154, /* '!' */ + 152, /* '"' */ + 145, /* '#' */ + 149, /* '$' */ + 108, /* '%' */ + 108, /* '&' */ + 108, /* ''' */ + 108, /* '(' */ + 178, /* ')' */ + 178, /* '*' */ + 99, /* '+' */ + 71, /* ',' */ + 149, /* '-' */ + 151, /* '.' */ + 156, /* '/' */ + 154, /* '0' */ + 149, /* '1' */ + 153, /* '2' */ + 152, /* '3' */ + 152, /* '4' */ + 159, /* '5' */ + 67, /* '6' */ + 154, /* '7' */ + 67, /* '8' */ + 154, /* '9' */ + 82, /* ':' */ + 149, /* ';' */ + 125, /* '<' */ + 149, /* '=' */ + 149, /* '>' */ + 149, /* '?' */ + 149, /* '@' */ + 159, /* 'A' */ + 129, /* 'B' */ + 155, /* 'C' */ + 125, /* 'D' */ + 119, /* 'E' */ + 152, /* 'F' */ + 184, /* 'G' */ + 157, /* 'H' */ + 184, /* 'I' */ + 157, /* 'J' */ + 182, /* 'K' */ + 155, /* 'L' */ + 186, /* 'M' */ + 158, /* 'N' */ + 189, /* 'O' */ + 162, /* 'P' */ + 182, /* 'Q' */ + 155, /* 'R' */ + 191, /* 'S' */ + 161, /* 'T' */ + 184, /* 'U' */ + 157, /* 'V' */ + 184, /* 'W' */ + 157, /* 'X' */ + 182, /* 'Y' */ + 155, /* 'Z' */ + 186, /* '[' */ + 158, /* '\' */ + 184, /* ']' */ + 154, /* '^' */ + 184, /* '_' */ + 154, /* '`' */ + 182, /* 'a' */ + 152, /* 'b' */ + 186, /* 'c' */ + 156, /* 'd' */ + 182, /* 'e' */ + 152, /* 'f' */ + 186, /* 'g' */ + 157, /* 'h' */ + 186, /* 'i' */ + 157, /* 'j' */ + 185, /* 'k' */ + 155, /* 'l' */ + 188, /* 'm' */ + 158, /* 'n' */ + 184, /* 'o' */ + 155, /* 'p' */ + 187, /* 'q' */ + 157, /* 'r' */ + 186, /* 's' */ + 157, /* 't' */ + 186, /* 'u' */ + 157, /* 'v' */ + 185, /* 'w' */ + 155, /* 'x' */ + 188, /* 'y' */ + 158, /* 'z' */ + 182, /* '{' */ + 191, /* '|' */ + 184, /* '}' */ + 154, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XHX */ + { + 199, /* ' ' */ + 120, /* '!' */ + 135, /* '"' */ + 131, /* '#' */ + 135, /* '$' */ + 94, /* '%' */ + 94, /* '&' */ + 94, /* ''' */ + 94, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 85, /* '+' */ + 35, /* ',' */ + 135, /* '-' */ + 105, /* '.' */ + 142, /* '/' */ + 140, /* '0' */ + 135, /* '1' */ + 140, /* '2' */ + 138, /* '3' */ + 138, /* '4' */ + 145, /* '5' */ + 14, /* '6' */ + 140, /* '7' */ + 14, /* '8' */ + 140, /* '9' */ + 68, /* ':' */ + 135, /* ';' */ + 108, /* '<' */ + 135, /* '=' */ + 135, /* '>' */ + 135, /* '?' */ + 135, /* '@' */ + 139, /* 'A' */ + 108, /* 'B' */ + 138, /* 'C' */ + 108, /* 'D' */ + 105, /* 'E' */ + 135, /* 'F' */ + 170, /* 'G' */ + 140, /* 'H' */ + 170, /* 'I' */ + 140, /* 'J' */ + 168, /* 'K' */ + 138, /* 'L' */ + 172, /* 'M' */ + 142, /* 'N' */ + 175, /* 'O' */ + 145, /* 'P' */ + 168, /* 'Q' */ + 138, /* 'R' */ + 138, /* 'S' */ + 108, /* 'T' */ + 170, /* 'U' */ + 140, /* 'V' */ + 170, /* 'W' */ + 140, /* 'X' */ + 168, /* 'Y' */ + 138, /* 'Z' */ + 172, /* '[' */ + 142, /* '\' */ + 170, /* ']' */ + 140, /* '^' */ + 170, /* '_' */ + 140, /* '`' */ + 168, /* 'a' */ + 138, /* 'b' */ + 172, /* 'c' */ + 142, /* 'd' */ + 168, /* 'e' */ + 138, /* 'f' */ + 170, /* 'g' */ + 140, /* 'h' */ + 170, /* 'i' */ + 140, /* 'j' */ + 168, /* 'k' */ + 138, /* 'l' */ + 172, /* 'm' */ + 142, /* 'n' */ + 168, /* 'o' */ + 138, /* 'p' */ + 170, /* 'q' */ + 140, /* 'r' */ + 170, /* 's' */ + 140, /* 't' */ + 170, /* 'u' */ + 140, /* 'v' */ + 168, /* 'w' */ + 138, /* 'x' */ + 172, /* 'y' */ + 142, /* 'z' */ + 168, /* '{' */ + 138, /* '|' */ + 170, /* '}' */ + 140, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Helvetica-BoldOblique", + 0, + YES + }, { + /* width table for font XBR */ + { + 50, /* ' ' */ + 103, /* '!' */ + 103, /* '"' */ + 103, /* '#' */ + 67, /* '$' */ + 60, /* '%' */ + 60, /* '&' */ + 40, /* ''' */ + 40, /* '(' */ + 90, /* ')' */ + 90, /* '*' */ + 77, /* '+' */ + 67, /* ',' */ + 67, /* '-' */ + 90, /* '.' */ + 57, /* '/' */ + 57, /* '0' */ + 73, /* '1' */ + 77, /* '2' */ + 43, /* '3' */ + 70, /* '4' */ + 53, /* '5' */ + 53, /* '6' */ + 63, /* '7' */ + 53, /* '8' */ + 70, /* '9' */ + 167, /* ':' */ + 210, /* ';' */ + 143, /* '<' */ + 70, /* '=' */ + 70, /* '>' */ + 100, /* '?' */ + 53, /* '@' */ + 133, /* 'A' */ + 93, /* 'B' */ + 207, /* 'C' */ + 150, /* 'D' */ + 50, /* 'E' */ + 110, /* 'F' */ + 113, /* 'G' */ + 97, /* 'H' */ + 113, /* 'I' */ + 97, /* 'J' */ + 113, /* 'K' */ + 97, /* 'L' */ + 113, /* 'M' */ + 97, /* 'N' */ + 113, /* 'O' */ + 97, /* 'P' */ + 113, /* 'Q' */ + 97, /* 'R' */ + 123, /* 'S' */ + 87, /* 'T' */ + 120, /* 'U' */ + 87, /* 'V' */ + 120, /* 'W' */ + 87, /* 'X' */ + 120, /* 'Y' */ + 87, /* 'Z' */ + 120, /* '[' */ + 87, /* '\' */ + 57, /* ']' */ + 50, /* '^' */ + 57, /* '_' */ + 50, /* '`' */ + 57, /* 'a' */ + 50, /* 'b' */ + 57, /* 'c' */ + 50, /* 'd' */ + 123, /* 'e' */ + 110, /* 'f' */ + 133, /* 'g' */ + 93, /* 'h' */ + 133, /* 'i' */ + 93, /* 'j' */ + 133, /* 'k' */ + 93, /* 'l' */ + 133, /* 'm' */ + 93, /* 'n' */ + 133, /* 'o' */ + 93, /* 'p' */ + 110, /* 'q' */ + 87, /* 'r' */ + 130, /* 's' */ + 113, /* 't' */ + 130, /* 'u' */ + 113, /* 'v' */ + 130, /* 'w' */ + 113, /* 'x' */ + 130, /* 'y' */ + 113, /* 'z' */ + 107, /* '{' */ + 90, /* '|' */ + 107, /* '}' */ + 80, /* '~' */ + 53, /* ' ' */ + }, + /* height table for font XBR */ + { + 273, /* ' ' */ + 136, /* '!' */ + 148, /* '"' */ + 142, /* '#' */ + 143, /* '$' */ + 101, /* '%' */ + 101, /* '&' */ + 101, /* ''' */ + 101, /* '(' */ + 172, /* ')' */ + 172, /* '*' */ + 121, /* '+' */ + 64, /* ',' */ + 146, /* '-' */ + 148, /* '.' */ + 141, /* '/' */ + 141, /* '0' */ + 132, /* '1' */ + 141, /* '2' */ + 142, /* '3' */ + 142, /* '4' */ + 149, /* '5' */ + 60, /* '6' */ + 146, /* '7' */ + 53, /* '8' */ + 141, /* '9' */ + 76, /* ':' */ + 142, /* ';' */ + 114, /* '<' */ + 142, /* '=' */ + 142, /* '>' */ + 142, /* '?' */ + 147, /* '@' */ + 159, /* 'A' */ + 125, /* 'B' */ + 148, /* 'C' */ + 114, /* 'D' */ + 109, /* 'E' */ + 164, /* 'F' */ + 173, /* 'G' */ + 143, /* 'H' */ + 173, /* 'I' */ + 143, /* 'J' */ + 173, /* 'K' */ + 144, /* 'L' */ + 173, /* 'M' */ + 143, /* 'N' */ + 181, /* 'O' */ + 151, /* 'P' */ + 170, /* 'Q' */ + 141, /* 'R' */ + 178, /* 'S' */ + 144, /* 'T' */ + 173, /* 'U' */ + 143, /* 'V' */ + 173, /* 'W' */ + 143, /* 'X' */ + 173, /* 'Y' */ + 144, /* 'Z' */ + 173, /* '[' */ + 143, /* '\' */ + 173, /* ']' */ + 141, /* '^' */ + 173, /* '_' */ + 141, /* '`' */ + 172, /* 'a' */ + 142, /* 'b' */ + 173, /* 'c' */ + 141, /* 'd' */ + 170, /* 'e' */ + 139, /* 'f' */ + 175, /* 'g' */ + 143, /* 'h' */ + 175, /* 'i' */ + 143, /* 'j' */ + 175, /* 'k' */ + 144, /* 'l' */ + 175, /* 'm' */ + 143, /* 'n' */ + 172, /* 'o' */ + 141, /* 'p' */ + 175, /* 'q' */ + 143, /* 'r' */ + 175, /* 's' */ + 143, /* 't' */ + 175, /* 'u' */ + 143, /* 'v' */ + 175, /* 'w' */ + 144, /* 'x' */ + 175, /* 'y' */ + 143, /* 'z' */ + 173, /* '{' */ + 181, /* '|' */ + 173, /* '}' */ + 141, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XBR */ + { + 193, /* ' ' */ + 123, /* '!' */ + 132, /* '"' */ + 128, /* '#' */ + 130, /* '$' */ + 87, /* '%' */ + 87, /* '&' */ + 87, /* ''' */ + 87, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 107, /* '+' */ + 33, /* ',' */ + 132, /* '-' */ + 98, /* '.' */ + 127, /* '/' */ + 127, /* '0' */ + 118, /* '1' */ + 128, /* '2' */ + 128, /* '3' */ + 128, /* '4' */ + 135, /* '5' */ + 14, /* '6' */ + 132, /* '7' */ + 14, /* '8' */ + 127, /* '9' */ + 62, /* ':' */ + 128, /* ';' */ + 98, /* '<' */ + 128, /* '=' */ + 128, /* '>' */ + 128, /* '?' */ + 133, /* '@' */ + 136, /* 'A' */ + 104, /* 'B' */ + 132, /* 'C' */ + 98, /* 'D' */ + 95, /* 'E' */ + 132, /* 'F' */ + 159, /* 'G' */ + 127, /* 'H' */ + 159, /* 'I' */ + 127, /* 'J' */ + 159, /* 'K' */ + 128, /* 'L' */ + 159, /* 'M' */ + 127, /* 'N' */ + 168, /* 'O' */ + 135, /* 'P' */ + 156, /* 'Q' */ + 125, /* 'R' */ + 132, /* 'S' */ + 98, /* 'T' */ + 159, /* 'U' */ + 127, /* 'V' */ + 159, /* 'W' */ + 127, /* 'X' */ + 159, /* 'Y' */ + 128, /* 'Z' */ + 159, /* '[' */ + 127, /* '\' */ + 159, /* ']' */ + 127, /* '^' */ + 159, /* '_' */ + 127, /* '`' */ + 158, /* 'a' */ + 128, /* 'b' */ + 159, /* 'c' */ + 127, /* 'd' */ + 156, /* 'e' */ + 125, /* 'f' */ + 159, /* 'g' */ + 127, /* 'h' */ + 159, /* 'i' */ + 127, /* 'j' */ + 159, /* 'k' */ + 128, /* 'l' */ + 159, /* 'm' */ + 127, /* 'n' */ + 156, /* 'o' */ + 125, /* 'p' */ + 159, /* 'q' */ + 127, /* 'r' */ + 159, /* 's' */ + 127, /* 't' */ + 159, /* 'u' */ + 127, /* 'v' */ + 159, /* 'w' */ + 128, /* 'x' */ + 159, /* 'y' */ + 127, /* 'z' */ + 159, /* '{' */ + 128, /* '|' */ + 159, /* '}' */ + 127, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Bookman-Light", + 0, + NO + }, { + /* width table for font XBI */ + { + 53, /* ' ' */ + 103, /* '!' */ + 103, /* '"' */ + 103, /* '#' */ + 73, /* '$' */ + 50, /* '%' */ + 50, /* '&' */ + 30, /* ''' */ + 30, /* '(' */ + 103, /* ')' */ + 103, /* '*' */ + 77, /* '+' */ + 80, /* ',' */ + 73, /* '-' */ + 90, /* '.' */ + 57, /* '/' */ + 53, /* '0' */ + 73, /* '1' */ + 73, /* '2' */ + 43, /* '3' */ + 70, /* '4' */ + 50, /* '5' */ + 53, /* '6' */ + 57, /* '7' */ + 43, /* '8' */ + 73, /* '9' */ + 167, /* ':' */ + 203, /* ';' */ + 147, /* '<' */ + 73, /* '=' */ + 67, /* '>' */ + 97, /* '?' */ + 57, /* '@' */ + 127, /* 'A' */ + 90, /* 'B' */ + 197, /* 'C' */ + 150, /* 'D' */ + 47, /* 'E' */ + 103, /* 'F' */ + 117, /* 'G' */ + 103, /* 'H' */ + 117, /* 'I' */ + 103, /* 'J' */ + 117, /* 'K' */ + 103, /* 'L' */ + 117, /* 'M' */ + 103, /* 'N' */ + 117, /* 'O' */ + 103, /* 'P' */ + 117, /* 'Q' */ + 103, /* 'R' */ + 120, /* 'S' */ + 80, /* 'T' */ + 113, /* 'U' */ + 90, /* 'V' */ + 113, /* 'W' */ + 90, /* 'X' */ + 113, /* 'Y' */ + 90, /* 'Z' */ + 113, /* '[' */ + 90, /* '\' */ + 53, /* ']' */ + 47, /* '^' */ + 53, /* '_' */ + 47, /* '`' */ + 53, /* 'a' */ + 47, /* 'b' */ + 53, /* 'c' */ + 47, /* 'd' */ + 120, /* 'e' */ + 103, /* 'f' */ + 127, /* 'g' */ + 90, /* 'h' */ + 127, /* 'i' */ + 90, /* 'j' */ + 127, /* 'k' */ + 90, /* 'l' */ + 127, /* 'm' */ + 90, /* 'n' */ + 127, /* 'o' */ + 90, /* 'p' */ + 107, /* 'q' */ + 90, /* 'r' */ + 120, /* 's' */ + 103, /* 't' */ + 120, /* 'u' */ + 103, /* 'v' */ + 120, /* 'w' */ + 103, /* 'x' */ + 120, /* 'y' */ + 103, /* 'z' */ + 110, /* '{' */ + 100, /* '|' */ + 97, /* '}' */ + 87, /* '~' */ + 50, /* ' ' */ + }, + /* height table for font XBI */ + { + 273, /* ' ' */ + 152, /* '!' */ + 148, /* '"' */ + 142, /* '#' */ + 143, /* '$' */ + 95, /* '%' */ + 95, /* '&' */ + 94, /* ''' */ + 95, /* '(' */ + 173, /* ')' */ + 168, /* '*' */ + 121, /* '+' */ + 66, /* ',' */ + 146, /* '-' */ + 148, /* '.' */ + 146, /* '/' */ + 146, /* '0' */ + 132, /* '1' */ + 138, /* '2' */ + 140, /* '3' */ + 140, /* '4' */ + 146, /* '5' */ + 57, /* '6' */ + 147, /* '7' */ + 57, /* '8' */ + 139, /* '9' */ + 76, /* ':' */ + 142, /* ';' */ + 114, /* '<' */ + 146, /* '=' */ + 146, /* '>' */ + 142, /* '?' */ + 149, /* '@' */ + 173, /* 'A' */ + 125, /* 'B' */ + 148, /* 'C' */ + 114, /* 'D' */ + 111, /* 'E' */ + 164, /* 'F' */ + 174, /* 'G' */ + 148, /* 'H' */ + 170, /* 'I' */ + 141, /* 'J' */ + 171, /* 'K' */ + 142, /* 'L' */ + 174, /* 'M' */ + 148, /* 'N' */ + 176, /* 'O' */ + 148, /* 'P' */ + 169, /* 'Q' */ + 139, /* 'R' */ + 174, /* 'S' */ + 141, /* 'T' */ + 174, /* 'U' */ + 148, /* 'V' */ + 170, /* 'W' */ + 141, /* 'X' */ + 171, /* 'Y' */ + 142, /* 'Z' */ + 174, /* '[' */ + 148, /* '\' */ + 174, /* ']' */ + 148, /* '^' */ + 170, /* '_' */ + 141, /* '`' */ + 171, /* 'a' */ + 142, /* 'b' */ + 174, /* 'c' */ + 148, /* 'd' */ + 169, /* 'e' */ + 139, /* 'f' */ + 176, /* 'g' */ + 148, /* 'h' */ + 172, /* 'i' */ + 141, /* 'j' */ + 173, /* 'k' */ + 142, /* 'l' */ + 176, /* 'm' */ + 148, /* 'n' */ + 171, /* 'o' */ + 139, /* 'p' */ + 172, /* 'q' */ + 141, /* 'r' */ + 176, /* 's' */ + 148, /* 't' */ + 172, /* 'u' */ + 141, /* 'v' */ + 173, /* 'w' */ + 142, /* 'x' */ + 176, /* 'y' */ + 148, /* 'z' */ + 171, /* '{' */ + 175, /* '|' */ + 170, /* '}' */ + 141, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XBI */ + { + 193, /* ' ' */ + 133, /* '!' */ + 132, /* '"' */ + 128, /* '#' */ + 130, /* '$' */ + 82, /* '%' */ + 81, /* '&' */ + 81, /* ''' */ + 81, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 107, /* '+' */ + 33, /* ',' */ + 132, /* '-' */ + 98, /* '.' */ + 132, /* '/' */ + 132, /* '0' */ + 118, /* '1' */ + 124, /* '2' */ + 126, /* '3' */ + 126, /* '4' */ + 132, /* '5' */ + 14, /* '6' */ + 134, /* '7' */ + 14, /* '8' */ + 125, /* '9' */ + 62, /* ':' */ + 128, /* ';' */ + 98, /* '<' */ + 132, /* '=' */ + 132, /* '>' */ + 128, /* '?' */ + 133, /* '@' */ + 144, /* 'A' */ + 103, /* 'B' */ + 132, /* 'C' */ + 98, /* 'D' */ + 95, /* 'E' */ + 132, /* 'F' */ + 160, /* 'G' */ + 132, /* 'H' */ + 156, /* 'I' */ + 125, /* 'J' */ + 157, /* 'K' */ + 126, /* 'L' */ + 160, /* 'M' */ + 132, /* 'N' */ + 162, /* 'O' */ + 132, /* 'P' */ + 155, /* 'Q' */ + 123, /* 'R' */ + 132, /* 'S' */ + 98, /* 'T' */ + 160, /* 'U' */ + 132, /* 'V' */ + 156, /* 'W' */ + 125, /* 'X' */ + 157, /* 'Y' */ + 126, /* 'Z' */ + 160, /* '[' */ + 132, /* '\' */ + 160, /* ']' */ + 132, /* '^' */ + 156, /* '_' */ + 125, /* '`' */ + 157, /* 'a' */ + 126, /* 'b' */ + 160, /* 'c' */ + 132, /* 'd' */ + 155, /* 'e' */ + 123, /* 'f' */ + 160, /* 'g' */ + 132, /* 'h' */ + 156, /* 'i' */ + 125, /* 'j' */ + 157, /* 'k' */ + 126, /* 'l' */ + 160, /* 'm' */ + 132, /* 'n' */ + 155, /* 'o' */ + 123, /* 'p' */ + 156, /* 'q' */ + 125, /* 'r' */ + 160, /* 's' */ + 132, /* 't' */ + 156, /* 'u' */ + 125, /* 'v' */ + 157, /* 'w' */ + 126, /* 'x' */ + 160, /* 'y' */ + 132, /* 'z' */ + 157, /* '{' */ + 126, /* '|' */ + 156, /* '}' */ + 125, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Bookman-LightItalic", + 0, + YES + }, { + /* width table for font XBB */ + { + 60, /* ' ' */ + 110, /* '!' */ + 110, /* '"' */ + 110, /* '#' */ + 90, /* '$' */ + 67, /* '%' */ + 67, /* '&' */ + 37, /* ''' */ + 37, /* '(' */ + 73, /* ')' */ + 63, /* '*' */ + 77, /* '+' */ + 90, /* ',' */ + 90, /* '-' */ + 110, /* '.' */ + 67, /* '/' */ + 67, /* '0' */ + 77, /* '1' */ + 83, /* '2' */ + 53, /* '3' */ + 83, /* '4' */ + 57, /* '5' */ + 60, /* '6' */ + 73, /* '7' */ + 53, /* '8' */ + 83, /* '9' */ + 167, /* ':' */ + 190, /* ';' */ + 147, /* '<' */ + 67, /* '=' */ + 67, /* '>' */ + 107, /* '?' */ + 57, /* '@' */ + 133, /* 'A' */ + 103, /* 'B' */ + 203, /* 'C' */ + 157, /* 'D' */ + 60, /* 'E' */ + 110, /* 'F' */ + 120, /* 'G' */ + 97, /* 'H' */ + 120, /* 'I' */ + 97, /* 'J' */ + 120, /* 'K' */ + 97, /* 'L' */ + 120, /* 'M' */ + 97, /* 'N' */ + 120, /* 'O' */ + 97, /* 'P' */ + 120, /* 'Q' */ + 97, /* 'R' */ + 123, /* 'S' */ + 97, /* 'T' */ + 120, /* 'U' */ + 97, /* 'V' */ + 120, /* 'W' */ + 97, /* 'X' */ + 120, /* 'Y' */ + 97, /* 'Z' */ + 120, /* '[' */ + 97, /* '\' */ + 67, /* ']' */ + 60, /* '^' */ + 67, /* '_' */ + 60, /* '`' */ + 67, /* 'a' */ + 60, /* 'b' */ + 67, /* 'c' */ + 60, /* 'd' */ + 123, /* 'e' */ + 113, /* 'f' */ + 133, /* 'g' */ + 103, /* 'h' */ + 133, /* 'i' */ + 103, /* 'j' */ + 133, /* 'k' */ + 103, /* 'l' */ + 133, /* 'm' */ + 103, /* 'n' */ + 133, /* 'o' */ + 103, /* 'p' */ + 110, /* 'q' */ + 87, /* 'r' */ + 123, /* 's' */ + 110, /* 't' */ + 123, /* 'u' */ + 110, /* 'v' */ + 123, /* 'w' */ + 110, /* 'x' */ + 123, /* 'y' */ + 110, /* 'z' */ + 117, /* '{' */ + 103, /* '|' */ + 107, /* '}' */ + 93, /* '~' */ + 57, /* ' ' */ + }, + /* height table for font XBB */ + { + 273, /* ' ' */ + 139, /* '!' */ + 148, /* '"' */ + 142, /* '#' */ + 143, /* '$' */ + 99, /* '%' */ + 99, /* '&' */ + 99, /* ''' */ + 99, /* '(' */ + 172, /* ')' */ + 172, /* '*' */ + 121, /* '+' */ + 70, /* ',' */ + 146, /* '-' */ + 148, /* '.' */ + 151, /* '/' */ + 151, /* '0' */ + 139, /* '1' */ + 149, /* '2' */ + 151, /* '3' */ + 146, /* '4' */ + 152, /* '5' */ + 64, /* '6' */ + 151, /* '7' */ + 57, /* '8' */ + 150, /* '9' */ + 79, /* ':' */ + 142, /* ';' */ + 118, /* '<' */ + 146, /* '=' */ + 146, /* '>' */ + 142, /* '?' */ + 148, /* '@' */ + 176, /* 'A' */ + 125, /* 'B' */ + 148, /* 'C' */ + 118, /* 'D' */ + 112, /* 'E' */ + 161, /* 'F' */ + 179, /* 'G' */ + 153, /* 'H' */ + 178, /* 'I' */ + 152, /* 'J' */ + 174, /* 'K' */ + 148, /* 'L' */ + 179, /* 'M' */ + 153, /* 'N' */ + 182, /* 'O' */ + 154, /* 'P' */ + 175, /* 'Q' */ + 148, /* 'R' */ + 181, /* 'S' */ + 151, /* 'T' */ + 179, /* 'U' */ + 153, /* 'V' */ + 178, /* 'W' */ + 152, /* 'X' */ + 174, /* 'Y' */ + 148, /* 'Z' */ + 179, /* '[' */ + 153, /* '\' */ + 179, /* ']' */ + 151, /* '^' */ + 178, /* '_' */ + 150, /* '`' */ + 176, /* 'a' */ + 146, /* 'b' */ + 179, /* 'c' */ + 151, /* 'd' */ + 175, /* 'e' */ + 146, /* 'f' */ + 182, /* 'g' */ + 153, /* 'h' */ + 181, /* 'i' */ + 152, /* 'j' */ + 176, /* 'k' */ + 148, /* 'l' */ + 182, /* 'm' */ + 153, /* 'n' */ + 177, /* 'o' */ + 148, /* 'p' */ + 181, /* 'q' */ + 152, /* 'r' */ + 182, /* 's' */ + 153, /* 't' */ + 181, /* 'u' */ + 152, /* 'v' */ + 176, /* 'w' */ + 148, /* 'x' */ + 182, /* 'y' */ + 153, /* 'z' */ + 174, /* '{' */ + 184, /* '|' */ + 178, /* '}' */ + 150, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XBB */ + { + 196, /* ' ' */ + 125, /* '!' */ + 132, /* '"' */ + 128, /* '#' */ + 130, /* '$' */ + 86, /* '%' */ + 86, /* '&' */ + 86, /* ''' */ + 86, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 107, /* '+' */ + 39, /* ',' */ + 132, /* '-' */ + 102, /* '.' */ + 137, /* '/' */ + 137, /* '0' */ + 125, /* '1' */ + 135, /* '2' */ + 138, /* '3' */ + 132, /* '4' */ + 138, /* '5' */ + 15, /* '6' */ + 137, /* '7' */ + 14, /* '8' */ + 136, /* '9' */ + 65, /* ':' */ + 128, /* ';' */ + 102, /* '<' */ + 132, /* '=' */ + 132, /* '>' */ + 128, /* '?' */ + 135, /* '@' */ + 144, /* 'A' */ + 105, /* 'B' */ + 132, /* 'C' */ + 102, /* 'D' */ + 98, /* 'E' */ + 132, /* 'F' */ + 166, /* 'G' */ + 137, /* 'H' */ + 165, /* 'I' */ + 136, /* 'J' */ + 160, /* 'K' */ + 132, /* 'L' */ + 166, /* 'M' */ + 137, /* 'N' */ + 168, /* 'O' */ + 138, /* 'P' */ + 161, /* 'Q' */ + 132, /* 'R' */ + 132, /* 'S' */ + 102, /* 'T' */ + 166, /* 'U' */ + 137, /* 'V' */ + 165, /* 'W' */ + 136, /* 'X' */ + 160, /* 'Y' */ + 132, /* 'Z' */ + 166, /* '[' */ + 137, /* '\' */ + 166, /* ']' */ + 137, /* '^' */ + 165, /* '_' */ + 136, /* '`' */ + 162, /* 'a' */ + 132, /* 'b' */ + 166, /* 'c' */ + 137, /* 'd' */ + 161, /* 'e' */ + 132, /* 'f' */ + 166, /* 'g' */ + 137, /* 'h' */ + 165, /* 'i' */ + 136, /* 'j' */ + 160, /* 'k' */ + 132, /* 'l' */ + 166, /* 'm' */ + 137, /* 'n' */ + 161, /* 'o' */ + 132, /* 'p' */ + 165, /* 'q' */ + 136, /* 'r' */ + 166, /* 's' */ + 137, /* 't' */ + 165, /* 'u' */ + 136, /* 'v' */ + 160, /* 'w' */ + 132, /* 'x' */ + 166, /* 'y' */ + 137, /* 'z' */ + 160, /* '{' */ + 132, /* '|' */ + 165, /* '}' */ + 136, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Bookman-Demi", + 0, + NO + }, { + /* width table for font XBX */ + { + 53, /* ' ' */ + 113, /* '!' */ + 113, /* '"' */ + 113, /* '#' */ + 87, /* '$' */ + 63, /* '%' */ + 63, /* '&' */ + 37, /* ''' */ + 37, /* '(' */ + 70, /* ')' */ + 70, /* '*' */ + 60, /* '+' */ + 87, /* ',' */ + 87, /* '-' */ + 103, /* '.' */ + 63, /* '/' */ + 57, /* '0' */ + 80, /* '1' */ + 77, /* '2' */ + 63, /* '3' */ + 87, /* '4' */ + 60, /* '5' */ + 60, /* '6' */ + 93, /* '7' */ + 53, /* '8' */ + 80, /* '9' */ + 167, /* ':' */ + 190, /* ';' */ + 147, /* '<' */ + 73, /* '=' */ + 73, /* '>' */ + 107, /* '?' */ + 63, /* '@' */ + 127, /* 'A' */ + 100, /* 'B' */ + 197, /* 'C' */ + 153, /* 'D' */ + 63, /* 'E' */ + 110, /* 'F' */ + 120, /* 'G' */ + 113, /* 'H' */ + 120, /* 'I' */ + 113, /* 'J' */ + 120, /* 'K' */ + 113, /* 'L' */ + 120, /* 'M' */ + 113, /* 'N' */ + 120, /* 'O' */ + 113, /* 'P' */ + 120, /* 'Q' */ + 113, /* 'R' */ + 117, /* 'S' */ + 93, /* 'T' */ + 120, /* 'U' */ + 93, /* 'V' */ + 120, /* 'W' */ + 93, /* 'X' */ + 120, /* 'Y' */ + 93, /* 'Z' */ + 120, /* '[' */ + 93, /* '\' */ + 63, /* ']' */ + 63, /* '^' */ + 63, /* '_' */ + 63, /* '`' */ + 63, /* 'a' */ + 63, /* 'b' */ + 63, /* 'c' */ + 63, /* 'd' */ + 123, /* 'e' */ + 113, /* 'f' */ + 127, /* 'g' */ + 100, /* 'h' */ + 127, /* 'i' */ + 100, /* 'j' */ + 127, /* 'k' */ + 100, /* 'l' */ + 127, /* 'm' */ + 100, /* 'n' */ + 127, /* 'o' */ + 100, /* 'p' */ + 117, /* 'q' */ + 90, /* 'r' */ + 123, /* 's' */ + 113, /* 't' */ + 123, /* 'u' */ + 113, /* 'v' */ + 123, /* 'w' */ + 113, /* 'x' */ + 123, /* 'y' */ + 113, /* 'z' */ + 110, /* '{' */ + 100, /* '|' */ + 113, /* '}' */ + 93, /* '~' */ + 57, /* ' ' */ + }, + /* height table for font XBX */ + { + 272, /* ' ' */ + 146, /* '!' */ + 148, /* '"' */ + 142, /* '#' */ + 143, /* '$' */ + 107, /* '%' */ + 107, /* '&' */ + 107, /* ''' */ + 107, /* '(' */ + 168, /* ')' */ + 170, /* '*' */ + 121, /* '+' */ + 74, /* ',' */ + 146, /* '-' */ + 148, /* '.' */ + 152, /* '/' */ + 152, /* '0' */ + 146, /* '1' */ + 146, /* '2' */ + 150, /* '3' */ + 149, /* '4' */ + 156, /* '5' */ + 64, /* '6' */ + 153, /* '7' */ + 58, /* '8' */ + 150, /* '9' */ + 79, /* ':' */ + 142, /* ';' */ + 118, /* '<' */ + 146, /* '=' */ + 146, /* '>' */ + 142, /* '?' */ + 152, /* '@' */ + 153, /* 'A' */ + 133, /* 'B' */ + 148, /* 'C' */ + 118, /* 'D' */ + 114, /* 'E' */ + 188, /* 'F' */ + 180, /* 'G' */ + 155, /* 'H' */ + 178, /* 'I' */ + 152, /* 'J' */ + 177, /* 'K' */ + 151, /* 'L' */ + 180, /* 'M' */ + 155, /* 'N' */ + 182, /* 'O' */ + 158, /* 'P' */ + 172, /* 'Q' */ + 148, /* 'R' */ + 181, /* 'S' */ + 151, /* 'T' */ + 180, /* 'U' */ + 155, /* 'V' */ + 178, /* 'W' */ + 152, /* 'X' */ + 177, /* 'Y' */ + 152, /* 'Z' */ + 180, /* '[' */ + 155, /* '\' */ + 180, /* ']' */ + 155, /* '^' */ + 178, /* '_' */ + 152, /* '`' */ + 177, /* 'a' */ + 152, /* 'b' */ + 180, /* 'c' */ + 155, /* 'd' */ + 172, /* 'e' */ + 148, /* 'f' */ + 182, /* 'g' */ + 155, /* 'h' */ + 180, /* 'i' */ + 152, /* 'j' */ + 179, /* 'k' */ + 152, /* 'l' */ + 182, /* 'm' */ + 155, /* 'n' */ + 174, /* 'o' */ + 148, /* 'p' */ + 180, /* 'q' */ + 152, /* 'r' */ + 182, /* 's' */ + 155, /* 't' */ + 180, /* 'u' */ + 152, /* 'v' */ + 179, /* 'w' */ + 151, /* 'x' */ + 182, /* 'y' */ + 155, /* 'z' */ + 177, /* '{' */ + 181, /* '|' */ + 178, /* '}' */ + 152, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XBX */ + { + 196, /* ' ' */ + 132, /* '!' */ + 132, /* '"' */ + 128, /* '#' */ + 130, /* '$' */ + 93, /* '%' */ + 93, /* '&' */ + 93, /* ''' */ + 93, /* '(' */ + 132, /* ')' */ + 132, /* '*' */ + 107, /* '+' */ + 41, /* ',' */ + 132, /* '-' */ + 102, /* '.' */ + 139, /* '/' */ + 139, /* '0' */ + 132, /* '1' */ + 132, /* '2' */ + 136, /* '3' */ + 135, /* '4' */ + 142, /* '5' */ + 15, /* '6' */ + 139, /* '7' */ + 14, /* '8' */ + 136, /* '9' */ + 65, /* ':' */ + 128, /* ';' */ + 102, /* '<' */ + 132, /* '=' */ + 132, /* '>' */ + 128, /* '?' */ + 136, /* '@' */ + 135, /* 'A' */ + 110, /* 'B' */ + 132, /* 'C' */ + 102, /* 'D' */ + 98, /* 'E' */ + 138, /* 'F' */ + 166, /* 'G' */ + 139, /* 'H' */ + 164, /* 'I' */ + 136, /* 'J' */ + 163, /* 'K' */ + 135, /* 'L' */ + 166, /* 'M' */ + 139, /* 'N' */ + 168, /* 'O' */ + 142, /* 'P' */ + 158, /* 'Q' */ + 132, /* 'R' */ + 132, /* 'S' */ + 102, /* 'T' */ + 166, /* 'U' */ + 139, /* 'V' */ + 164, /* 'W' */ + 136, /* 'X' */ + 163, /* 'Y' */ + 135, /* 'Z' */ + 166, /* '[' */ + 139, /* '\' */ + 166, /* ']' */ + 139, /* '^' */ + 164, /* '_' */ + 136, /* '`' */ + 163, /* 'a' */ + 135, /* 'b' */ + 166, /* 'c' */ + 139, /* 'd' */ + 158, /* 'e' */ + 132, /* 'f' */ + 166, /* 'g' */ + 139, /* 'h' */ + 164, /* 'i' */ + 136, /* 'j' */ + 163, /* 'k' */ + 135, /* 'l' */ + 166, /* 'm' */ + 139, /* 'n' */ + 158, /* 'o' */ + 132, /* 'p' */ + 164, /* 'q' */ + 136, /* 'r' */ + 166, /* 's' */ + 139, /* 't' */ + 164, /* 'u' */ + 136, /* 'v' */ + 163, /* 'w' */ + 135, /* 'x' */ + 166, /* 'y' */ + 139, /* 'z' */ + 163, /* '{' */ + 135, /* '|' */ + 164, /* '}' */ + 136, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Bookman-DemiItalic", + 0, + YES + }, { + /* width table for font XNR */ + { + 49, /* ' ' */ + 93, /* '!' */ + 93, /* '"' */ + 93, /* '#' */ + 65, /* '$' */ + 71, /* '%' */ + 71, /* '&' */ + 43, /* ''' */ + 43, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 65, /* ',' */ + 65, /* '-' */ + 74, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 167, /* ';' */ + 133, /* '<' */ + 56, /* '=' */ + 50, /* '>' */ + 111, /* '?' */ + 52, /* '@' */ + 130, /* 'A' */ + 83, /* 'B' */ + 167, /* 'C' */ + 139, /* 'D' */ + 52, /* 'E' */ + 96, /* 'F' */ + 120, /* 'G' */ + 93, /* 'H' */ + 120, /* 'I' */ + 93, /* 'J' */ + 120, /* 'K' */ + 93, /* 'L' */ + 120, /* 'M' */ + 93, /* 'N' */ + 120, /* 'O' */ + 93, /* 'P' */ + 120, /* 'Q' */ + 93, /* 'R' */ + 120, /* 'S' */ + 74, /* 'T' */ + 120, /* 'U' */ + 83, /* 'V' */ + 120, /* 'W' */ + 83, /* 'X' */ + 120, /* 'Y' */ + 83, /* 'Z' */ + 120, /* '[' */ + 83, /* '\' */ + 68, /* ']' */ + 52, /* '^' */ + 68, /* '_' */ + 52, /* '`' */ + 68, /* 'a' */ + 52, /* 'b' */ + 68, /* 'c' */ + 52, /* 'd' */ + 136, /* 'e' */ + 102, /* 'f' */ + 130, /* 'g' */ + 83, /* 'h' */ + 130, /* 'i' */ + 83, /* 'j' */ + 130, /* 'k' */ + 83, /* 'l' */ + 130, /* 'm' */ + 83, /* 'n' */ + 130, /* 'o' */ + 83, /* 'p' */ + 105, /* 'q' */ + 77, /* 'r' */ + 136, /* 's' */ + 102, /* 't' */ + 136, /* 'u' */ + 102, /* 'v' */ + 136, /* 'w' */ + 102, /* 'x' */ + 136, /* 'y' */ + 102, /* 'z' */ + 117, /* '{' */ + 89, /* '|' */ + 102, /* '}' */ + 80, /* '~' */ + 46, /* ' ' */ + }, + /* height table for font XNR */ + { + 276, /* ' ' */ + 149, /* '!' */ + 148, /* '"' */ + 149, /* '#' */ + 150, /* '$' */ + 95, /* '%' */ + 95, /* '&' */ + 95, /* ''' */ + 95, /* '(' */ + 176, /* ')' */ + 176, /* '*' */ + 120, /* '+' */ + 76, /* ',' */ + 152, /* '-' */ + 151, /* '.' */ + 145, /* '/' */ + 145, /* '0' */ + 132, /* '1' */ + 143, /* '2' */ + 135, /* '3' */ + 135, /* '4' */ + 152, /* '5' */ + 63, /* '6' */ + 145, /* '7' */ + 53, /* '8' */ + 145, /* '9' */ + 72, /* ':' */ + 149, /* ';' */ + 111, /* '<' */ + 152, /* '=' */ + 152, /* '>' */ + 149, /* '?' */ + 151, /* '@' */ + 167, /* 'A' */ + 135, /* 'B' */ + 149, /* 'C' */ + 111, /* 'D' */ + 105, /* 'E' */ + 154, /* 'F' */ + 187, /* 'G' */ + 148, /* 'H' */ + 187, /* 'I' */ + 147, /* 'J' */ + 178, /* 'K' */ + 137, /* 'L' */ + 187, /* 'M' */ + 148, /* 'N' */ + 192, /* 'O' */ + 154, /* 'P' */ + 180, /* 'Q' */ + 140, /* 'R' */ + 188, /* 'S' */ + 144, /* 'T' */ + 187, /* 'U' */ + 148, /* 'V' */ + 187, /* 'W' */ + 147, /* 'X' */ + 178, /* 'Y' */ + 137, /* 'Z' */ + 187, /* '[' */ + 148, /* '\' */ + 187, /* ']' */ + 145, /* '^' */ + 187, /* '_' */ + 145, /* '`' */ + 179, /* 'a' */ + 136, /* 'b' */ + 187, /* 'c' */ + 145, /* 'd' */ + 182, /* 'e' */ + 138, /* 'f' */ + 190, /* 'g' */ + 148, /* 'h' */ + 189, /* 'i' */ + 147, /* 'j' */ + 180, /* 'k' */ + 137, /* 'l' */ + 190, /* 'm' */ + 148, /* 'n' */ + 182, /* 'o' */ + 140, /* 'p' */ + 189, /* 'q' */ + 147, /* 'r' */ + 190, /* 's' */ + 148, /* 't' */ + 189, /* 'u' */ + 147, /* 'v' */ + 180, /* 'w' */ + 137, /* 'x' */ + 190, /* 'y' */ + 148, /* 'z' */ + 178, /* '{' */ + 167, /* '|' */ + 187, /* '}' */ + 145, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XNR */ + { + 199, /* ' ' */ + 111, /* '!' */ + 132, /* '"' */ + 135, /* '#' */ + 137, /* '$' */ + 81, /* '%' */ + 81, /* '&' */ + 81, /* ''' */ + 81, /* '(' */ + 138, /* ')' */ + 138, /* '*' */ + 106, /* '+' */ + 32, /* ',' */ + 138, /* '-' */ + 105, /* '.' */ + 132, /* '/' */ + 132, /* '0' */ + 118, /* '1' */ + 129, /* '2' */ + 121, /* '3' */ + 121, /* '4' */ + 138, /* '5' */ + 14, /* '6' */ + 131, /* '7' */ + 14, /* '8' */ + 131, /* '9' */ + 58, /* ':' */ + 135, /* ';' */ + 95, /* '<' */ + 138, /* '=' */ + 138, /* '>' */ + 135, /* '?' */ + 137, /* '@' */ + 141, /* 'A' */ + 106, /* 'B' */ + 135, /* 'C' */ + 95, /* 'D' */ + 92, /* 'E' */ + 138, /* 'F' */ + 174, /* 'G' */ + 132, /* 'H' */ + 173, /* 'I' */ + 131, /* 'J' */ + 164, /* 'K' */ + 121, /* 'L' */ + 174, /* 'M' */ + 132, /* 'N' */ + 178, /* 'O' */ + 138, /* 'P' */ + 166, /* 'Q' */ + 124, /* 'R' */ + 138, /* 'S' */ + 95, /* 'T' */ + 174, /* 'U' */ + 132, /* 'V' */ + 173, /* 'W' */ + 131, /* 'X' */ + 164, /* 'Y' */ + 121, /* 'Z' */ + 174, /* '[' */ + 132, /* '\' */ + 174, /* ']' */ + 132, /* '^' */ + 173, /* '_' */ + 131, /* '`' */ + 165, /* 'a' */ + 122, /* 'b' */ + 174, /* 'c' */ + 132, /* 'd' */ + 166, /* 'e' */ + 124, /* 'f' */ + 174, /* 'g' */ + 132, /* 'h' */ + 173, /* 'i' */ + 131, /* 'j' */ + 164, /* 'k' */ + 121, /* 'l' */ + 174, /* 'm' */ + 132, /* 'n' */ + 166, /* 'o' */ + 124, /* 'p' */ + 173, /* 'q' */ + 131, /* 'r' */ + 174, /* 's' */ + 132, /* 't' */ + 173, /* 'u' */ + 131, /* 'v' */ + 164, /* 'w' */ + 121, /* 'x' */ + 174, /* 'y' */ + 132, /* 'z' */ + 164, /* '{' */ + 121, /* '|' */ + 173, /* '}' */ + 131, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-NewCenturySchlbk-Roman", + 0, + NO + }, { + /* width table for font XNI */ + { + 55, /* ' ' */ + 93, /* '!' */ + 93, /* '"' */ + 93, /* '#' */ + 65, /* '$' */ + 71, /* '%' */ + 71, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 65, /* ',' */ + 65, /* '-' */ + 74, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 145, /* ';' */ + 120, /* '<' */ + 70, /* '=' */ + 62, /* '>' */ + 111, /* '?' */ + 55, /* '@' */ + 130, /* 'A' */ + 83, /* 'B' */ + 163, /* 'C' */ + 130, /* 'D' */ + 55, /* 'E' */ + 93, /* 'F' */ + 117, /* 'G' */ + 96, /* 'H' */ + 117, /* 'I' */ + 96, /* 'J' */ + 117, /* 'K' */ + 96, /* 'L' */ + 117, /* 'M' */ + 96, /* 'N' */ + 117, /* 'O' */ + 96, /* 'P' */ + 117, /* 'Q' */ + 96, /* 'R' */ + 120, /* 'S' */ + 74, /* 'T' */ + 120, /* 'U' */ + 74, /* 'V' */ + 120, /* 'W' */ + 74, /* 'X' */ + 120, /* 'Y' */ + 74, /* 'Z' */ + 120, /* '[' */ + 74, /* '\' */ + 68, /* ']' */ + 55, /* '^' */ + 68, /* '_' */ + 55, /* '`' */ + 68, /* 'a' */ + 55, /* 'b' */ + 68, /* 'c' */ + 55, /* 'd' */ + 136, /* 'e' */ + 102, /* 'f' */ + 130, /* 'g' */ + 83, /* 'h' */ + 130, /* 'i' */ + 83, /* 'j' */ + 130, /* 'k' */ + 83, /* 'l' */ + 130, /* 'm' */ + 83, /* 'n' */ + 130, /* 'o' */ + 83, /* 'p' */ + 111, /* 'q' */ + 74, /* 'r' */ + 136, /* 's' */ + 102, /* 't' */ + 136, /* 'u' */ + 102, /* 'v' */ + 136, /* 'w' */ + 102, /* 'x' */ + 136, /* 'y' */ + 102, /* 'z' */ + 114, /* '{' */ + 83, /* '|' */ + 111, /* '}' */ + 77, /* '~' */ + 46, /* ' ' */ + }, + /* height table for font XNI */ + { + 276, /* ' ' */ + 147, /* '!' */ + 148, /* '"' */ + 145, /* '#' */ + 151, /* '$' */ + 95, /* '%' */ + 95, /* '&' */ + 95, /* ''' */ + 95, /* '(' */ + 176, /* ')' */ + 176, /* '*' */ + 120, /* '+' */ + 74, /* ',' */ + 152, /* '-' */ + 151, /* '.' */ + 143, /* '/' */ + 143, /* '0' */ + 129, /* '1' */ + 141, /* '2' */ + 135, /* '3' */ + 135, /* '4' */ + 146, /* '5' */ + 63, /* '6' */ + 142, /* '7' */ + 53, /* '8' */ + 142, /* '9' */ + 72, /* ':' */ + 149, /* ';' */ + 108, /* '<' */ + 152, /* '=' */ + 152, /* '>' */ + 149, /* '?' */ + 154, /* '@' */ + 167, /* 'A' */ + 139, /* 'B' */ + 149, /* 'C' */ + 108, /* 'D' */ + 108, /* 'E' */ + 186, /* 'F' */ + 186, /* 'G' */ + 145, /* 'H' */ + 184, /* 'I' */ + 145, /* 'J' */ + 179, /* 'K' */ + 137, /* 'L' */ + 185, /* 'M' */ + 145, /* 'N' */ + 189, /* 'O' */ + 148, /* 'P' */ + 181, /* 'Q' */ + 138, /* 'R' */ + 188, /* 'S' */ + 141, /* 'T' */ + 186, /* 'U' */ + 145, /* 'V' */ + 184, /* 'W' */ + 145, /* 'X' */ + 179, /* 'Y' */ + 137, /* 'Z' */ + 185, /* '[' */ + 145, /* '\' */ + 186, /* ']' */ + 145, /* '^' */ + 184, /* '_' */ + 145, /* '`' */ + 179, /* 'a' */ + 138, /* 'b' */ + 185, /* 'c' */ + 145, /* 'd' */ + 183, /* 'e' */ + 138, /* 'f' */ + 188, /* 'g' */ + 145, /* 'h' */ + 187, /* 'i' */ + 145, /* 'j' */ + 182, /* 'k' */ + 137, /* 'l' */ + 188, /* 'm' */ + 145, /* 'n' */ + 183, /* 'o' */ + 138, /* 'p' */ + 187, /* 'q' */ + 144, /* 'r' */ + 188, /* 's' */ + 145, /* 't' */ + 187, /* 'u' */ + 145, /* 'v' */ + 182, /* 'w' */ + 137, /* 'x' */ + 188, /* 'y' */ + 145, /* 'z' */ + 179, /* '{' */ + 167, /* '|' */ + 184, /* '}' */ + 144, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XNI */ + { + 199, /* ' ' */ + 111, /* '!' */ + 132, /* '"' */ + 131, /* '#' */ + 137, /* '$' */ + 81, /* '%' */ + 81, /* '&' */ + 81, /* ''' */ + 81, /* '(' */ + 138, /* ')' */ + 138, /* '*' */ + 106, /* '+' */ + 32, /* ',' */ + 138, /* '-' */ + 105, /* '.' */ + 129, /* '/' */ + 129, /* '0' */ + 115, /* '1' */ + 127, /* '2' */ + 121, /* '3' */ + 121, /* '4' */ + 132, /* '5' */ + 14, /* '6' */ + 129, /* '7' */ + 14, /* '8' */ + 128, /* '9' */ + 58, /* ':' */ + 135, /* ';' */ + 92, /* '<' */ + 138, /* '=' */ + 138, /* '>' */ + 135, /* '?' */ + 138, /* '@' */ + 139, /* 'A' */ + 105, /* 'B' */ + 135, /* 'C' */ + 92, /* 'D' */ + 92, /* 'E' */ + 138, /* 'F' */ + 172, /* 'G' */ + 129, /* 'H' */ + 171, /* 'I' */ + 129, /* 'J' */ + 166, /* 'K' */ + 121, /* 'L' */ + 172, /* 'M' */ + 129, /* 'N' */ + 175, /* 'O' */ + 132, /* 'P' */ + 167, /* 'Q' */ + 122, /* 'R' */ + 138, /* 'S' */ + 92, /* 'T' */ + 172, /* 'U' */ + 129, /* 'V' */ + 171, /* 'W' */ + 129, /* 'X' */ + 166, /* 'Y' */ + 121, /* 'Z' */ + 172, /* '[' */ + 129, /* '\' */ + 172, /* ']' */ + 129, /* '^' */ + 171, /* '_' */ + 129, /* '`' */ + 166, /* 'a' */ + 122, /* 'b' */ + 172, /* 'c' */ + 129, /* 'd' */ + 167, /* 'e' */ + 122, /* 'f' */ + 172, /* 'g' */ + 129, /* 'h' */ + 171, /* 'i' */ + 129, /* 'j' */ + 166, /* 'k' */ + 121, /* 'l' */ + 172, /* 'm' */ + 129, /* 'n' */ + 167, /* 'o' */ + 122, /* 'p' */ + 171, /* 'q' */ + 128, /* 'r' */ + 172, /* 's' */ + 129, /* 't' */ + 171, /* 'u' */ + 129, /* 'v' */ + 166, /* 'w' */ + 121, /* 'x' */ + 172, /* 'y' */ + 129, /* 'z' */ + 166, /* '{' */ + 121, /* '|' */ + 171, /* '}' */ + 128, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-NewCenturySchlbk-Italic", + 0, + YES + }, { + /* width table for font XNB */ + { + 49, /* ' ' */ + 96, /* '!' */ + 96, /* '"' */ + 96, /* '#' */ + 80, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 80, /* ',' */ + 80, /* '-' */ + 83, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 163, /* ';' */ + 145, /* '<' */ + 61, /* '=' */ + 61, /* '>' */ + 120, /* '?' */ + 59, /* '@' */ + 139, /* 'A' */ + 102, /* 'B' */ + 167, /* 'C' */ + 151, /* 'D' */ + 62, /* 'E' */ + 102, /* 'F' */ + 126, /* 'G' */ + 102, /* 'H' */ + 126, /* 'I' */ + 102, /* 'J' */ + 126, /* 'K' */ + 102, /* 'L' */ + 126, /* 'M' */ + 102, /* 'N' */ + 126, /* 'O' */ + 102, /* 'P' */ + 126, /* 'Q' */ + 102, /* 'R' */ + 130, /* 'S' */ + 93, /* 'T' */ + 126, /* 'U' */ + 96, /* 'V' */ + 126, /* 'W' */ + 96, /* 'X' */ + 126, /* 'Y' */ + 96, /* 'Z' */ + 126, /* '[' */ + 96, /* '\' */ + 74, /* ']' */ + 62, /* '^' */ + 74, /* '_' */ + 62, /* '`' */ + 74, /* 'a' */ + 62, /* 'b' */ + 74, /* 'c' */ + 62, /* 'd' */ + 139, /* 'e' */ + 114, /* 'f' */ + 139, /* 'g' */ + 102, /* 'h' */ + 139, /* 'i' */ + 102, /* 'j' */ + 139, /* 'k' */ + 102, /* 'l' */ + 139, /* 'm' */ + 102, /* 'n' */ + 139, /* 'o' */ + 102, /* 'p' */ + 111, /* 'q' */ + 83, /* 'r' */ + 139, /* 's' */ + 114, /* 't' */ + 139, /* 'u' */ + 114, /* 'v' */ + 139, /* 'w' */ + 114, /* 'x' */ + 139, /* 'y' */ + 114, /* 'z' */ + 120, /* '{' */ + 102, /* '|' */ + 111, /* '}' */ + 89, /* '~' */ + 48, /* ' ' */ + }, + /* height table for font XNB */ + { + 276, /* ' ' */ + 140, /* '!' */ + 148, /* '"' */ + 149, /* '#' */ + 152, /* '$' */ + 98, /* '%' */ + 98, /* '&' */ + 98, /* ''' */ + 98, /* '(' */ + 167, /* ')' */ + 167, /* '*' */ + 115, /* '+' */ + 87, /* ',' */ + 152, /* '-' */ + 154, /* '.' */ + 152, /* '/' */ + 152, /* '0' */ + 139, /* '1' */ + 146, /* '2' */ + 143, /* '3' */ + 143, /* '4' */ + 156, /* '5' */ + 67, /* '6' */ + 152, /* '7' */ + 57, /* '8' */ + 149, /* '9' */ + 76, /* ':' */ + 149, /* ';' */ + 111, /* '<' */ + 152, /* '=' */ + 152, /* '>' */ + 149, /* '?' */ + 151, /* '@' */ + 161, /* 'A' */ + 137, /* 'B' */ + 149, /* 'C' */ + 111, /* 'D' */ + 107, /* 'E' */ + 154, /* 'F' */ + 191, /* 'G' */ + 154, /* 'H' */ + 189, /* 'I' */ + 151, /* 'J' */ + 184, /* 'K' */ + 145, /* 'L' */ + 191, /* 'M' */ + 154, /* 'N' */ + 193, /* 'O' */ + 158, /* 'P' */ + 183, /* 'Q' */ + 148, /* 'R' */ + 191, /* 'S' */ + 148, /* 'T' */ + 191, /* 'U' */ + 154, /* 'V' */ + 189, /* 'W' */ + 151, /* 'X' */ + 184, /* 'Y' */ + 146, /* 'Z' */ + 191, /* '[' */ + 154, /* '\' */ + 191, /* ']' */ + 152, /* '^' */ + 189, /* '_' */ + 149, /* '`' */ + 186, /* 'a' */ + 142, /* 'b' */ + 191, /* 'c' */ + 152, /* 'd' */ + 185, /* 'e' */ + 146, /* 'f' */ + 193, /* 'g' */ + 154, /* 'h' */ + 191, /* 'i' */ + 151, /* 'j' */ + 186, /* 'k' */ + 145, /* 'l' */ + 193, /* 'm' */ + 154, /* 'n' */ + 185, /* 'o' */ + 148, /* 'p' */ + 191, /* 'q' */ + 151, /* 'r' */ + 193, /* 's' */ + 154, /* 't' */ + 191, /* 'u' */ + 151, /* 'v' */ + 186, /* 'w' */ + 145, /* 'x' */ + 193, /* 'y' */ + 154, /* 'z' */ + 184, /* '{' */ + 175, /* '|' */ + 189, /* '}' */ + 149, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XNB */ + { + 199, /* ' ' */ + 108, /* '!' */ + 132, /* '"' */ + 135, /* '#' */ + 138, /* '$' */ + 84, /* '%' */ + 84, /* '&' */ + 84, /* ''' */ + 84, /* '(' */ + 138, /* ')' */ + 138, /* '*' */ + 101, /* '+' */ + 42, /* ',' */ + 138, /* '-' */ + 105, /* '.' */ + 138, /* '/' */ + 138, /* '0' */ + 125, /* '1' */ + 133, /* '2' */ + 129, /* '3' */ + 129, /* '4' */ + 142, /* '5' */ + 14, /* '6' */ + 138, /* '7' */ + 14, /* '8' */ + 135, /* '9' */ + 62, /* ':' */ + 135, /* ';' */ + 95, /* '<' */ + 138, /* '=' */ + 138, /* '>' */ + 135, /* '?' */ + 137, /* '@' */ + 141, /* 'A' */ + 108, /* 'B' */ + 135, /* 'C' */ + 95, /* 'D' */ + 93, /* 'E' */ + 138, /* 'F' */ + 177, /* 'G' */ + 138, /* 'H' */ + 175, /* 'I' */ + 135, /* 'J' */ + 170, /* 'K' */ + 129, /* 'L' */ + 177, /* 'M' */ + 138, /* 'N' */ + 179, /* 'O' */ + 142, /* 'P' */ + 169, /* 'Q' */ + 132, /* 'R' */ + 138, /* 'S' */ + 95, /* 'T' */ + 177, /* 'U' */ + 138, /* 'V' */ + 175, /* 'W' */ + 135, /* 'X' */ + 170, /* 'Y' */ + 129, /* 'Z' */ + 177, /* '[' */ + 138, /* '\' */ + 177, /* ']' */ + 138, /* '^' */ + 175, /* '_' */ + 135, /* '`' */ + 172, /* 'a' */ + 128, /* 'b' */ + 177, /* 'c' */ + 138, /* 'd' */ + 169, /* 'e' */ + 132, /* 'f' */ + 177, /* 'g' */ + 138, /* 'h' */ + 175, /* 'i' */ + 135, /* 'j' */ + 170, /* 'k' */ + 129, /* 'l' */ + 177, /* 'm' */ + 138, /* 'n' */ + 169, /* 'o' */ + 132, /* 'p' */ + 175, /* 'q' */ + 135, /* 'r' */ + 177, /* 's' */ + 138, /* 't' */ + 175, /* 'u' */ + 135, /* 'v' */ + 170, /* 'w' */ + 129, /* 'x' */ + 177, /* 'y' */ + 138, /* 'z' */ + 170, /* '{' */ + 129, /* '|' */ + 175, /* '}' */ + 135, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-NewCenturySchlbk-Bold", + 0, + NO + }, { + /* width table for font XNX */ + { + 55, /* ' ' */ + 96, /* '!' */ + 96, /* '"' */ + 96, /* '#' */ + 80, /* '$' */ + 80, /* '%' */ + 80, /* '&' */ + 46, /* ''' */ + 46, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 80, /* ',' */ + 80, /* '-' */ + 80, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 148, /* ';' */ + 136, /* '<' */ + 69, /* '=' */ + 59, /* '>' */ + 117, /* '?' */ + 65, /* '@' */ + 139, /* 'A' */ + 96, /* 'B' */ + 160, /* 'C' */ + 142, /* 'D' */ + 65, /* 'E' */ + 96, /* 'F' */ + 123, /* 'G' */ + 111, /* 'H' */ + 123, /* 'I' */ + 111, /* 'J' */ + 123, /* 'K' */ + 111, /* 'L' */ + 123, /* 'M' */ + 111, /* 'N' */ + 123, /* 'O' */ + 111, /* 'P' */ + 123, /* 'Q' */ + 111, /* 'R' */ + 126, /* 'S' */ + 89, /* 'T' */ + 123, /* 'U' */ + 86, /* 'V' */ + 123, /* 'W' */ + 86, /* 'X' */ + 123, /* 'Y' */ + 86, /* 'Z' */ + 123, /* '[' */ + 86, /* '\' */ + 74, /* ']' */ + 65, /* '^' */ + 74, /* '_' */ + 65, /* '`' */ + 74, /* 'a' */ + 65, /* 'b' */ + 74, /* 'c' */ + 65, /* 'd' */ + 142, /* 'e' */ + 114, /* 'f' */ + 139, /* 'g' */ + 96, /* 'h' */ + 139, /* 'i' */ + 96, /* 'j' */ + 139, /* 'k' */ + 96, /* 'l' */ + 139, /* 'm' */ + 96, /* 'n' */ + 139, /* 'o' */ + 96, /* 'p' */ + 114, /* 'q' */ + 80, /* 'r' */ + 139, /* 's' */ + 114, /* 't' */ + 139, /* 'u' */ + 114, /* 'v' */ + 139, /* 'w' */ + 114, /* 'x' */ + 139, /* 'y' */ + 114, /* 'z' */ + 117, /* '{' */ + 86, /* '|' */ + 117, /* '}' */ + 86, /* '~' */ + 48, /* ' ' */ + }, + /* height table for font XNX */ + { + 276, /* ' ' */ + 148, /* '!' */ + 148, /* '"' */ + 146, /* '#' */ + 151, /* '$' */ + 98, /* '%' */ + 98, /* '&' */ + 98, /* ''' */ + 98, /* '(' */ + 176, /* ')' */ + 177, /* '*' */ + 114, /* '+' */ + 85, /* ',' */ + 152, /* '-' */ + 151, /* '.' */ + 148, /* '/' */ + 148, /* '0' */ + 136, /* '1' */ + 145, /* '2' */ + 142, /* '3' */ + 142, /* '4' */ + 152, /* '5' */ + 63, /* '6' */ + 146, /* '7' */ + 57, /* '8' */ + 146, /* '9' */ + 76, /* ':' */ + 149, /* ';' */ + 111, /* '<' */ + 152, /* '=' */ + 152, /* '>' */ + 149, /* '?' */ + 154, /* '@' */ + 170, /* 'A' */ + 145, /* 'B' */ + 149, /* 'C' */ + 111, /* 'D' */ + 111, /* 'E' */ + 186, /* 'F' */ + 187, /* 'G' */ + 150, /* 'H' */ + 186, /* 'I' */ + 148, /* 'J' */ + 183, /* 'K' */ + 144, /* 'L' */ + 187, /* 'M' */ + 150, /* 'N' */ + 196, /* 'O' */ + 154, /* 'P' */ + 182, /* 'Q' */ + 144, /* 'R' */ + 188, /* 'S' */ + 144, /* 'T' */ + 187, /* 'U' */ + 150, /* 'V' */ + 186, /* 'W' */ + 148, /* 'X' */ + 183, /* 'Y' */ + 144, /* 'Z' */ + 187, /* '[' */ + 150, /* '\' */ + 187, /* ']' */ + 150, /* '^' */ + 186, /* '_' */ + 148, /* '`' */ + 183, /* 'a' */ + 144, /* 'b' */ + 187, /* 'c' */ + 150, /* 'd' */ + 184, /* 'e' */ + 144, /* 'f' */ + 190, /* 'g' */ + 150, /* 'h' */ + 188, /* 'i' */ + 148, /* 'j' */ + 185, /* 'k' */ + 144, /* 'l' */ + 190, /* 'm' */ + 150, /* 'n' */ + 184, /* 'o' */ + 144, /* 'p' */ + 188, /* 'q' */ + 148, /* 'r' */ + 190, /* 's' */ + 150, /* 't' */ + 188, /* 'u' */ + 148, /* 'v' */ + 185, /* 'w' */ + 144, /* 'x' */ + 190, /* 'y' */ + 150, /* 'z' */ + 183, /* '{' */ + 177, /* '|' */ + 186, /* '}' */ + 148, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XNX */ + { + 199, /* ' ' */ + 112, /* '!' */ + 132, /* '"' */ + 132, /* '#' */ + 137, /* '$' */ + 84, /* '%' */ + 84, /* '&' */ + 84, /* ''' */ + 84, /* '(' */ + 138, /* ')' */ + 138, /* '*' */ + 100, /* '+' */ + 40, /* ',' */ + 138, /* '-' */ + 105, /* '.' */ + 134, /* '/' */ + 134, /* '0' */ + 122, /* '1' */ + 131, /* '2' */ + 128, /* '3' */ + 128, /* '4' */ + 138, /* '5' */ + 14, /* '6' */ + 132, /* '7' */ + 14, /* '8' */ + 132, /* '9' */ + 62, /* ':' */ + 135, /* ';' */ + 95, /* '<' */ + 138, /* '=' */ + 138, /* '>' */ + 135, /* '?' */ + 138, /* '@' */ + 143, /* 'A' */ + 110, /* 'B' */ + 135, /* 'C' */ + 95, /* 'D' */ + 95, /* 'E' */ + 138, /* 'F' */ + 174, /* 'G' */ + 134, /* 'H' */ + 172, /* 'I' */ + 132, /* 'J' */ + 169, /* 'K' */ + 128, /* 'L' */ + 174, /* 'M' */ + 134, /* 'N' */ + 182, /* 'O' */ + 138, /* 'P' */ + 168, /* 'Q' */ + 128, /* 'R' */ + 138, /* 'S' */ + 95, /* 'T' */ + 174, /* 'U' */ + 134, /* 'V' */ + 172, /* 'W' */ + 132, /* 'X' */ + 169, /* 'Y' */ + 128, /* 'Z' */ + 174, /* '[' */ + 134, /* '\' */ + 174, /* ']' */ + 134, /* '^' */ + 172, /* '_' */ + 132, /* '`' */ + 169, /* 'a' */ + 128, /* 'b' */ + 174, /* 'c' */ + 134, /* 'd' */ + 168, /* 'e' */ + 128, /* 'f' */ + 174, /* 'g' */ + 134, /* 'h' */ + 172, /* 'i' */ + 132, /* 'j' */ + 169, /* 'k' */ + 128, /* 'l' */ + 174, /* 'm' */ + 134, /* 'n' */ + 168, /* 'o' */ + 128, /* 'p' */ + 172, /* 'q' */ + 132, /* 'r' */ + 174, /* 's' */ + 134, /* 't' */ + 172, /* 'u' */ + 132, /* 'v' */ + 169, /* 'w' */ + 128, /* 'x' */ + 174, /* 'y' */ + 134, /* 'z' */ + 169, /* '{' */ + 128, /* '|' */ + 172, /* '}' */ + 132, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-NewCenturySchlbk-BoldItalic", + 0, + YES + }, { + /* width table for font XPR */ + { + 46, /* ' ' */ + 83, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 83, /* ',' */ + 83, /* '-' */ + 74, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 42, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 63, /* '7' */ + 52, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 157, /* ';' */ + 126, /* '<' */ + 55, /* '=' */ + 55, /* '>' */ + 102, /* '?' */ + 48, /* '@' */ + 139, /* 'A' */ + 93, /* 'B' */ + 166, /* 'C' */ + 138, /* 'D' */ + 48, /* 'E' */ + 93, /* 'F' */ + 130, /* 'G' */ + 83, /* 'H' */ + 130, /* 'I' */ + 83, /* 'J' */ + 130, /* 'K' */ + 83, /* 'L' */ + 130, /* 'M' */ + 83, /* 'N' */ + 130, /* 'O' */ + 83, /* 'P' */ + 130, /* 'Q' */ + 83, /* 'R' */ + 118, /* 'S' */ + 74, /* 'T' */ + 102, /* 'U' */ + 80, /* 'V' */ + 102, /* 'W' */ + 80, /* 'X' */ + 102, /* 'Y' */ + 80, /* 'Z' */ + 102, /* '[' */ + 80, /* '\' */ + 56, /* ']' */ + 48, /* '^' */ + 56, /* '_' */ + 48, /* '`' */ + 56, /* 'a' */ + 48, /* 'b' */ + 56, /* 'c' */ + 48, /* 'd' */ + 138, /* 'e' */ + 97, /* 'f' */ + 131, /* 'g' */ + 91, /* 'h' */ + 131, /* 'i' */ + 91, /* 'j' */ + 131, /* 'k' */ + 91, /* 'l' */ + 131, /* 'm' */ + 91, /* 'n' */ + 131, /* 'o' */ + 91, /* 'p' */ + 87, /* 'q' */ + 71, /* 'r' */ + 130, /* 's' */ + 100, /* 't' */ + 130, /* 'u' */ + 100, /* 'v' */ + 130, /* 'w' */ + 100, /* 'x' */ + 130, /* 'y' */ + 100, /* 'z' */ + 111, /* '{' */ + 93, /* '|' */ + 111, /* '}' */ + 83, /* '~' */ + 42, /* ' ' */ + }, + /* height table for font XPR */ + { + 268, /* ' ' */ + 138, /* '!' */ + 144, /* '"' */ + 146, /* '#' */ + 146, /* '$' */ + 99, /* '%' */ + 99, /* '&' */ + 99, /* ''' */ + 99, /* '(' */ + 144, /* ')' */ + 185, /* '*' */ + 114, /* '+' */ + 72, /* ',' */ + 146, /* '-' */ + 144, /* '.' */ + 141, /* '/' */ + 141, /* '0' */ + 126, /* '1' */ + 138, /* '2' */ + 134, /* '3' */ + 134, /* '4' */ + 146, /* '5' */ + 65, /* '6' */ + 142, /* '7' */ + 53, /* '8' */ + 141, /* '9' */ + 76, /* ':' */ + 143, /* ';' */ + 108, /* '<' */ + 146, /* '=' */ + 146, /* '>' */ + 143, /* '?' */ + 149, /* '@' */ + 149, /* 'A' */ + 111, /* 'B' */ + 148, /* 'C' */ + 108, /* 'D' */ + 106, /* 'E' */ + 151, /* 'F' */ + 180, /* 'G' */ + 143, /* 'H' */ + 180, /* 'I' */ + 143, /* 'J' */ + 173, /* 'K' */ + 136, /* 'L' */ + 180, /* 'M' */ + 143, /* 'N' */ + 186, /* 'O' */ + 148, /* 'P' */ + 173, /* 'Q' */ + 138, /* 'R' */ + 184, /* 'S' */ + 144, /* 'T' */ + 180, /* 'U' */ + 143, /* 'V' */ + 180, /* 'W' */ + 143, /* 'X' */ + 173, /* 'Y' */ + 136, /* 'Z' */ + 180, /* '[' */ + 143, /* '\' */ + 180, /* ']' */ + 141, /* '^' */ + 180, /* '_' */ + 141, /* '`' */ + 173, /* 'a' */ + 139, /* 'b' */ + 180, /* 'c' */ + 141, /* 'd' */ + 176, /* 'e' */ + 136, /* 'f' */ + 181, /* 'g' */ + 143, /* 'h' */ + 181, /* 'i' */ + 143, /* 'j' */ + 175, /* 'k' */ + 136, /* 'l' */ + 181, /* 'm' */ + 143, /* 'n' */ + 175, /* 'o' */ + 138, /* 'p' */ + 181, /* 'q' */ + 143, /* 'r' */ + 181, /* 's' */ + 143, /* 't' */ + 181, /* 'u' */ + 143, /* 'v' */ + 175, /* 'w' */ + 136, /* 'x' */ + 181, /* 'y' */ + 143, /* 'z' */ + 173, /* '{' */ + 180, /* '|' */ + 180, /* '}' */ + 141, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XPR */ + { + 186, /* ' ' */ + 108, /* '!' */ + 128, /* '"' */ + 132, /* '#' */ + 132, /* '$' */ + 85, /* '%' */ + 85, /* '&' */ + 85, /* ''' */ + 85, /* '(' */ + 130, /* ')' */ + 130, /* '*' */ + 100, /* '+' */ + 32, /* ',' */ + 132, /* '-' */ + 92, /* '.' */ + 127, /* '/' */ + 127, /* '0' */ + 112, /* '1' */ + 125, /* '2' */ + 120, /* '3' */ + 120, /* '4' */ + 132, /* '5' */ + 12, /* '6' */ + 128, /* '7' */ + 14, /* '8' */ + 127, /* '9' */ + 62, /* ':' */ + 128, /* ';' */ + 92, /* '<' */ + 132, /* '=' */ + 132, /* '>' */ + 128, /* '?' */ + 135, /* '@' */ + 132, /* 'A' */ + 93, /* 'B' */ + 132, /* 'C' */ + 92, /* 'D' */ + 92, /* 'E' */ + 135, /* 'F' */ + 165, /* 'G' */ + 127, /* 'H' */ + 165, /* 'I' */ + 127, /* 'J' */ + 159, /* 'K' */ + 120, /* 'L' */ + 165, /* 'M' */ + 127, /* 'N' */ + 172, /* 'O' */ + 132, /* 'P' */ + 159, /* 'Q' */ + 122, /* 'R' */ + 132, /* 'S' */ + 92, /* 'T' */ + 165, /* 'U' */ + 127, /* 'V' */ + 165, /* 'W' */ + 127, /* 'X' */ + 159, /* 'Y' */ + 120, /* 'Z' */ + 165, /* '[' */ + 127, /* '\' */ + 165, /* ']' */ + 127, /* '^' */ + 165, /* '_' */ + 127, /* '`' */ + 158, /* 'a' */ + 125, /* 'b' */ + 165, /* 'c' */ + 127, /* 'd' */ + 159, /* 'e' */ + 122, /* 'f' */ + 165, /* 'g' */ + 127, /* 'h' */ + 165, /* 'i' */ + 127, /* 'j' */ + 159, /* 'k' */ + 120, /* 'l' */ + 165, /* 'm' */ + 127, /* 'n' */ + 159, /* 'o' */ + 122, /* 'p' */ + 165, /* 'q' */ + 127, /* 'r' */ + 165, /* 's' */ + 127, /* 't' */ + 165, /* 'u' */ + 127, /* 'v' */ + 159, /* 'w' */ + 120, /* 'x' */ + 165, /* 'y' */ + 127, /* 'z' */ + 159, /* '{' */ + 120, /* '|' */ + 165, /* '}' */ + 127, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Palatino-Roman", + 0, + NO + }, { + /* width table for font XPI */ + { + 55, /* ' ' */ + 83, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 83, /* '+' */ + 83, /* ',' */ + 83, /* '-' */ + 83, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 157, /* ';' */ + 106, /* '<' */ + 55, /* '=' */ + 55, /* '>' */ + 93, /* '?' */ + 46, /* '@' */ + 130, /* 'A' */ + 74, /* 'B' */ + 171, /* 'C' */ + 111, /* 'D' */ + 46, /* 'E' */ + 83, /* 'F' */ + 120, /* 'G' */ + 74, /* 'H' */ + 120, /* 'I' */ + 74, /* 'J' */ + 120, /* 'K' */ + 74, /* 'L' */ + 120, /* 'M' */ + 74, /* 'N' */ + 120, /* 'O' */ + 74, /* 'P' */ + 120, /* 'Q' */ + 74, /* 'R' */ + 111, /* 'S' */ + 68, /* 'T' */ + 102, /* 'U' */ + 65, /* 'V' */ + 102, /* 'W' */ + 65, /* 'X' */ + 102, /* 'Y' */ + 65, /* 'Z' */ + 102, /* '[' */ + 65, /* '\' */ + 55, /* ']' */ + 46, /* '^' */ + 55, /* '_' */ + 46, /* '`' */ + 55, /* 'a' */ + 46, /* 'b' */ + 55, /* 'c' */ + 46, /* 'd' */ + 130, /* 'e' */ + 93, /* 'f' */ + 130, /* 'g' */ + 74, /* 'h' */ + 130, /* 'i' */ + 74, /* 'j' */ + 130, /* 'k' */ + 74, /* 'l' */ + 130, /* 'm' */ + 74, /* 'n' */ + 130, /* 'o' */ + 74, /* 'p' */ + 93, /* 'q' */ + 65, /* 'r' */ + 130, /* 's' */ + 93, /* 't' */ + 130, /* 'u' */ + 93, /* 'v' */ + 130, /* 'w' */ + 93, /* 'x' */ + 130, /* 'y' */ + 93, /* 'z' */ + 111, /* '{' */ + 83, /* '|' */ + 111, /* '}' */ + 74, /* '~' */ + 42, /* ' ' */ + }, + /* height table for font XPI */ + { + 277, /* ' ' */ + 136, /* '!' */ + 149, /* '"' */ + 144, /* '#' */ + 150, /* '$' */ + 101, /* '%' */ + 101, /* '&' */ + 101, /* ''' */ + 101, /* '(' */ + 143, /* ')' */ + 170, /* '*' */ + 115, /* '+' */ + 68, /* ',' */ + 150, /* '-' */ + 148, /* '.' */ + 142, /* '/' */ + 142, /* '0' */ + 126, /* '1' */ + 141, /* '2' */ + 135, /* '3' */ + 134, /* '4' */ + 149, /* '5' */ + 63, /* '6' */ + 150, /* '7' */ + 60, /* '8' */ + 141, /* '9' */ + 72, /* ':' */ + 143, /* ';' */ + 111, /* '<' */ + 146, /* '=' */ + 146, /* '>' */ + 142, /* '?' */ + 152, /* '@' */ + 154, /* 'A' */ + 117, /* 'B' */ + 148, /* 'C' */ + 111, /* 'D' */ + 111, /* 'E' */ + 194, /* 'F' */ + 178, /* 'G' */ + 144, /* 'H' */ + 176, /* 'I' */ + 143, /* 'J' */ + 169, /* 'K' */ + 136, /* 'L' */ + 178, /* 'M' */ + 144, /* 'N' */ + 184, /* 'O' */ + 151, /* 'P' */ + 173, /* 'Q' */ + 138, /* 'R' */ + 181, /* 'S' */ + 144, /* 'T' */ + 177, /* 'U' */ + 144, /* 'V' */ + 176, /* 'W' */ + 143, /* 'X' */ + 169, /* 'Y' */ + 136, /* 'Z' */ + 177, /* '[' */ + 144, /* '\' */ + 177, /* ']' */ + 144, /* '^' */ + 176, /* '_' */ + 143, /* '`' */ + 169, /* 'a' */ + 141, /* 'b' */ + 177, /* 'c' */ + 144, /* 'd' */ + 174, /* 'e' */ + 138, /* 'f' */ + 179, /* 'g' */ + 144, /* 'h' */ + 178, /* 'i' */ + 143, /* 'j' */ + 171, /* 'k' */ + 136, /* 'l' */ + 179, /* 'm' */ + 144, /* 'n' */ + 174, /* 'o' */ + 138, /* 'p' */ + 181, /* 'q' */ + 143, /* 'r' */ + 179, /* 's' */ + 144, /* 't' */ + 178, /* 'u' */ + 143, /* 'v' */ + 171, /* 'w' */ + 136, /* 'x' */ + 179, /* 'y' */ + 144, /* 'z' */ + 169, /* '{' */ + 179, /* '|' */ + 179, /* '}' */ + 143, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XPI */ + { + 186, /* ' ' */ + 106, /* '!' */ + 132, /* '"' */ + 130, /* '#' */ + 136, /* '$' */ + 87, /* '%' */ + 87, /* '&' */ + 87, /* ''' */ + 87, /* '(' */ + 129, /* ')' */ + 129, /* '*' */ + 102, /* '+' */ + 34, /* ',' */ + 136, /* '-' */ + 92, /* '.' */ + 128, /* '/' */ + 128, /* '0' */ + 112, /* '1' */ + 127, /* '2' */ + 121, /* '3' */ + 120, /* '4' */ + 135, /* '5' */ + 14, /* '6' */ + 136, /* '7' */ + 11, /* '8' */ + 127, /* '9' */ + 58, /* ':' */ + 129, /* ';' */ + 95, /* '<' */ + 132, /* '=' */ + 132, /* '>' */ + 128, /* '?' */ + 136, /* '@' */ + 134, /* 'A' */ + 99, /* 'B' */ + 132, /* 'C' */ + 95, /* 'D' */ + 95, /* 'E' */ + 135, /* 'F' */ + 163, /* 'G' */ + 128, /* 'H' */ + 162, /* 'I' */ + 127, /* 'J' */ + 155, /* 'K' */ + 120, /* 'L' */ + 163, /* 'M' */ + 128, /* 'N' */ + 170, /* 'O' */ + 135, /* 'P' */ + 158, /* 'Q' */ + 122, /* 'R' */ + 132, /* 'S' */ + 95, /* 'T' */ + 163, /* 'U' */ + 128, /* 'V' */ + 162, /* 'W' */ + 127, /* 'X' */ + 155, /* 'Y' */ + 120, /* 'Z' */ + 163, /* '[' */ + 128, /* '\' */ + 163, /* ']' */ + 128, /* '^' */ + 162, /* '_' */ + 127, /* '`' */ + 155, /* 'a' */ + 125, /* 'b' */ + 163, /* 'c' */ + 128, /* 'd' */ + 158, /* 'e' */ + 122, /* 'f' */ + 163, /* 'g' */ + 128, /* 'h' */ + 162, /* 'i' */ + 127, /* 'j' */ + 155, /* 'k' */ + 120, /* 'l' */ + 163, /* 'm' */ + 128, /* 'n' */ + 158, /* 'o' */ + 122, /* 'p' */ + 165, /* 'q' */ + 127, /* 'r' */ + 163, /* 's' */ + 128, /* 't' */ + 162, /* 'u' */ + 127, /* 'v' */ + 155, /* 'w' */ + 120, /* 'x' */ + 163, /* 'y' */ + 128, /* 'z' */ + 155, /* '{' */ + 120, /* '|' */ + 165, /* '}' */ + 127, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Palatino-Italic", + 0, + YES + }, { + /* width table for font XPB */ + { + 46, /* ' ' */ + 83, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 65, /* ''' */ + 65, /* '(' */ + 83, /* ')' */ + 83, /* '*' */ + 101, /* '+' */ + 83, /* ',' */ + 83, /* '-' */ + 74, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 55, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 167, /* ';' */ + 130, /* '<' */ + 73, /* '=' */ + 81, /* '>' */ + 102, /* '?' */ + 55, /* '@' */ + 139, /* 'A' */ + 93, /* 'B' */ + 167, /* 'C' */ + 139, /* 'D' */ + 55, /* 'E' */ + 102, /* 'F' */ + 130, /* 'G' */ + 83, /* 'H' */ + 130, /* 'I' */ + 83, /* 'J' */ + 130, /* 'K' */ + 83, /* 'L' */ + 130, /* 'M' */ + 83, /* 'N' */ + 130, /* 'O' */ + 83, /* 'P' */ + 130, /* 'Q' */ + 83, /* 'R' */ + 120, /* 'S' */ + 74, /* 'T' */ + 102, /* 'U' */ + 83, /* 'V' */ + 102, /* 'W' */ + 83, /* 'X' */ + 102, /* 'Y' */ + 83, /* 'Z' */ + 102, /* '[' */ + 83, /* '\' */ + 65, /* ']' */ + 55, /* '^' */ + 65, /* '_' */ + 55, /* '`' */ + 65, /* 'a' */ + 55, /* 'b' */ + 65, /* 'c' */ + 55, /* 'd' */ + 139, /* 'e' */ + 102, /* 'f' */ + 139, /* 'g' */ + 93, /* 'h' */ + 139, /* 'i' */ + 93, /* 'j' */ + 139, /* 'k' */ + 93, /* 'l' */ + 139, /* 'm' */ + 93, /* 'n' */ + 139, /* 'o' */ + 93, /* 'p' */ + 102, /* 'q' */ + 74, /* 'r' */ + 130, /* 's' */ + 102, /* 't' */ + 130, /* 'u' */ + 102, /* 'v' */ + 130, /* 'w' */ + 102, /* 'x' */ + 130, /* 'y' */ + 102, /* 'z' */ + 111, /* '{' */ + 93, /* '|' */ + 111, /* '}' */ + 83, /* '~' */ + 42, /* ' ' */ + }, + /* height table for font XPB */ + { + 268, /* ' ' */ + 138, /* '!' */ + 142, /* '"' */ + 144, /* '#' */ + 144, /* '$' */ + 101, /* '%' */ + 101, /* '&' */ + 101, /* ''' */ + 101, /* '(' */ + 143, /* ')' */ + 183, /* '*' */ + 114, /* '+' */ + 76, /* ',' */ + 144, /* '-' */ + 144, /* '.' */ + 146, /* '/' */ + 146, /* '0' */ + 129, /* '1' */ + 139, /* '2' */ + 140, /* '3' */ + 140, /* '4' */ + 146, /* '5' */ + 62, /* '6' */ + 146, /* '7' */ + 67, /* '8' */ + 142, /* '9' */ + 76, /* ':' */ + 143, /* ';' */ + 108, /* '<' */ + 139, /* '=' */ + 139, /* '>' */ + 143, /* '?' */ + 148, /* '@' */ + 149, /* 'A' */ + 109, /* 'B' */ + 148, /* 'C' */ + 108, /* 'D' */ + 106, /* 'E' */ + 148, /* 'F' */ + 181, /* 'G' */ + 148, /* 'H' */ + 179, /* 'I' */ + 144, /* 'J' */ + 177, /* 'K' */ + 142, /* 'L' */ + 181, /* 'M' */ + 148, /* 'N' */ + 184, /* 'O' */ + 148, /* 'P' */ + 176, /* 'Q' */ + 141, /* 'R' */ + 181, /* 'S' */ + 141, /* 'T' */ + 181, /* 'U' */ + 148, /* 'V' */ + 179, /* 'W' */ + 144, /* 'X' */ + 177, /* 'Y' */ + 142, /* 'Z' */ + 181, /* '[' */ + 148, /* '\' */ + 181, /* ']' */ + 146, /* '^' */ + 179, /* '_' */ + 142, /* '`' */ + 179, /* 'a' */ + 146, /* 'b' */ + 181, /* 'c' */ + 146, /* 'd' */ + 178, /* 'e' */ + 139, /* 'f' */ + 183, /* 'g' */ + 148, /* 'h' */ + 181, /* 'i' */ + 144, /* 'j' */ + 179, /* 'k' */ + 142, /* 'l' */ + 182, /* 'm' */ + 148, /* 'n' */ + 178, /* 'o' */ + 141, /* 'p' */ + 181, /* 'q' */ + 144, /* 'r' */ + 183, /* 's' */ + 148, /* 't' */ + 181, /* 'u' */ + 144, /* 'v' */ + 179, /* 'w' */ + 142, /* 'x' */ + 182, /* 'y' */ + 148, /* 'z' */ + 177, /* '{' */ + 185, /* '|' */ + 180, /* '}' */ + 143, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XPB */ + { + 186, /* ' ' */ + 106, /* '!' */ + 125, /* '"' */ + 130, /* '#' */ + 130, /* '$' */ + 87, /* '%' */ + 87, /* '&' */ + 87, /* ''' */ + 87, /* '(' */ + 128, /* ')' */ + 128, /* '*' */ + 100, /* '+' */ + 36, /* ',' */ + 130, /* '-' */ + 92, /* '.' */ + 132, /* '/' */ + 132, /* '0' */ + 115, /* '1' */ + 125, /* '2' */ + 126, /* '3' */ + 126, /* '4' */ + 132, /* '5' */ + 13, /* '6' */ + 132, /* '7' */ + 14, /* '8' */ + 128, /* '9' */ + 62, /* ':' */ + 128, /* ';' */ + 92, /* '<' */ + 125, /* '=' */ + 125, /* '>' */ + 128, /* '?' */ + 134, /* '@' */ + 132, /* 'A' */ + 92, /* 'B' */ + 132, /* 'C' */ + 92, /* 'D' */ + 92, /* 'E' */ + 132, /* 'F' */ + 166, /* 'G' */ + 132, /* 'H' */ + 165, /* 'I' */ + 128, /* 'J' */ + 163, /* 'K' */ + 126, /* 'L' */ + 166, /* 'M' */ + 132, /* 'N' */ + 170, /* 'O' */ + 132, /* 'P' */ + 162, /* 'Q' */ + 125, /* 'R' */ + 132, /* 'S' */ + 92, /* 'T' */ + 166, /* 'U' */ + 132, /* 'V' */ + 165, /* 'W' */ + 128, /* 'X' */ + 163, /* 'Y' */ + 126, /* 'Z' */ + 166, /* '[' */ + 132, /* '\' */ + 166, /* ']' */ + 132, /* '^' */ + 165, /* '_' */ + 128, /* '`' */ + 165, /* 'a' */ + 132, /* 'b' */ + 166, /* 'c' */ + 132, /* 'd' */ + 162, /* 'e' */ + 125, /* 'f' */ + 166, /* 'g' */ + 132, /* 'h' */ + 165, /* 'i' */ + 128, /* 'j' */ + 163, /* 'k' */ + 126, /* 'l' */ + 166, /* 'm' */ + 132, /* 'n' */ + 162, /* 'o' */ + 125, /* 'p' */ + 165, /* 'q' */ + 128, /* 'r' */ + 166, /* 's' */ + 132, /* 't' */ + 165, /* 'u' */ + 128, /* 'v' */ + 163, /* 'w' */ + 126, /* 'x' */ + 166, /* 'y' */ + 132, /* 'z' */ + 163, /* '{' */ + 126, /* '|' */ + 165, /* '}' */ + 128, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Palatino-Bold", + 0, + NO + }, { + /* width table for font XPX */ + { + 55, /* ' ' */ + 83, /* '!' */ + 83, /* '"' */ + 83, /* '#' */ + 83, /* '$' */ + 83, /* '%' */ + 83, /* '&' */ + 55, /* ''' */ + 55, /* '(' */ + 93, /* ')' */ + 93, /* '*' */ + 101, /* '+' */ + 83, /* ',' */ + 83, /* '-' */ + 74, /* '.' */ + 55, /* '/' */ + 55, /* '0' */ + 55, /* '1' */ + 55, /* '2' */ + 55, /* '3' */ + 55, /* '4' */ + 93, /* '5' */ + 55, /* '6' */ + 55, /* '7' */ + 55, /* '8' */ + 55, /* '9' */ + 167, /* ':' */ + 157, /* ';' */ + 123, /* '<' */ + 55, /* '=' */ + 55, /* '>' */ + 102, /* '?' */ + 55, /* '@' */ + 139, /* 'A' */ + 93, /* 'B' */ + 157, /* 'C' */ + 130, /* 'D' */ + 55, /* 'E' */ + 93, /* 'F' */ + 120, /* 'G' */ + 93, /* 'H' */ + 120, /* 'I' */ + 93, /* 'J' */ + 120, /* 'K' */ + 93, /* 'L' */ + 120, /* 'M' */ + 93, /* 'N' */ + 120, /* 'O' */ + 93, /* 'P' */ + 120, /* 'Q' */ + 93, /* 'R' */ + 114, /* 'S' */ + 74, /* 'T' */ + 102, /* 'U' */ + 74, /* 'V' */ + 102, /* 'W' */ + 74, /* 'X' */ + 102, /* 'Y' */ + 74, /* 'Z' */ + 102, /* '[' */ + 74, /* '\' */ + 65, /* ']' */ + 55, /* '^' */ + 65, /* '_' */ + 55, /* '`' */ + 65, /* 'a' */ + 55, /* 'b' */ + 65, /* 'c' */ + 55, /* 'd' */ + 130, /* 'e' */ + 93, /* 'f' */ + 139, /* 'g' */ + 93, /* 'h' */ + 139, /* 'i' */ + 93, /* 'j' */ + 139, /* 'k' */ + 93, /* 'l' */ + 139, /* 'm' */ + 93, /* 'n' */ + 139, /* 'o' */ + 93, /* 'p' */ + 93, /* 'q' */ + 74, /* 'r' */ + 130, /* 's' */ + 93, /* 't' */ + 130, /* 'u' */ + 93, /* 'v' */ + 130, /* 'w' */ + 93, /* 'x' */ + 130, /* 'y' */ + 93, /* 'z' */ + 102, /* '{' */ + 93, /* '|' */ + 111, /* '}' */ + 83, /* '~' */ + 42, /* ' ' */ + }, + /* height table for font XPX */ + { + 270, /* ' ' */ + 136, /* '!' */ + 142, /* '"' */ + 146, /* '#' */ + 148, /* '$' */ + 102, /* '%' */ + 102, /* '&' */ + 102, /* ''' */ + 102, /* '(' */ + 143, /* ')' */ + 171, /* '*' */ + 114, /* '+' */ + 76, /* ',' */ + 148, /* '-' */ + 146, /* '.' */ + 146, /* '/' */ + 146, /* '0' */ + 129, /* '1' */ + 142, /* '2' */ + 139, /* '3' */ + 139, /* '4' */ + 146, /* '5' */ + 64, /* '6' */ + 146, /* '7' */ + 57, /* '8' */ + 142, /* '9' */ + 76, /* ':' */ + 143, /* ';' */ + 108, /* '<' */ + 142, /* '=' */ + 142, /* '>' */ + 143, /* '?' */ + 151, /* '@' */ + 158, /* 'A' */ + 120, /* 'B' */ + 148, /* 'C' */ + 108, /* 'D' */ + 108, /* 'E' */ + 194, /* 'F' */ + 180, /* 'G' */ + 148, /* 'H' */ + 178, /* 'I' */ + 144, /* 'J' */ + 175, /* 'K' */ + 141, /* 'L' */ + 180, /* 'M' */ + 148, /* 'N' */ + 184, /* 'O' */ + 148, /* 'P' */ + 173, /* 'Q' */ + 139, /* 'R' */ + 181, /* 'S' */ + 141, /* 'T' */ + 180, /* 'U' */ + 148, /* 'V' */ + 178, /* 'W' */ + 144, /* 'X' */ + 175, /* 'Y' */ + 141, /* 'Z' */ + 180, /* '[' */ + 148, /* '\' */ + 180, /* ']' */ + 148, /* '^' */ + 178, /* '_' */ + 144, /* '`' */ + 175, /* 'a' */ + 145, /* 'b' */ + 180, /* 'c' */ + 148, /* 'd' */ + 173, /* 'e' */ + 139, /* 'f' */ + 182, /* 'g' */ + 148, /* 'h' */ + 179, /* 'i' */ + 144, /* 'j' */ + 177, /* 'k' */ + 141, /* 'l' */ + 182, /* 'm' */ + 148, /* 'n' */ + 174, /* 'o' */ + 139, /* 'p' */ + 179, /* 'q' */ + 144, /* 'r' */ + 182, /* 's' */ + 148, /* 't' */ + 179, /* 'u' */ + 144, /* 'v' */ + 177, /* 'w' */ + 141, /* 'x' */ + 182, /* 'y' */ + 148, /* 'z' */ + 175, /* '{' */ + 185, /* '|' */ + 177, /* '}' */ + 144, /* '~' */ + 28, /* ' ' */ + }, + /* ascent table for font XPX */ + { + 188, /* ' ' */ + 105, /* '!' */ + 128, /* '"' */ + 132, /* '#' */ + 134, /* '$' */ + 88, /* '%' */ + 88, /* '&' */ + 88, /* ''' */ + 88, /* '(' */ + 128, /* ')' */ + 132, /* '*' */ + 100, /* '+' */ + 38, /* ',' */ + 134, /* '-' */ + 94, /* '.' */ + 132, /* '/' */ + 132, /* '0' */ + 115, /* '1' */ + 128, /* '2' */ + 125, /* '3' */ + 125, /* '4' */ + 132, /* '5' */ + 15, /* '6' */ + 132, /* '7' */ + 11, /* '8' */ + 128, /* '9' */ + 62, /* ':' */ + 128, /* ';' */ + 92, /* '<' */ + 128, /* '=' */ + 128, /* '>' */ + 128, /* '?' */ + 135, /* '@' */ + 136, /* 'A' */ + 98, /* 'B' */ + 132, /* 'C' */ + 92, /* 'D' */ + 92, /* 'E' */ + 135, /* 'F' */ + 166, /* 'G' */ + 132, /* 'H' */ + 163, /* 'I' */ + 128, /* 'J' */ + 161, /* 'K' */ + 125, /* 'L' */ + 166, /* 'M' */ + 132, /* 'N' */ + 170, /* 'O' */ + 132, /* 'P' */ + 158, /* 'Q' */ + 123, /* 'R' */ + 132, /* 'S' */ + 92, /* 'T' */ + 166, /* 'U' */ + 132, /* 'V' */ + 163, /* 'W' */ + 128, /* 'X' */ + 161, /* 'Y' */ + 125, /* 'Z' */ + 166, /* '[' */ + 132, /* '\' */ + 166, /* ']' */ + 132, /* '^' */ + 163, /* '_' */ + 128, /* '`' */ + 161, /* 'a' */ + 129, /* 'b' */ + 166, /* 'c' */ + 132, /* 'd' */ + 158, /* 'e' */ + 123, /* 'f' */ + 166, /* 'g' */ + 132, /* 'h' */ + 163, /* 'i' */ + 128, /* 'j' */ + 161, /* 'k' */ + 125, /* 'l' */ + 166, /* 'm' */ + 132, /* 'n' */ + 158, /* 'o' */ + 123, /* 'p' */ + 163, /* 'q' */ + 128, /* 'r' */ + 166, /* 's' */ + 132, /* 't' */ + 163, /* 'u' */ + 128, /* 'v' */ + 161, /* 'w' */ + 125, /* 'x' */ + 166, /* 'y' */ + 132, /* 'z' */ + 161, /* '{' */ + 125, /* '|' */ + 163, /* '}' */ + 128, /* '~' */ + 14, /* ' ' */ + }, + + "Ext-Palatino-BoldItalic", + 0, + YES + }, { +#endif + /* width table for font ZD */ + { + 46, /* ' ' */ + 162, /* '!' */ + 160, /* '"' */ + 162, /* '#' */ + 163, /* '$' */ + 120, /* '%' */ + 131, /* '&' */ + 132, /* ''' */ + 132, /* '(' */ + 115, /* ')' */ + 160, /* '*' */ + 156, /* '+' */ + 91, /* ',' */ + 142, /* '-' */ + 152, /* '.' */ + 155, /* '/' */ + 152, /* '0' */ + 157, /* '1' */ + 162, /* '2' */ + 126, /* '3' */ + 141, /* '4' */ + 127, /* '5' */ + 127, /* '6' */ + 95, /* '7' */ + 113, /* '8' */ + 127, /* '9' */ + 127, /* ':' */ + 126, /* ';' */ + 126, /* '<' */ + 82, /* '=' */ + 92, /* '>' */ + 89, /* '?' */ + 96, /* '@' */ + 115, /* 'A' */ + 131, /* 'B' */ + 131, /* 'C' */ + 131, /* 'D' */ + 132, /* 'E' */ + 132, /* 'F' */ + 132, /* 'G' */ + 136, /* 'H' */ + 137, /* 'I' */ + 131, /* 'J' */ + 140, /* 'K' */ + 137, /* 'L' */ + 139, /* 'M' */ + 136, /* 'N' */ + 138, /* 'O' */ + 154, /* 'P' */ + 124, /* 'Q' */ + 120, /* 'R' */ + 125, /* 'S' */ + 132, /* 'T' */ + 132, /* 'U' */ + 116, /* 'V' */ + 129, /* 'W' */ + 128, /* 'X' */ + 132, /* 'Y' */ + 126, /* 'Z' */ + 118, /* '[' */ + 118, /* '\' */ + 114, /* ']' */ + 117, /* '^' */ + 138, /* '_' */ + 136, /* '`' */ + 131, /* 'a' */ + 131, /* 'b' */ + 118, /* 'c' */ + 114, /* 'd' */ + 116, /* 'e' */ + 115, /* 'f' */ + 131, /* 'g' */ + 131, /* 'h' */ + 119, /* 'i' */ + 132, /* 'j' */ + 131, /* 'k' */ + 132, /* 'l' */ + 145, /* 'm' */ + 127, /* 'n' */ + 127, /* 'o' */ + 127, /* 'p' */ + 126, /* 'q' */ + 126, /* 'r' */ + 149, /* 's' */ + 149, /* 't' */ + 131, /* 'u' */ + 131, /* 'v' */ + 73, /* 'w' */ + 23, /* 'x' */ + 46, /* 'y' */ + 69, /* 'z' */ + 65, /* '{' */ + 65, /* '|' */ + 111, /* '}' */ + 111, /* '~' */ + }, + /* height table for font ZD */ + { + 153, /* ' ' */ + 129, /* '!' */ + 129, /* '"' */ + 129, /* '#' */ + 142, /* '$' */ + 122, /* '%' */ + 148, /* '&' */ + 148, /* ''' */ + 148, /* '(' */ + 119, /* ')' */ + 122, /* '*' */ + 119, /* '+' */ + 148, /* ',' */ + 133, /* '-' */ + 135, /* '.' */ + 119, /* '/' */ + 132, /* '0' */ + 119, /* '1' */ + 126, /* '2' */ + 147, /* '3' */ + 148, /* '4' */ + 143, /* '5' */ + 143, /* '6' */ + 149, /* '7' */ + 148, /* '8' */ + 142, /* '9' */ + 142, /* ':' */ + 143, /* ';' */ + 142, /* '<' */ + 142, /* '=' */ + 144, /* '>' */ + 142, /* '?' */ + 127, /* '@' */ + 147, /* 'A' */ + 148, /* 'B' */ + 148, /* 'C' */ + 148, /* 'D' */ + 148, /* 'E' */ + 148, /* 'F' */ + 148, /* 'G' */ + 148, /* 'H' */ + 148, /* 'I' */ + 148, /* 'J' */ + 148, /* 'K' */ + 147, /* 'L' */ + 148, /* 'M' */ + 148, /* 'N' */ + 148, /* 'O' */ + 148, /* 'P' */ + 142, /* 'Q' */ + 142, /* 'R' */ + 142, /* 'S' */ + 148, /* 'T' */ + 148, /* 'U' */ + 148, /* 'V' */ + 148, /* 'W' */ + 145, /* 'X' */ + 148, /* 'Y' */ + 142, /* 'Z' */ + 148, /* '[' */ + 148, /* '\' */ + 144, /* ']' */ + 148, /* '^' */ + 149, /* '_' */ + 148, /* '`' */ + 148, /* 'a' */ + 148, /* 'b' */ + 147, /* 'c' */ + 142, /* 'd' */ + 143, /* 'e' */ + 141, /* 'f' */ + 148, /* 'g' */ + 148, /* 'h' */ + 148, /* 'i' */ + 148, /* 'j' */ + 148, /* 'k' */ + 148, /* 'l' */ + 148, /* 'm' */ + 142, /* 'n' */ + 142, /* 'o' */ + 144, /* 'p' */ + 142, /* 'q' */ + 144, /* 'r' */ + 145, /* 's' */ + 145, /* 't' */ + 148, /* 'u' */ + 148, /* 'v' */ + 148, /* 'w' */ + 142, /* 'x' */ + 142, /* 'y' */ + 142, /* 'z' */ + 146, /* '{' */ + 146, /* '|' */ + 145, /* '}' */ + 146, /* '~' */ + }, + /* ascent table for font ZD */ + { + 108, /* ' ' */ + 115, /* '!' */ + 115, /* '"' */ + 115, /* '#' */ + 128, /* '$' */ + 108, /* '%' */ + 132, /* '&' */ + 132, /* ''' */ + 132, /* '(' */ + 105, /* ')' */ + 108, /* '*' */ + 105, /* '+' */ + 132, /* ',' */ + 119, /* '-' */ + 121, /* '.' */ + 105, /* '/' */ + 118, /* '0' */ + 105, /* '1' */ + 112, /* '2' */ + 131, /* '3' */ + 132, /* '4' */ + 129, /* '5' */ + 129, /* '6' */ + 124, /* '7' */ + 132, /* '8' */ + 128, /* '9' */ + 128, /* ':' */ + 129, /* ';' */ + 128, /* '<' */ + 128, /* '=' */ + 128, /* '>' */ + 128, /* '?' */ + 113, /* '@' */ + 131, /* 'A' */ + 132, /* 'B' */ + 132, /* 'C' */ + 132, /* 'D' */ + 132, /* 'E' */ + 132, /* 'F' */ + 132, /* 'G' */ + 132, /* 'H' */ + 134, /* 'I' */ + 132, /* 'J' */ + 132, /* 'K' */ + 132, /* 'L' */ + 132, /* 'M' */ + 132, /* 'N' */ + 132, /* 'O' */ + 132, /* 'P' */ + 128, /* 'Q' */ + 128, /* 'R' */ + 128, /* 'S' */ + 132, /* 'T' */ + 132, /* 'U' */ + 132, /* 'V' */ + 132, /* 'W' */ + 130, /* 'X' */ + 134, /* 'Y' */ + 128, /* 'Z' */ + 132, /* '[' */ + 132, /* '\' */ + 130, /* ']' */ + 132, /* '^' */ + 133, /* '_' */ + 132, /* '`' */ + 132, /* 'a' */ + 132, /* 'b' */ + 133, /* 'c' */ + 129, /* 'd' */ + 129, /* 'e' */ + 127, /* 'f' */ + 132, /* 'g' */ + 132, /* 'h' */ + 132, /* 'i' */ + 132, /* 'j' */ + 132, /* 'k' */ + 132, /* 'l' */ + 132, /* 'm' */ + 128, /* 'n' */ + 128, /* 'o' */ + 128, /* 'p' */ + 128, /* 'q' */ + 128, /* 'r' */ + 132, /* 's' */ + 128, /* 't' */ + 131, /* 'u' */ + 131, /* 'v' */ + 132, /* 'w' */ + 128, /* 'x' */ + 128, /* 'y' */ + 128, /* 'z' */ + 132, /* '{' */ + 132, /* '|' */ + 131, /* '}' */ + 132, /* '~' */ + }, + + "ZapfDingbats", + 0, + NO + }, { + /* width table for font ZI */ + { + 37, /* ' ' */ + 47, /* '!' */ + 37, /* '"' */ + 73, /* '#' */ + 73, /* '$' */ + 113, /* '%' */ + 130, /* '&' */ + 40, /* ''' */ + 43, /* '(' */ + 37, /* ')' */ + 70, /* '*' */ + 87, /* '+' */ + 37, /* ',' */ + 47, /* '-' */ + 37, /* '.' */ + 57, /* '/' */ + 73, /* '0' */ + 73, /* '1' */ + 73, /* '2' */ + 73, /* '3' */ + 73, /* '4' */ + 73, /* '5' */ + 73, /* '6' */ + 73, /* '7' */ + 73, /* '8' */ + 73, /* '9' */ + 43, /* ':' */ + 40, /* ';' */ + 87, /* '<' */ + 87, /* '=' */ + 87, /* '>' */ + 63, /* '?' */ + 117, /* '@' */ + 103, /* 'A' */ + 100, /* 'B' */ + 87, /* 'C' */ + 117, /* 'D' */ + 103, /* 'E' */ + 97, /* 'F' */ + 103, /* 'G' */ + 113, /* 'H' */ + 63, /* 'I' */ + 67, /* 'J' */ + 110, /* 'K' */ + 97, /* 'L' */ + 140, /* 'M' */ + 117, /* 'N' */ + 100, /* 'O' */ + 90, /* 'P' */ + 100, /* 'Q' */ + 100, /* 'R' */ + 77, /* 'S' */ + 83, /* 'T' */ + 123, /* 'U' */ + 107, /* 'V' */ + 147, /* 'W' */ + 93, /* 'X' */ + 93, /* 'Y' */ + 103, /* 'Z' */ + 40, /* '[' */ + 80, /* '\' */ + 53, /* ']' */ + 87, /* '^' */ + 83, /* '_' */ + 40, /* '`' */ + 70, /* 'a' */ + 70, /* 'b' */ + 57, /* 'c' */ + 73, /* 'd' */ + 57, /* 'e' */ + 53, /* 'f' */ + 67, /* 'g' */ + 73, /* 'h' */ + 40, /* 'i' */ + 37, /* 'j' */ + 73, /* 'k' */ + 40, /* 'l' */ + 103, /* 'm' */ + 77, /* 'n' */ + 67, /* 'o' */ + 73, /* 'p' */ + 67, /* 'q' */ + 50, /* 'r' */ + 53, /* 's' */ + 53, /* 't' */ + 77, /* 'u' */ + 73, /* 'v' */ + 113, /* 'w' */ + 70, /* 'x' */ + 67, /* 'y' */ + 73, /* 'z' */ + 40, /* '{' */ + 87, /* '|' */ + 40, /* '}' */ + 87, /* '~' */ + }, + /* height table for font ZI */ + { + 153, /* ' ' */ + 127, /* '!' */ + 126, /* '"' */ + 124, /* '#' */ + 164, /* '$' */ + 128, /* '%' */ + 123, /* '&' */ + 124, /* ''' */ + 167, /* '(' */ + 167, /* ')' */ + 141, /* '*' */ + 98, /* '+' */ + 73, /* ',' */ + 66, /* '-' */ + 51, /* '.' */ + 169, /* '/' */ + 124, /* '0' */ + 125, /* '1' */ + 125, /* '2' */ + 122, /* '3' */ + 129, /* '4' */ + 137, /* '5' */ + 128, /* '6' */ + 133, /* '7' */ + 124, /* '8' */ + 124, /* '9' */ + 97, /* ':' */ + 112, /* ';' */ + 103, /* '<' */ + 82, /* '=' */ + 103, /* '>' */ + 127, /* '?' */ + 131, /* '@' */ + 129, /* 'A' */ + 130, /* 'B' */ + 138, /* 'C' */ + 130, /* 'D' */ + 128, /* 'E' */ + 150, /* 'F' */ + 165, /* 'G' */ + 142, /* 'H' */ + 123, /* 'I' */ + 143, /* 'J' */ + 149, /* 'K' */ + 124, /* 'L' */ + 141, /* 'M' */ + 166, /* 'N' */ + 128, /* 'O' */ + 128, /* 'P' */ + 158, /* 'Q' */ + 155, /* 'R' */ + 138, /* 'S' */ + 136, /* 'T' */ + 126, /* 'U' */ + 144, /* 'V' */ + 143, /* 'W' */ + 128, /* 'X' */ + 154, /* 'Y' */ + 130, /* 'Z' */ + 166, /* '[' */ + 122, /* '\' */ + 166, /* ']' */ + 141, /* '^' */ + 34, /* '_' */ + 140, /* '`' */ + 98, /* 'a' */ + 143, /* 'b' */ + 98, /* 'c' */ + 142, /* 'd' */ + 98, /* 'e' */ + 182, /* 'f' */ + 134, /* 'g' */ + 143, /* 'h' */ + 133, /* 'i' */ + 173, /* 'j' */ + 165, /* 'k' */ + 142, /* 'l' */ + 97, /* 'm' */ + 98, /* 'n' */ + 98, /* 'o' */ + 137, /* 'p' */ + 150, /* 'q' */ + 97, /* 'r' */ + 98, /* 's' */ + 114, /* 't' */ + 99, /* 'u' */ + 103, /* 'v' */ + 104, /* 'w' */ + 121, /* 'x' */ + 137, /* 'y' */ + 101, /* 'z' */ + 165, /* '{' */ + 148, /* '|' */ + 165, /* '}' */ + 74, /* '~' */ + }, + /* ascent table for font ZI */ + { + 108, /* ' ' */ + 112, /* '!' */ + 112, /* '"' */ + 110, /* '#' */ + 126, /* '$' */ + 112, /* '%' */ + 107, /* '&' */ + 110, /* ''' */ + 125, /* '(' */ + 125, /* ')' */ + 127, /* '*' */ + 85, /* '+' */ + 43, /* ',' */ + 52, /* '-' */ + 35, /* '.' */ + 127, /* '/' */ + 108, /* '0' */ + 111, /* '1' */ + 108, /* '2' */ + 108, /* '3' */ + 111, /* '4' */ + 121, /* '5' */ + 112, /* '6' */ + 116, /* '7' */ + 108, /* '8' */ + 108, /* '9' */ + 82, /* ':' */ + 82, /* ';' */ + 89, /* '<' */ + 68, /* '=' */ + 89, /* '>' */ + 112, /* '?' */ + 112, /* '@' */ + 113, /* 'A' */ + 117, /* 'B' */ + 112, /* 'C' */ + 116, /* 'D' */ + 112, /* 'E' */ + 117, /* 'F' */ + 112, /* 'G' */ + 126, /* 'H' */ + 109, /* 'I' */ + 109, /* 'J' */ + 109, /* 'K' */ + 110, /* 'L' */ + 125, /* 'M' */ + 126, /* 'N' */ + 112, /* 'O' */ + 114, /* 'P' */ + 112, /* 'Q' */ + 116, /* 'R' */ + 112, /* 'S' */ + 122, /* 'T' */ + 110, /* 'U' */ + 128, /* 'V' */ + 127, /* 'W' */ + 112, /* 'X' */ + 115, /* 'Y' */ + 113, /* 'Z' */ + 125, /* '[' */ + 108, /* '\' */ + 125, /* ']' */ + 127, /* '^' */ + -2, /* '_' */ + 127, /* '`' */ + 82, /* 'a' */ + 126, /* 'b' */ + 82, /* 'c' */ + 126, /* 'd' */ + 82, /* 'e' */ + 126, /* 'f' */ + 82, /* 'g' */ + 127, /* 'h' */ + 117, /* 'i' */ + 117, /* 'j' */ + 126, /* 'k' */ + 126, /* 'l' */ + 82, /* 'm' */ + 82, /* 'n' */ + 82, /* 'o' */ + 82, /* 'p' */ + 94, /* 'q' */ + 82, /* 'r' */ + 82, /* 's' */ + 98, /* 't' */ + 83, /* 'u' */ + 87, /* 'v' */ + 88, /* 'w' */ + 82, /* 'x' */ + 83, /* 'y' */ + 85, /* 'z' */ + 124, /* '{' */ + 134, /* '|' */ + 124, /* '}' */ + 60, /* '~' */ + }, + + "ZapfChancery-MediumItalic", + 0, + YES + }, { +{ + 272, /* gclef */ + 279, /* fclef */ + 237, /* cclef */ + 147, /* dblwhole */ + 145, /* 1n */ + 118, /* 2n */ + 112, /* 4n */ + 84, /* upflag */ + 84, /* dnflag */ + 70, /* qwhrest */ + 70, /* dwhrest */ + 237, /* 1rest */ + 237, /* 2rest */ + 113, /* 4rest */ + 127, /* 8rest */ + 138, /* 16rest */ + 154, /* 32rest */ + 168, /* 64rest */ + 181, /* 128rest */ + 197, /* 256rest */ + 140, /* ll1rest */ + 140, /* ll2rest */ + 62, /* dot */ + 95, /* nat */ + 120, /* sharp */ + 104, /* flat */ + 123, /* dblsharp */ + 186, /* dblflat */ + 118, /* xnote */ + 155, /* dwhdiamond */ + 118, /* diamond */ + 118, /* filldiamond */ + 145, /* up2n */ + 145, /* dn2n */ + 141, /* up4n */ + 140, /* dn4n */ + 176, /* com */ + 176, /* cut */ + 61, /* begped */ + 140, /* pedal */ + 62, /* endped */ + 136, /* dnbow */ + 123, /* upbow */ + 70, /* wedge */ + 70, /* uwedge */ + 251, /* ferm */ + 251, /* uferm */ + 209, /* sign */ + 251, /* coda */ + 206, /* mor */ + 206, /* invmor */ + 204, /* turn */ + 204, /* invturn */ + 186, /* acc_gt */ + 131, /* acc_hat */ + 131, /* acc_uhat */ + 223, /* tr */ + 140, /* leg */ + 154, /* rr */ + 98, /* dim */ + 129, /* halfdim */ + 134, /* triangle */ + 204, /* measrpt */ + 151, /* copyright */ + 216, /* up8n */ + 140, /* dn8n */ + 216, /* up16n */ + 140, /* dn16n */ + 216, /* up32n */ + 140, /* dn32n */ + 216, /* up64n */ + 140, /* dn64n */ + 216, /* up128n */ + 140, /* dn128n */ + 216, /* up256n */ + 140, /* dn256n */ +}, { + 666, /* gclef */ + 352, /* fclef */ + 372, /* cclef */ + 166, /* dblwhole */ + 91, /* 1n */ + 94, /* 2n */ + 91, /* 4n */ + 236, /* upflag */ + 236, /* dnflag */ + 194, /* qwhrest */ + 111, /* dwhrest */ + 115, /* 1rest */ + 75, /* 2rest */ + 284, /* 4rest */ + 177, /* 8rest */ + 261, /* 16rest */ + 344, /* 32rest */ + 386, /* 64rest */ + 469, /* 128rest */ + 552, /* 256rest */ + 112, /* ll1rest */ + 70, /* ll2rest */ + 61, /* dot */ + 263, /* nat */ + 286, /* sharp */ + 236, /* flat */ + 122, /* dblsharp */ + 236, /* dblflat */ + 100, /* xnote */ + 194, /* dwhdiamond */ + 83, /* diamond */ + 83, /* filldiamond */ + 366, /* up2n */ + 366, /* dn2n */ + 365, /* up4n */ + 365, /* dn4n */ + 204, /* com */ + 277, /* cut */ + 116, /* begped */ + 97, /* pedal */ + 116, /* endped */ + 152, /* dnbow */ + 169, /* upbow */ + 95, /* wedge */ + 95, /* uwedge */ + 166, /* ferm */ + 166, /* uferm */ + 255, /* sign */ + 263, /* coda */ + 105, /* mor */ + 152, /* invmor */ + 118, /* turn */ + 119, /* invturn */ + 119, /* acc_gt */ + 147, /* acc_hat */ + 147, /* acc_uhat */ + 166, /* tr */ + 41, /* leg */ + 172, /* rr */ + 151, /* dim */ + 166, /* halfdim */ + 140, /* triangle */ + 213, /* measrpt */ + 150, /* copyright */ + 365, /* up8n */ + 365, /* dn8n */ + 365, /* up16n */ + 365, /* dn16n */ + 431, /* up32n */ + 431, /* dn32n */ + 498, /* up64n */ + 498, /* dn64n */ + 565, /* up128n */ + 565, /* dn128n */ + 623, /* up256n */ + 623, /* dn256n */ +}, { + 430, /* gclef */ + 102, /* fclef */ + 186, /* cclef */ + 83, /* dblwhole */ + 45, /* 1n */ + 47, /* 2n */ + 45, /* 4n */ + 236, /* upflag */ + 0, /* dnflag */ + 97, /* qwhrest */ + 97, /* dwhrest */ + 101, /* 1rest */ + 55, /* 2rest */ + 148, /* 4rest */ + 79, /* 8rest */ + 79, /* 16rest */ + 162, /* 32rest */ + 162, /* 64rest */ + 245, /* 128rest */ + 245, /* 256rest */ + 98, /* ll1rest */ + 55, /* ll2rest */ + 30, /* dot */ + 131, /* nat */ + 143, /* sharp */ + 166, /* flat */ + 61, /* dblsharp */ + 166, /* dblflat */ + 50, /* xnote */ + 97, /* dwhdiamond */ + 41, /* diamond */ + 41, /* filldiamond */ + 305, /* up2n */ + 61, /* dn2n */ + 305, /* up4n */ + 59, /* dn4n */ + 102, /* com */ + 138, /* cut */ + 97, /* begped */ + 91, /* pedal */ + 97, /* endped */ + 138, /* dnbow */ + 140, /* upbow */ + 83, /* wedge */ + 81, /* uwedge */ + 152, /* ferm */ + 152, /* uferm */ + 127, /* sign */ + 131, /* coda */ + 52, /* mor */ + 76, /* invmor */ + 59, /* turn */ + 59, /* invturn */ + 59, /* acc_gt */ + 133, /* acc_hat */ + 133, /* acc_uhat */ + 152, /* tr */ + 20, /* leg */ + 155, /* rr */ + 137, /* dim */ + 152, /* halfdim */ + 120, /* triangle */ + 106, /* measrpt */ + 130, /* copyright */ + 305, /* up8n */ + 59, /* dn8n */ + 305, /* up16n */ + 59, /* dn16n */ + 372, /* up32n */ + 59, /* dn32n */ + 438, /* up64n */ + 59, /* dn64n */ + 505, /* up128n */ + 59, /* dn128n */ + 563, /* up256n */ + 59, /* dn256n */ +}, + "mfont0", + 0, + NO + }, { +{ + 127, /* dwhrighttriangle */ + 118, /* righttriangle */ + 118, /* fillrighttriangle */ + 127, /* udwhrighttriangle */ + 118, /* urighttriangle */ + 118, /* ufillrighttriangle */ + 127, /* dwhrectangle */ + 118, /* rectangle */ + 118, /* fillrectangle */ + 127, /* dwhisostriangle */ + 118, /* isostriangle */ + 118, /* fillisostriangle */ + 127, /* dwhpiewedge */ + 118, /* piewedge */ + 118, /* fillpiewedge */ + 127, /* dwhsemicircle */ + 118, /* semicircle */ + 118, /* fillsemicircle */ + 191, /* dwhslashhead */ + 187, /* slashhead */ + 176, /* fillslashhead */ + 118, /* blankhead */ +}, { + 166, /* dwhrighttriangle */ + 79, /* righttriangle */ + 79, /* fillrighttriangle */ + 166, /* udwhrighttriangle */ + 79, /* urighttriangle */ + 79, /* ufillrighttriangle */ + 166, /* dwhrectangle */ + 75, /* rectangle */ + 75, /* fillrectangle */ + 166, /* dwhisostriangle */ + 79, /* isostriangle */ + 79, /* fillisostriangle */ + 166, /* dwhpiewedge */ + 79, /* piewedge */ + 79, /* fillpiewedge */ + 166, /* dwhsemicircle */ + 79, /* semicircle */ + 79, /* fillsemicircle */ + 200, /* dwhslashhead */ + 200, /* slashhead */ + 186, /* fillslashhead */ + 75, /* blankhead */ +}, { + 83, /* dwhrighttriangle */ + 37, /* righttriangle */ + 37, /* fillrighttriangle */ + 83, /* udwhrighttriangle */ + 41, /* urighttriangle */ + 41, /* ufillrighttriangle */ + 83, /* dwhrectangle */ + 37, /* rectangle */ + 37, /* fillrectangle */ + 83, /* dwhisostriangle */ + 41, /* isostriangle */ + 41, /* fillisostriangle */ + 83, /* dwhpiewedge */ + 37, /* piewedge */ + 37, /* fillpiewedge */ + 83, /* dwhsemicircle */ + 37, /* semicircle */ + 37, /* fillsemicircle */ + 100, /* dwhslashhead */ + 100, /* slashhead */ + 93, /* fillslashhead */ + 37, /* blankhead */ +}, + "mfont1", + 0, + NO +}}; + +/* 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 +}; + +/* table of maximum ascents for each font in inches */ + +float Maxfontascent[MAXFONTS] = { + (double) 135 / (double) FONTFACTOR, + (double) 136 / (double) FONTFACTOR, + (double) 139 / (double) FONTFACTOR, + (double) 136 / (double) FONTFACTOR, + (double) 148 / (double) FONTFACTOR, + (double) 148 / (double) FONTFACTOR, + (double) 155 / (double) FONTFACTOR, + (double) 155 / (double) FONTFACTOR, + (double) 125 / (double) FONTFACTOR, + (double) 125 / (double) FONTFACTOR, + (double) 130 / (double) FONTFACTOR, + (double) 130 / (double) FONTFACTOR, + (double) 142 / (double) FONTFACTOR, + (double) 142 / (double) FONTFACTOR, + (double) 141 / (double) FONTFACTOR, + (double) 141 / (double) FONTFACTOR, + (double) 146 / (double) FONTFACTOR, + (double) 141 / (double) FONTFACTOR, + (double) 148 / (double) FONTFACTOR, + (double) 145 / (double) FONTFACTOR, + (double) 147 / (double) FONTFACTOR, + (double) 146 / (double) FONTFACTOR, + (double) 147 / (double) FONTFACTOR, + (double) 146 / (double) FONTFACTOR, + (double) 136 / (double) FONTFACTOR, + (double) 136 / (double) FONTFACTOR, + (double) 135 / (double) FONTFACTOR, + (double) 137 / (double) FONTFACTOR, +#ifdef EXTCHAR + (double) 186 / (double) FONTFACTOR, + (double) 186 / (double) FONTFACTOR, + (double) 189 / (double) FONTFACTOR, + (double) 189 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 179 / (double) FONTFACTOR, + (double) 179 / (double) FONTFACTOR, + (double) 179 / (double) FONTFACTOR, + (double) 179 / (double) FONTFACTOR, + (double) 196 / (double) FONTFACTOR, + (double) 196 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 193 / (double) FONTFACTOR, + (double) 193 / (double) FONTFACTOR, + (double) 196 / (double) FONTFACTOR, + (double) 196 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 199 / (double) FONTFACTOR, + (double) 186 / (double) FONTFACTOR, + (double) 186 / (double) FONTFACTOR, + (double) 186 / (double) FONTFACTOR, + (double) 188 / (double) FONTFACTOR, +#endif + (double) 134 / (double) FONTFACTOR, + (double) 134 / (double) FONTFACTOR, + 0.8 * ((double) DFLT_SIZE / (double) PPI) +}; diff --git a/mup/mup/globals.c b/mup/mup/globals.c new file mode 100644 index 0000000..27914c8 --- /dev/null +++ b/mup/mup/globals.c @@ -0,0 +1,266 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2006 + * by Arkkra Enterprises */ +/* All rights reserved */ +/* + * globals.c + * + * This files defines all the global variables used in more than one + * file, except for ones that are used only by yacc and lex. + */ + +#include "structs.h" +#include "rational.h" +#include "globals.h" + +/* + * Define the fixed SSV structures, which accumulate attributes of the + * score, staffs, and voices. + */ +struct SSV Score; +struct SSV Staff[MAXSTAFFS]; +struct SSV Voice[MAXSTAFFS][MAXVOICES]; + +/* + * Define command line requested staff and voice visibilities. Each value is + * YES or NO. + */ +short Staff_vis[MAXSTAFFS + 1]; +short Voice_vis[MAXSTAFFS + 1][MAXVOICES + 1]; + +/* + * Define head and tail cells of the main linked list set up by the parser. + */ +struct MAINLL *Mainllhc_p; +struct MAINLL *Mainlltc_p; + +int Optch = OPTION_MARKER; /* character for command line options */ +int Mupmate = NO; /* was Mup called from Mupmate? */ +int Errorcount; /* number of errors found so far */ +int Maxverses; /* maximum number of verse numbers used in the song */ +short Meas_num = 1; /* count measure numbers */ +int Preproc = NO; /* was -E specified on command line? */ +int Ppcomments = NO; /* was -C specified on command line? */ + +int Context = C_MUSIC; +int Curr_family = BASE_TIMES; +int Curr_font = FONT_TR; +int Curr_size = DFLT_SIZE; +int Got_some_data = NO; +int Doing_tab_staff; /* YES while parsing a line for a tab staff, else NO */ +int Doing_MIDI = NO; +char *Curr_filename; +char *Outfilename = ""; +int Vflag = NO; +int Vcombused = NO; /* was the voicecombine parameter ever used? */ +int CSBused = NO; /* was cross staff beaming used in this song? */ +int CSSused = NO; /* was cross staff stemming used in this song? */ +int CSSpass = NO; /* YES while doing a special pass for cross staff stem*/ + +/* + * Due to read ahead, we may already be on the following line when generating + * an error message, so need to know when to compensate by subtracting + * 1 from the current line number. + */ +int Last_was_newline = NO; + +/* + * The following table lets you conveniently find the character name of any + * note head type of form GF_NORMAL. It is to be indexed like this: + * headchar = Hctab [ basictime > 2 ? 3 : basictime ]; + */ +unsigned char Hctab [] = { + C_DBLWHOLE, C_1N, C_2N, C_4N +}; + +/* + * This table is like Hctab, but for X notes. Note that for half notes and + * longer, we actually draw the note as a diamond instead of an X. + */ +unsigned char Xhctab[] = { + C_DWHDIAMOND, C_DIAMOND, C_DIAMOND, C_XNOTE +}; + +/* + * This table is like Hctab, but for diamond shaped notes. + */ +unsigned char Dhctab[] = { + C_DWHDIAMOND, C_DIAMOND, C_DIAMOND, C_FILLDIAMOND +}; + +/* + * The following table lets you conveniently find the character name of any + * rest type, whole or shorter. It is to be indexed by log2(basictime). + */ +unsigned char Resttab[] = { + C_LL1REST, C_LL2REST, C_4REST, C_8REST, C_16REST, C_32REST, C_64REST, + C_128REST, C_256REST, +}; + +/* + * The following table tells how many letters up from C each note is. It is + * to be indexed by (noteletter - 'a'). + */ +int Letshift[] = { 5, 6, 0, 1, 2, 3, 4, }; + /* a b c d e f g */ + +/* the note letters in the order of the circle of fifths */ +char Circle[] = "fcgdaeb"; + +/* internal accidental letters */ +char Acclets[] = "B&n#x"; + +/* external accidental symbols */ +char *Acctostr[] = { "&&", "&", "", "#", "x" }; + +/* + * Define strings for pedstyle = pedstar ("Ped." and the star). + */ +char Ped_start[] = { FONT_ZI, 18, 'P', 'e', 'd', '.', '\0' }; +char Ped_stop[] = { FONT_ZD, 14, 'j', '\0' }; + +/* + * Define the string info for standard guitar tuning. Note that the octaves + * are for how it should be printed; the actual sound is an octave lower. + * When outputting MIDI, we check whether the tablature staff is using this + * default array, and if so, automatically transpose down by 12 halfsteps. + */ +struct STRINGINFO Guitar[DEFTABLINES] = { + { 'e', '\0', 0, 5 }, + { 'b', '\0', 0, 4 }, + { 'g', '\0', 0, 4 }, + { 'd', '\0', 0, 4 }, + { 'a', '\0', 0, 3 }, + { 'e', '\0', 1, 3 }, +}; + +/* + * These arrays are used to keep track of things while adjusting the pitches + * of notes to account for octave marks. They are indexed by staff number, + * so element 0 of each array is unused. Octave mark related transposition + * is done both in MIDI code and trantab code. + */ +int Octave_adjust[MAXSTAFFS+1]; /* how many octaves to adjust due to + * user-specified octave marks */ +int Octave_bars[MAXSTAFFS+1]; /* how many bar lines to cross with + * current Octave_adjust (if Octave_adjust is + * zero, this variable is meaningless) */ +float Octave_count[MAXSTAFFS+1];/* number of counts into measure that + * Octave_adjust applies in measure after + * Octave_bars have gone by. (if Octave_adjust + * is zero, this variable is meaningless */ +/* + * Define fixed location variables. For all of these, only the absolute + * coordinates are used. + */ +float _Page [NUMCTYPE]; /* whole page */ +float _Win [NUMCTYPE]; /* middle (music) window */ +float _Cur [NUMCTYPE]; /* current position */ + +/* + * Define the structures for headers and footers. + */ +struct BLOCKHEAD Header; /* first page header */ +struct BLOCKHEAD Footer; /* first page footer */ +struct BLOCKHEAD Header2; /* later page header */ +struct BLOCKHEAD Footer2; /* later page footer */ + +/* + * used by print phase to keep track of current staff locations + */ +float *Score_location_p; /* score coord from FEED struct */ +float Staffs_y[MAXSTAFFS + 1]; /* absolute Y of the staffs of a score */ + +/* + * While constructing a GRPSYL list of groups or lyrics, or a list of STUFF, + * any of which could be being defining for multiple staffs at once and/or more + * than one vno, keep a pointer to the list of staffs and vnos being defined. + * Once we gather an entire line of input, the GRPSYL list or STUFF list is + * cloned for each staff being defined, and the information is moved to be + * associated with the appropriate STAFF structs. + */ +struct RANGELIST *Staffrange_p; +struct RANGELIST *Vnorange_p; + +/* + * During parse phase, this keeps track of the place (PL_ABOVE, PL_BELOW, + * or PL_BETWEEN) of the current thing being collected (groups, lyrics, + * or stuff). + */ +short Place; + +/* + * Snapshot of the state of pedals at the beginning of endings. + * The zeroth element of the array is used as a flag. If it is YES, + * the rest of the array contains the pedal state for each staff, + * YES for pedal on, NO for off. If the zeroth element is NO, + * the rest of the array is meaningless. + */ +short Ped_snapshot[MAXSTAFFS + 1]; + +/* table to give a quick mapping from staff number to STAFF struct */ +struct MAINLL *Staffmap_p[MAXSTAFFS + 1]; + +/* pointer to beginning of all the STAFF structs in current measure */ +struct MAINLL *List_of_staffs_p; + +struct SVRANGELIST *Svrangelist_p; + +/* beginning of the list of GRPSYL structs currently being built */ +struct GRPSYL *Curr_gs_list_p; + +/* If 0, no multirest in current measure yet. + * If 1, got a multirest. + * If 2, got both a multirest and music data */ +short Got_multirest; + +/* YES if input contained at least one group in the current measure */ +short Got_group; + +short Pagenum; /* which page we are currently printing */ +int Last_pagenum; /* page number of the final page */ + +/* set to YES if given font is used somewhere */ +short Font_used[MAXFONTS]; + +/* items used when chord grids are to be printed at the end of the song */ +struct ATEND_INFO Atend_info; + +/* + * Define a variable for a staff's staffscale, and other variables which are + * staffscale times the corresponding macro symbol in all caps. This is to + * avoid recalculating these all the time. These variables are for use in + * files where a main function loops over staffs, and calls a tree of + * subroutines for each staff. The main function should set these variables + * for the current staff, and from there on the code can use them. Early in + * Mup they are initialized to their default values by doing initstructs() + * and set_staffscale(0), so that everywhere before the point where staff + * scaling begins (in restsyl.c) they are set to these default values, and + * code before there can call utilities that use these symbols and no scaling + * will result. + */ +float Staffscale; /* for this staff */ +float Stdpad; /* STDPAD on this staff */ +float Stepsize; /* STEPSIZE on this staff */ +float Flagsep; /* FLAGSEP on this staff */ +float Smflagsep; /* SMFLAGSEP on this staff */ +float Tupheight; /* TUPHEIGHT on this staff */ + +/* define rational number constants that may be useful in multiple files */ +RATIONAL Zero = {0,1}; +RATIONAL One_fourth = {1,4}; +RATIONAL One_third = {1,3}; +RATIONAL One_half = {1,2}; +RATIONAL Two_thirds = {2,3}; +RATIONAL Three_fourths = {3,4}; +RATIONAL One = {1,1}; +RATIONAL Two = {2,1}; +RATIONAL Three = {3,1}; +RATIONAL Four = {4,1}; + +/* + * Define something longer than the longest possible measure. See the comment + * by the #define for MAXTSLEN. + */ +RATIONAL Maxtime = {(MAXTSLEN - 3) * 99 + 1, 1}; + +int Debuglevel; /* bitmap of what message classes to print */ diff --git a/mup/mup/globals.h b/mup/mup/globals.h new file mode 100644 index 0000000..f652098 --- /dev/null +++ b/mup/mup/globals.h @@ -0,0 +1,813 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * globals.h + * + * This file has externs for the global variables defined in global.c. + * It also has externs for all nonstatic functions. + */ + +#ifndef _GLOBALS +#define _GLOBALS + +#ifdef __WATCOMC__ +#include +#endif +#include +#include +#include "structs.h" +#ifdef VMS +#include +#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 +#include +#else +/* UNIX utilities that don't appear in official header files in SV_R3 */ +extern char *malloc(); +extern char *calloc(); +extern char *realloc(); +extern void free(); + +extern void exit(); +extern int abs(); +extern int atoi(); +extern double atof(); +extern void qsort(); +extern long strtol(); +#endif + +/* abshorz.c */ +extern void abshorz P((void)); + +/* absvert.c */ +extern void absvert P((void)); + +/* assign.c */ +extern void assign_int P((int var, int value, struct MAINLL *mainll_item_p)); +extern void assign_float P((int var, double value, + struct MAINLL *mainll_item_p)); +extern void assign_vscheme P((int numvoices, int vtype, + struct MAINLL *mainll_item_p)); +extern void assign_key P((int num, int acc, int minor, + struct MAINLL *mainll_item_p)); +extern void assign_string P((int var, char *string, + struct MAINLL *mainll_item_p)); +extern void assign_unit P((int unittype, struct MAINLL *mainll_p)); +extern char *copy_string P((char *string, int font, int size)); +extern void assign_timesig P(( struct MAINLL *mainll_item_p, int invisible, + char **next_alternation_p)); +extern void assign_font P((int var, int value, struct MAINLL *mainll_item_p)); +extern void new_staffset P((void)); +extern void add_staffset P((int start, int end, char *label1, char *label2)); +extern void set_staffset P((int var, struct MAINLL *mainll_item_p)); +extern void new_barstlist P((void)); +extern void add_barst P((int start, int end)); +extern void set_barstlist P((struct MAINLL *mainll_item_p)); +extern void new_beamlist P((void)); +extern void add_beamlist P((RATIONAL value)); +extern void set_beamlist P((struct MAINLL *mainll_item_p)); +extern void asgn_stafflines P((int numlines, int printclef, + struct MAINLL *mainll_item_p)); +extern void set_font P((int var, int value, struct MAINLL *mll_p)); +extern void add_tab_string_info P((int pitch, int accidental, int nticks, + int octave, struct SSV *ssv_p)); +extern void set_mnum P((struct BAR *bar_p, int mnum)); +extern void assign_2floats P((int var, double value1, double value2, + struct MAINLL *mainll_item_p)); +extern void chkmargin P((double topmargin, double botmargin, double leftmargin, + double rightmargin)); +extern double adjust2inches P((double value)); +extern void begin_subbeam P((void)); +extern void end_subbeam P((void)); +extern void assign_vcombine P((int qualifier, struct MAINLL * mainll_p)); + +/* beaming.c */ +extern void setbeamloc P((struct GRPSYL *curr_grp_p, + struct GRPSYL *last_grp_p)); +extern int has_cust_beaming P((struct GRPSYL *grpsyl_p)); +extern void do_beaming P((struct GRPSYL *grpsyl_p, int grpsize, int staffno, + int vno)); +extern void set_alt_beams P((struct GRPSYL *grpsyl_p)); +extern int chk_crossbeam P((struct GRPSYL *gs_p, struct MAINLL *mll_p)); + +/* beamstem.c */ +extern void beamstem P((void)); + +/* brac.c */ +extern int brac_check P((struct STAFFSET *bracelist_p, int nbrace, + struct STAFFSET *bracklist_p, int nbrack)); +extern int pr_brac P((int is_restart, double x_offset, struct MAINLL *mll_p)); +extern double width_left_of_score P((struct MAINLL *mll_p)); +extern double pwidth_left_of_score P((struct MAINLL *mll_p, + struct MAINLL *prev_feed_mll_p)); + +/* charinfo.c */ +extern double height P((int font, int size, int ch)); +extern double width P((int font, int size, int ch)); +extern double ascent P((int font, int size, int ch)); +extern double descent P((int font, int size, int ch)); +extern char *fix_string P((char *string, int font, int size, char *fname, + int lineno)); +extern char *mc_num2name P((int code, int font)); +extern unsigned char mc_name2num P((char *name, char *fname, int lineno, + int *size_p, int *font_p)); +extern int str2mfont P((int str)); +extern int mfont2str P((int mfont)); +#ifdef EXTCHAR +extern char *ext_num2name P((int code)); +#endif +extern int is_music_symbol P((char *str)); +extern double strascent P((char *str)); +extern double strdescent P((char *str)); +extern double strheight P((char *str)); +extern double strwidth P((char *str)); +extern char *tranchstr P((char *chordstring, int staffno)); +extern int restchar P((int basictime)); +extern char *dashstr P((char *str)); +extern void end_fontsize P((char *str, int *font_p, int *size_p)); +extern char *ascii_str P((char *str, int verbose, int pagenum, int textmod)); +extern char *split_string P((char *string, double desired_width)); +extern int adj_size P((int size, double factor, char *filename, int lineno)); +extern char *resize_string P((char *string, double factor, char *filename, + int lineno)); +extern double left_width P((char *)); +extern char *acc_trans P((char *string)); +extern char *modify_chstr P((char *string, int modifier)); +extern int is_ital_font P((int font)); +extern double circled_dimensions P((char *str, float* height_p, float *width_p, + float *ascent_adjust, float *x_offset_p)); +extern char *get_reh_string P((char *string, int staffnum)); + +/* check.c */ +extern int rangecheck P((int n, int min, int max, char *name)); +extern int frangecheck P((double n, double min, double max, char *name)); +extern int power_of2check P((int n, char *name)); +extern int contextcheck P((int validcontext, char *action)); +extern char *contextname P((int cont)); +extern void check_at_least1visible P((void)); +extern void chk_vis_feed P((void)); +extern void chk_interval P((int inttype, int intnum)); +extern void used_check P((struct MAINLL *mll_p, int var, char *name)); +extern int l_rangecheck P((int num, int min, int max, char *name, char *fname, + int lineno)); +extern void combine_rests P((int c)); +extern char *markname P((int mark)); +extern void chk_order P((struct SSV *ssv_p, int place)); +extern int erangecheck P((int n, int min, int max, int empty_value, + char *name)); +extern void chk_x_arg P((char *x_arg, int *start_p, int *end_p)); +extern void extract P((int start, int end)); + +/* debug.c */ +extern char *stype_name P((int stype)); +extern void print_mainll P((void)); + +/* errors.c */ +extern void ufatal P((char *format, ...)); +extern void pfatal P((char *format, ...)); +extern void l_ufatal P((char *filename, int lineno, char *format, ...)); +extern void l_pfatal P((char *filename, int lineno, char *format, ...)); +extern void l_no_mem P((char *filename, int lineno)); +extern void cant_open P((char *filename)); +extern void warning P((char *format, ...)); +extern void l_yyerror P((char *fname, int lineno, char *format, ...)); +extern void l_warning P((char *filename, int lineno, char *format, ...)); +extern void debug P((int level, char *format, ...)); +extern int debug_on P((int level)); +extern void doraterr P((int code)); +extern void error_exit P((void)); +extern void print_offending_line P((char *filename, int lineno)); + +/* font.c */ +extern double fontascent P((int font, int size)); +extern double fontdescent P((int font, int size)); +extern double fontheight P((int font, int size)); +extern void parse_font_file P((char *filename)); +extern int lookup_font P((char *fontname)); +extern int font_index P((int font)); +extern char *fontnum2name P((int font)); + +/* fontdata.c */ +extern struct FONTINFO Fontinfo[MAXFONTS]; +extern float Maxfontheight[MAXFONTS]; +extern float Maxfontascent[MAXFONTS]; + +/* gram.y */ +extern int yyparse P((void)); +extern int yyerror P((char *msg)); + +/* grpsyl.c */ +extern struct GRPSYL *newGRPSYL P((int grp_or_syl)); +extern void copy_attributes P((struct GRPSYL *newgrp_p, + struct GRPSYL *oldgrp_p)); +extern struct TIMELIST *copy_timeunit P((struct GRPSYL *newgrp_p, + struct GRPSYL *oldgrp_p, struct TIMELIST *timelist_p)); +extern void copy_notes P((struct GRPSYL *newgrp_p, struct GRPSYL *oldgrp_p)); +extern void link_notegroup P((struct GRPSYL *newgrp_p, + struct GRPSYL *last_grp_p)); +extern void add_note P((struct GRPSYL *grpsyl_p, int pitch, int accidental, + int octave, int nticks, int has_paren, char *bend_string)); +#ifdef __STDC__ +extern int notecomp P((const void *item1_p, const void *item2_p)); +#else +extern int notecomp P((char *item1_p, char *item2_p)); +#endif +extern int reconstruct_basictime P((RATIONAL fulltime)); +extern int recalc_dots P((RATIONAL fulltime, int basictime)); +extern void clone_withlist P((struct GRPSYL *newgrp_p, + struct GRPSYL *oldgrp_p)); +extern char *stringname P((int stringno, int staffno)); +extern char *format_string_name P((int letter, int accidental, + int nticks)); +extern void do_bar P((int bartype)); +extern void begin_tuplet P((void)); +extern void end_tuplet P((int tupcont, RATIONAL tuptime, int printtup, + int tupside)); +extern void check4barline_at_end P((void)); +extern void add_multirest P((int nummeas)); +extern struct GRPSYL *clone_gs_list P((struct GRPSYL *list_p, + int copy_noteinfo)); +extern void add_slurto P((struct GRPSYL *grpsyl_p, int pitch, int octave, + int note_index, int slurstyle)); +extern void free_grpsyls P((struct GRPSYL *gs_p)); +extern void resize_notelist P((struct GRPSYL *gs_p)); +extern void add_meas_space P((struct GRPSYL **gs_p_p, int staff, int voice)); +extern int is_mrpt P((struct GRPSYL *gs_p)); +extern void report_mix_error P((void)); +extern void free_notelist P((struct GRPSYL *gs_p)); +extern void begin_slur P((struct GRPSYL *grpsyl_p, int note_index)); +extern void set_slurdir P((struct GRPSYL *grpsyl_p, int note_index, int dir)); +extern int has_pickup P((void)); +extern struct GRPSYL *expandgrp P((struct GRPSYL *grpsyl_p, + struct TIMELIST *timelist_p)); +extern RATIONAL calcfulltime P((RATIONAL basictime, int dots)); + +/* lex.l */ +extern void chk_ifdefs P((void)); +extern int save_macro P((FILE *file)); +extern int yylex P((void)); +extern void get_parameters P((char *macname)); +extern int get_mac_arguments P((char *macname, int num_args)); +extern void pushback P((int c)); +extern void begin_raw P(()); +extern void end_raw P(()); +extern void new_lexbuff P((FILE *file)); +extern void del_lexbuff P((void)); + +/* locvar.c */ +extern void fix_locvars P((void)); + +/* lyrics.c */ +extern void lyr_verse P((int begin, int end)); +extern void proc_lyrics P((struct GRPSYL *grpsyl_p, char *lyrstring)); +extern void attach_lyrics2staffs P((struct MAINLL *mll_staffs_p)); +extern void sylwidth P((char *lyrstring, float *wid_b4_syl_p, + float *wid_real_syl_p, float *wid_after_syl_p)); +extern void set_maxverses P((void)); +extern struct SSV *get_lyr_dflt_timeunit_ssv P((void)); +extern void setlyrfont P((int staffno, int font)); +extern void setlyrsize P((int staffno, int size)); +extern void lyr_compensate P((struct GRPSYL *gs_p)); +extern struct GRPSYL *derive_lyrtime P((void)); +extern void lyr_new_bar P((void)); + +/* macros.c */ +extern int not_in_mac P((int inc_dec)); +extern void mac_error P((void)); +extern void includefile P((char *fname)); +extern int popfile P((void)); +extern void cmdline_macro P((char *macdef)); +extern void define_macro P((char *macname)); +extern void undef_macro P((char *macname)); +extern void call_macro P((char *macname)); +extern int is_defined P((char *macname, int paramtoo)); +#ifndef unix +extern void mac_cleanup P((void)); +#endif +extern void add_parameter P((char *macname, char *param_name)); +extern void set_parm_value P((char *macname, char *argbuff, int argnum)); +extern char *add2argbuff P((char *argbuff, int c)); +extern FILE *find_file P((char **filename_p)); +extern void preproc P((void)); + +/* main.c */ +extern int onpagelist P((int pagenum)); +extern int yywrap P((void)); +extern int last_page P((void)); + +/* mainlist.c */ +extern struct MAINLL *newMAINLLstruct P((int structtype, int lineno)); +extern void insertMAINLL P((struct MAINLL *info_p, struct MAINLL *where)); +extern void unlinkMAINLL P((struct MAINLL *which_p)); + +/* map.c */ +extern void begin_map P((void)); +extern void end_map P((void)); +extern void map_item P((void)); +extern void save_map P((void)); +extern struct SSV *get_dflt_timeunit_ssv P((void)); +extern void reset_input_style P((void)); +extern int input_style P((int staff, int voice)); +extern void merge_dup_notes P((struct GRPSYL *gs_p, int n)); +extern void link_groups P((void)); +extern int is_tab_range P((void)); +extern int timelists_equal P((struct TIMELIST *tlist1_p, + struct TIMELIST *tlist2_p)); + +/* mkchords.c */ +extern void makechords P((void)); + +/* midi.c */ +extern void gen_midi P((char *midifilename)); +extern UINT32B write_delta P((int mfile)); +extern int voice_used P((int staffno, int vno)); + +/* midiutil.c */ +extern void fix_track_size P((int mfile, long track_start, long track_size)); +extern int parse_octave P((char *string, int place, char *fname, int lineno)); +extern int clocks P((int num)); +extern int getkeyword P((char *string, char **key_p, int *leng_p, + char **arg_p_p)); +extern int matches P((char *key, int leng, char *cmd)); +extern int hexdig P((int ch)); +extern UINT32B midi_wrstring P((int mfile, char *str, int internalform)); +extern UINT32B wr_varlength P((int mfile, UINT32B num)); +extern UINT32B midi_keysig P((int mfile, int sharps, int is_minor)); +extern UINT32B midi_timesig P((int mfile)); +extern void add_rest P((struct GRPSYL *gs_p, RATIONAL fulltime)); +extern struct GRPSYL *grp_before P((struct GRPSYL *gs_p, struct MAINLL *mll_p, + int staffno, int v)); +extern void midi_squeeze P((void)); +extern void guitar_transpose P((void)); +extern void other_voice_accidentals P((struct STAFF *staff_p)); +extern void mv_midi_items P((struct MAINLL *mll_p, + struct MAINLL *topstaff_mll_p)); +extern int get_param P((char *arg, char *inputfile, int inputlineno, + int *parmnum_p, int *parmval_p)); + +/* nxtstrch.c */ +extern double backsp_width P((int size)); +extern int next_str_char P((char **str_p, int *font_p, int *size_p)); +extern int nxt_str_char P((char **str_p, int *font_p, int *size_p, + int *textfont_p, double *vertical_p, double *horizontal_p, + int *in_pile_p, int slash)); +extern double align_distance P((char *string, int font, int size)); +extern double pile_width P((void)); +extern int pile_size P((int size, int in_pile)); + +/* parstssv.c */ +extern struct TIMEDSSV *tssv_create P((int context)); +extern void tssv_update P((struct TIMEDSSV *timedssv_p, int param, int value)); +extern void tssv_setgrpsyl P((struct GRPSYL *gs_p)); +extern void tssv_line P((void)); +extern struct TIMEDSSV *tssv_sort P((void)); + +/* parstuff.c */ +extern void chk_stuff_header P((int size, int modifier, int place, + int dist_usage)); +extern void add_stuff_item P((double start_count, double start_steps, + int gracebackup, char *string, int bars, double count, + int dist, int dist_usage)); +extern int string_is_sym P((char *string, int sym, int font)); +extern void attach_stuff P((void)); +extern void meas_stuff_chk P((void)); +extern void chk4dangling_til_clauses P((char *boundary_desc)); +extern struct STUFF *newSTUFF P((char *string, int dist, int dist_usage, + double start_count, double start_steps, int gracebackup, + int bars, double count, int stuff_type, int modifier, + int place, char *inputfile, int inputlineno)); +extern void reset_ped_state P((void)); +extern void set_reh_string P((struct BAR *bar_p, int fontfamily, int font, + int size, char *string)); +extern void set_stuff_type P((int stuff_type)); +extern int dflt_place P((void)); +extern void ped_endings P((int endingloc)); +extern void multi_stuff P((int nmeas)); +extern int get_stuff_type P((void)); +extern char *stuff_modifier P((int modifier)); +extern char *pad_string P((char *string, int modifier)); +extern void connect_stuff P((struct STAFF *staff_p, struct STUFF *stufflist_p)); +extern void init_reh P((int rehnumber, char *rehletter, + struct MAINLL *mainbar_p)); + +/* phrase.c */ +extern void phrase_points P((struct MAINLL *mll_p, struct STUFF *stuff_p)); +extern void tieslur_points P((struct MAINLL *mll_p, struct STUFF *stuff_p)); +extern void bend_points P((struct MAINLL *mll_p, struct STUFF *stuff_p)); +extern void tabslur_points P((struct MAINLL *mll_p, struct STUFF *stuff_p)); + +/* plutils.c */ +extern struct GRPSYL *nextnongrace P((struct GRPSYL *gs_p)); +extern struct GRPSYL *prevnongrace P((struct GRPSYL *gs_p)); +extern struct GRPSYL *nextglobnongrace P((struct GRPSYL *gs_p, + struct MAINLL **mll_p_p)); +extern struct GRPSYL *prevglobnongrace P((struct GRPSYL *gs_p, + struct MAINLL **mll_p_p)); +extern int drmo P((int num)); +extern double tieslurpad P((struct STAFF *staff_p, struct GRPSYL *gs_p)); +extern int hasspace P((struct GRPSYL *gs_p, RATIONAL vtime, RATIONAL vtime2)); +extern struct GRPSYL *closestgroup P((double count, struct GRPSYL *firstgs_p, + int timeden)); +extern int chkallspace P((struct MAINLL *msbeg_p, struct STUFF *stuff_p, + int vno)); +extern int allspace P((int vno, struct MAINLL *msbeg_p, RATIONAL begtime, + struct MAINLL *msend_p, RATIONAL endtime)); +extern struct MAINLL *getendstuff P((struct MAINLL *mainll_p, + struct STUFF *stuff_p, int *timeden_p)); +extern void accdimen P((struct NOTE *note_p, float *ascent_p, float *descent_p, + float *width_p)); +extern double staffvertspace P((int s)); +extern double halfstaffhi P((int s)); +extern RATIONAL ratbend P((struct NOTE *note_p)); +extern double notehorz P((struct GRPSYL *gs_p, struct NOTE *note_p, int coord)); +extern int allsmall P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p)); +extern void finalstemadjust P((struct GRPSYL *gs_p)); +extern double getstemshift P((struct GRPSYL *gs_p)); +extern int vscheme_voices P((int vscheme)); +extern struct MAINLL *chmgrp2staffm P((struct MAINLL *mll_p, + struct GRPSYL *gs_p)); +extern void shiftgs P((struct GRPSYL *gs_p, double shift)); +extern double nearestline P((double offset)); +extern void vfyoffset P((struct GRPSYL *g_p[])); +extern double adjslope P((struct GRPSYL *g_p, double oldslope, int betweencsb)); +extern double eos_bar_adjust P((struct BAR *bar_p)); +extern double curve_y_at_x P((struct CRVLIST *first_p, double x)); +extern double findcubic P((struct CRVLIST *left_p, struct CRVLIST *right_p, + float *a_p, float *b_p, float *c_p)); +extern double solvecubic P((double a, double b, double c, double d, + double lo, double hi, double thresh)); +extern int css_affects_stemtip P((struct GRPSYL *gs1_p)); +extern struct CHORD *gs2ch P((struct MAINLL *mll_p, struct GRPSYL *gs_p)); +extern int css_affects_tieslurbend P((struct STUFF *stuff_p, struct MAINLL *mll_p)); +extern int css_affects_phrase P((struct STUFF *stuff_p, struct MAINLL *mll_p)); +extern struct GRPSYL *nextsimilar P((struct GRPSYL *gs_p)); +extern struct GRPSYL *prevsimilar P((struct GRPSYL *gs_p)); +extern double stemroom P((struct GRPSYL *gs_p)); + +/* print.c */ +extern void print_music P((void)); +extern void do_linetype P((int ltype)); +extern void draw_line P((double x1, double y1, double x2, double y2)); +extern void pr_muschar P((double x, double y, int ch, int size, int font)); +extern double pr_clefsig P((struct MAINLL *mll_p, struct CLEFSIG *clefsig_p, + int really_print)); +extern void pr_string P((double x, double y, char *string, int justify, + char *fname, int lineno)); +extern void end_curve P((int ncoord, double x, double y)); +extern void outcoord P((double val)); +extern void draw_wavy P((double x1, double y1, double x2, double y2)); +extern void do_pr_brac P((double x, double y1, double y2, int which)); +extern void pr_linenum P((char *inputfile, int inputlineno)); +extern void do_moveto P((double x, double y)); +extern void do_line P((double x, double y)); +extern void do_fill P((void)); +extern void do_stroke P((void)); +extern void do_curveto P((double x1, double y1, double x2, double y2, + double x3, double y3)); +extern void do_newpath P((void)); +extern void do_closepath P((void)); +extern void trailer P((void)); +extern void do_closepath P((void)); +extern void do_whitebox P((double x1, double y1, double x2, double y2)); +extern void draw_prop_line P((double x1, double y1, double x2, double y2, + int size, int ltype)); +extern void do_grid P((double x, double y, double space, struct GRID *grid_p, + int staff)); +extern void newpage P((struct MAINLL *mll_p)); +extern void pr_feed P((struct MAINLL *main_feed_p)); +extern double pr_clef P((int staffno, double x, int really_print, int size)); + +/* prntdata.c */ +extern void pr_staff P((struct MAINLL *mll_p)); +extern int tupdir P((struct GRPSYL *gs_p, struct STAFF *staff_p)); +extern char *num2str P((int num)); +extern char *mrnum P((struct STAFF *staff_p, double *x_p, double *y_offset_p, + double *height_p, double *width_p)); +extern int tupgetsbrack P((struct GRPSYL *gs_p)); +extern char *tupnumsize P((struct GRPSYL *gs_p, float *west_p, + float *east_p, float *height_p, struct STAFF *staff_p)); +extern int pbeamside P((struct GRPSYL *gs_p, struct GRPSYL *first_p)); +extern struct GRPSYL *nxtbmgrp P((struct GRPSYL *gs_p, struct GRPSYL *first_p, + struct GRPSYL *endnext_p)); +extern struct GRPSYL *prevbmgrp P((struct GRPSYL *gs_p, + struct GRPSYL *first_p)); +extern double end_bm_offset P((struct GRPSYL *top_first_p, struct GRPSYL *end_p, + int basictime)); +extern void pr_slashes P((struct GRPSYL *grpsyl_p, double x, double y, + double sign, double offset, double y_tilt)); +extern void pr_tab_groups P((struct GRPSYL *gs_p, struct MAINLL *mll_p)); +extern void pr_withlist P((struct GRPSYL *gs_p)); +extern void pr_mrpt P((struct GRPSYL *gs_p, struct STAFF *staff_p)); +extern void pr_multirest P((struct GRPSYL *gs_p, struct STAFF *staff_p)); + +/* prntmisc.c */ +extern void pr_endings P((struct MAINLL *main_feed_p)); +extern int has_ending P((int staffno)); +extern void pr_ped_char P((struct STUFF *stuff_p, int staffno)); +extern void pr_ped_bar P((struct MAINLL *mll_p, struct BAR *bar_p)); +extern void pr_phrase P((struct CRVLIST *crvlist_p, int linetype, int tapered, + int staffno)); +extern void pr_allcurve P((float x[], float y[], int num, double cwid, + int tapered)); +extern void saveped P((struct MAINLL *mll_p, struct BAR *bar_p)); +extern double ped_offset P((void)); +extern void pr_bend P((struct CRVLIST *crvlist_p)); +extern void pr_tabslur P((struct CRVLIST *crvlist_p, int ts_style)); +extern void pr_sm_bend P((double x, double y)); +extern void pr_atend P((void)); + +/* prnttab.c */ +extern char *fret_string P((struct NOTE *note_p, struct GRPSYL *gs_p)); +extern char *bend_string P((struct NOTE *note_p)); +extern void pr_tab_groups P((struct GRPSYL *gs_p, struct MAINLL *mll_p)); +extern double pr_tabclef P((int staffno, double x, int really_print, int size)); + +/* prolog.c */ +extern void ps_prolog P((void)); + +/* range.c */ +extern void begin_range P((int place)); +extern void save_staff_range P((int beginstaffno, int endstaffno)); +extern void save_vno_range P((int begin, int end)); +extern void free_rlists P((void)); +extern void chk_range_type P((int has_ampersand)); +extern void create_staffs P((void)); +extern void all P((void)); +extern void free_staffrange P((void)); +extern void free_vnorange P((void)); +extern int is_tab_staff P((int staffno)); +extern int leadstaff P((void)); +extern void add_to_sv_list P((void)); +extern void free_sv_list P((struct SVRANGELIST *svlist_p)); +extern void begin_sv_list P((void)); + +/* relvert.c */ +extern void relvert P((void)); + +/* restsyl.c */ +extern void restsyl P((void)); + +/* roll.c */ +extern void newROLLINFO P((void)); +extern void setrolldir P((int dir)); +extern void rollparam P((int topstaff, int topvoice, int botstaff, + int botvoice)); +extern void rolloffset P((double offset)); +extern void do_rolls P((struct MAINLL *mll_p)); +extern void print_roll P((struct GRPSYL *gs_p)); +extern int gets_roll P((struct GRPSYL *gs_p, struct STAFF *staff_p, int v)); + +/* setgrps.c */ +extern void setgrps P((void)); + +/* setnotes.c */ +extern void setnotes P((void)); + +/* ssv.c */ +extern void initstructs P((void)); +extern void zapssv P((struct SSV *s_p)); +extern struct SSV *svpath P((int s, int field)); +extern struct SSV *vvpath P((int s, int v, int field)); +extern void asgnssv P((struct SSV *i_p)); +extern void setssvstate P((struct MAINLL *mainll_p)); + +/* stuff.c */ +extern void stuff P((void)); + +/* symtbl.c */ +extern void init_symtbl P((void)); +extern void addsym P((char *symname, float *coordlist_p, int coordtype)); +extern float *symval P((char *symname, float **ref_p_p)); +extern struct COORD_INFO *find_coord P((float *key)); +extern void add_coord P((float *coordlist_p, int coordtype)); +extern struct GRID *findgrid P((char *name)); +extern void add_grid P((char *name, char *griddef)); +extern struct GRID *nextgrid P((struct GRID *grid_p)); +extern void set_win_coord P((float *coord_p)); +extern void add_shape P((char *name, char *shapes)); +extern int nheadchar P((int headshape, int basictime, int stemdir, + int *font_p)); +extern int get_shape_num P((char *shapename)); +extern double stem_yoff P((int headch, int font, int stemdir)); +extern void remember_tsig_params P((struct MAINLL *mll_p)); +extern void upd_ref P((float *old_p, float *new_p)); +extern void rep_inpcoord P((struct INPCOORD *old_inpcoord_p, + struct INPCOORD *new_inpcoord_p)); + +/* tie.c */ +extern void tie P((void)); +extern void tie_carry P((void)); +extern struct GRPSYL *find_1st_grp_in_nxt_measure P((struct MAINLL *mll_p, + int vno)); +extern struct GRPSYL *find_next_group P((struct MAINLL *mll_p, + struct GRPSYL *gs_p, char *type)); +extern struct NOTE *find_matching_note P((struct GRPSYL *gs_p, + int letter, int octave, char *type_p)); + +/* trantab.c */ +extern void tab2tabnote P((void)); + +/* trnspose.c */ +extern void transgroups P((void)); +extern char *tranchnote P((int letter, int acc, int staffno)); +extern int eff_key P((int staff)); +extern void totaltrans P((int s, int *type_p, int *num_p)); + +/* undrscre.c */ +extern int spread_extender P((struct GRPSYL *gs_p, struct MAINLL *mll_p, + int verse, int sylplace, int really_print)); +extern int has_extender P((char *syl)); +extern void cont_extender P((struct MAINLL *mll_p, int sylplace, + int verseno)); +extern int last_char P((char *str)); + +/* utils.c */ +extern void set_cur P((double x, double y)); +extern void set_win P((double n, double s, double e, double w)); +extern double width_barline P((struct BAR *bar_p)); +extern double width_clefsig P((struct CLEFSIG *clefsig_p)); +extern int clefchar P((int clef)); +extern void calc_headfoot_height P((void)); +extern int numbeams P((int btime)); +extern int acc2char P((int acc)); +extern double inpc_x P((struct INPCOORD *inpcoord_p, char *fname, int lineno)); +extern double inpc_y P((struct INPCOORD *inpcoord_p, char *fname, int lineno)); +extern double find_y_stem P((struct GRPSYL *gs_p)); +extern double find_x_stem P((struct GRPSYL *gs_p)); +extern double width_keysig P((int sharps, int naturals)); +extern struct GRPSYL *nextgrpsyl P((struct GRPSYL *gs_p, + struct MAINLL **mll_p_p)); +extern struct GRPSYL *prevgrpsyl P((struct GRPSYL *gs_p, + struct MAINLL **mll_p_p)); +extern void octave_transpose P((struct STAFF *staff_p, struct MAINLL *mll_p, + int vno, int normdir)); +extern int eff_acc P((struct GRPSYL *gs_p, struct NOTE *note_p, + struct MAINLL *mll_p)); +extern int acc_from_keysig P((int letter, int staffno, struct MAINLL *mll_p)); +extern void set_staffscale P((int s)); +extern void gridsize P((struct GRID *grid_p, int staff, float *north_ptr, + float *south_ptr, float *east_ptr, float *west_ptr)); +extern double gridspace P((int staff)); +extern void gridinfo P((struct GRID *grid_p, int staff, int *frets_p, + int *fretnum_p, int *numvert_p, int *topfret_p)); +extern double clefspace P((int prevclef, double prevscale, int curclef, + double curscale, int measnum)); +extern double eff_rightmargin P((struct MAINLL *mainll_p)); +extern double eff_leftmargin P((struct MAINLL *mainll_p)); +extern short *findprimes P((int max)); +extern short *factor P((int num)); +extern double clefwidth P((int clef, int is_small)); +extern int clefvert P((int clef, int is_small, float *north_p, float *south_p)); +extern double widest_head P((struct GRPSYL *gs_p)); +extern void calc_block_heights P((void)); + +#endif diff --git a/mup/mup/grpsyl.c b/mup/mup/grpsyl.c new file mode 100644 index 0000000..fee4085 --- /dev/null +++ b/mup/mup/grpsyl.c @@ -0,0 +1,3427 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions for building up lists of GRPSYL structs, + * error checking them, etc. These functions are called at parse + * time from gram.y */ + + +#include +#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)); + + +/* 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); +} + + +/* 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; +} + + +/* 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); + } + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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"); + } + } + } +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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)++; +} + + +/* 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); + } +} + + +/* 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(); +} + + +/* 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); +} + + +/* 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(); +} + + +/* 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(); +} + + +/* 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); + } +} + + +/* 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"); + } + } + } + } +} + + +/* 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); + } +} + + +/* 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; + } + } + } + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); + } +} + + +/* 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; +} + + +/* 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; + } + } + } +} + + +/* 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; + } + } +} + + +/* 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; +} + +/* 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; + } + } + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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--; + } + } + } +} + + +/* 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); +} + + +/* 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"); + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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)++; +} + + +/* 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., + * aupdown + */ + +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; + } + } +} + + +/* 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)); +} + + +/* 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; + } + } + } +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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); +} + + +/* 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"); + } + } +} + + +/* + * 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); +} + + +/* + * Given a RATIONAL basictime and number of dots, + * return the corresponding fulltime. That is calculated by + * (2 * basictime) - (basictime x 1/2 to the (dots) power) + */ + +RATIONAL +calcfulltime(basictime, dots) + +RATIONAL basictime; +int dots; + +{ + return( rsub (rmul(Two, basictime), rmul(basictime, rrai(One_half, dots))) ); +} diff --git a/mup/mup/ifgram.c b/mup/mup/ifgram.c new file mode 100644 index 0000000..e516f07 --- /dev/null +++ b/mup/mup/ifgram.c @@ -0,0 +1,1697 @@ +/* A Bison parser, made from ifgram.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* If NAME_PREFIX is specified substitute the variables and functions + names. */ +#define yyparse ifparse +#define yylex iflex +#define yyerror iferror +#define yylval iflval +#define yychar ifchar +#define yydebug ifdebug +#define yynerrs ifnerrs + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + ICT_AND = 258, + ICT_BITAND = 259, + ICT_BITCOMPLEMENT = 260, + ICT_BITOR = 261, + ICT_BITXOR = 262, + ICT_COLON = 263, + ICT_DIVIDE = 264, + ICT_END = 265, + ICT_ERROR = 266, + ICT_EQ = 267, + ICT_FALSE = 268, + ICT_GT = 269, + ICT_GE = 270, + ICT_LPAREN = 271, + ICT_LE = 272, + ICT_LT = 273, + ICT_MINUS = 274, + ICT_MOD = 275, + ICT_MULT = 276, + ICT_NE = 277, + ICT_NOT = 278, + ICT_OR = 279, + ICT_PLUS = 280, + ICT_QUESTION = 281, + ICT_RPAREN = 282, + ICT_SHLEFT = 283, + ICT_SHRIGHT = 284, + ICT_TRUE = 285, + ICT_VALUE = 286 + }; +#endif +#define ICT_AND 258 +#define ICT_BITAND 259 +#define ICT_BITCOMPLEMENT 260 +#define ICT_BITOR 261 +#define ICT_BITXOR 262 +#define ICT_COLON 263 +#define ICT_DIVIDE 264 +#define ICT_END 265 +#define ICT_ERROR 266 +#define ICT_EQ 267 +#define ICT_FALSE 268 +#define ICT_GT 269 +#define ICT_GE 270 +#define ICT_LPAREN 271 +#define ICT_LE 272 +#define ICT_LT 273 +#define ICT_MINUS 274 +#define ICT_MOD 275 +#define ICT_MULT 276 +#define ICT_NE 277 +#define ICT_NOT 278 +#define ICT_OR 279 +#define ICT_PLUS 280 +#define ICT_QUESTION 281 +#define ICT_RPAREN 282 +#define ICT_SHLEFT 283 +#define ICT_SHRIGHT 284 +#define ICT_TRUE 285 +#define ICT_VALUE 286 + + + + +/* Copy the first part of user declarations. */ +#line 2 "ifgram.y" + +/* Copyright 2005 by Arkkra Enterprises */ +/* All rights reserved. */ + +/* This is a "mini-parser" that handles "if" clauses. + * It uses a buffer containing a compressed form of the user's input. + * The compressed format is described in lex.c above add_ifclause(). + * This tries to follow the ANSI C preprocessor rules as much as is reasonable. + * It uses C operator precedences and associativity. + * We do use 32-bit ints rather than longs to try to avoid any + * incompatibilities if someone creates a Mup file on a 32-bit machine + * and then tries to run it on 64-bit or vice-versa. + */ + +#include "defines.h" +#include "globals.h" + +#define YYDEBUG 1 + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#ifndef YYSTYPE +typedef int yystype; +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +#ifndef YYLTYPE +typedef struct yyltype +{ + int first_line; + int first_column; + int last_line; + int last_column; +} yyltype; +# define YYLTYPE yyltype +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +/* Copy the second part of user declarations. */ + + +/* Line 213 of /usr/share/bison/yacc.c. */ +#line 185 "ifgram.tab.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* 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 /* 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 /* 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 + + + +#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 */ + + + +#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; + } +} + + + +/* 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" + + yyvsp -= yylen; + yyssp -= yylen; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (YYPACT_NINF < yyn && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + int yytype = YYTRANSLATE (yychar); + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[yytype]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[yytype]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*----------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action. | +`----------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* Return failure if at end of input. */ + if (yychar == YYEOF) + { + /* Pop the error token. */ + YYPOPSTACK; + /* Pop the rest of the stack. */ + while (yyssp > yyss) + { + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], + *yyvsp)); + YYDPRINTF ((stderr, "\n")); + yydestruct (yystos[*yyssp], *yyvsp); + YYPOPSTACK; + } + YYABORT; + } + + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yydestruct (yychar1, yylval); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + YYDPRINTF ((stderr, "Error: popping ")); + YYDSYMPRINT ((stderr, + yystos[*yyssp], *yyvsp)); + YYDPRINTF ((stderr, "\n")); + + yydestruct (yystos[yystate], *yyvsp); + yyvsp--; + yystate = *--yyssp; + + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + } + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; + + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*----------------------------------------------. +| yyoverflowlab -- parser overflow comes here. | +`----------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} + + +#line 272 "ifgram.y" + + +/* This is a pointer to the buffer containing the clause in compressed form. + * A call to set_ifclause_buffer() sets this to point to an actual array */ +static unsigned char * Buffer; + +/* Our current position in Buffer */ +static int Offset; + +/* length of Buffer */ +static int Length; + + + +/* To use this mini-parser, put the clause in compressed internal form + * in an array, and pass that array and its length to this function, + * then call ifparse(). + */ + +void +set_ifclause_buffer(buff, len) + +unsigned char * buff; +int len; + +{ + Buffer = buff; + Length = len; + Offset = 0; +} + + +/* The compressed if-clause format is described in lex.c above add_ifclause(). + * Since it's very simple (everything except numbers + * are single character tokens), we have a hand-coded lexer. + * It maps the compressed format tokens to bison tokens. + */ + +int +iflex() +{ + if (Offset == Length) { + return(ICT_END); + } + + switch(Buffer[Offset++]) { + + case '(': + return(ICT_LPAREN); + case ')': + return(ICT_RPAREN); + + case '!': + return(ICT_NOT); + case '~': + return(ICT_BITCOMPLEMENT); + + case '*': + return(ICT_MULT); + case '/': + return(ICT_DIVIDE); + case '%': + return(ICT_MOD); + + case '+': + return(ICT_PLUS); + case '-': + return(ICT_MINUS); + + case 'l': + return(ICT_SHLEFT); + case 'r': + return(ICT_SHRIGHT); + + case '<': + return(ICT_LT); + case '>': + return(ICT_GT); + case 'L': + return(ICT_LE); + case 'G': + return(ICT_GE); + + case 'E': + return(ICT_EQ); + case 'N': + return(ICT_NE); + + case '&': + return(ICT_BITAND); + + case '^': + return(ICT_BITXOR); + + case '|': + return(ICT_BITOR); + + case 'a': + return(ICT_AND); + + case 'o': + return(ICT_OR); + + case '?': + return(ICT_QUESTION); + case ':': + return(ICT_COLON); + + case 'T': + return(ICT_TRUE); + case 'F': + return(ICT_FALSE); + case '#': + iflval = ((Buffer[Offset] << 24) & 0xff000000) + | ((Buffer[Offset+1] << 16) & 0xff0000) + | ((Buffer[Offset+2] << 8) & 0xff00) + | (Buffer[Offset+3] & 0xff); + Offset += 4; + return(ICT_VALUE); + + default: + return(ICT_ERROR); + } +} + + + +/* Error message printer for syntax/semantic errors in 'if' clauses. + * WARNING: bison appears to somehow use yyerror even when using a prefix + * other than yy. So if this function calls yyerror, it gets into an + * infinite loop! So don't do that... + */ + +int +iferror(msg) + +char * msg; + +{ + l_yyerror(Curr_filename, yylineno, msg); + return(0); +} + + diff --git a/mup/mup/lex.c b/mup/mup/lex.c new file mode 100644 index 0000000..dc303ea --- /dev/null +++ b/mup/mup/lex.c @@ -0,0 +1,5059 @@ +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* 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 +#include +#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 +#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 +#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" + + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } +} + + + +/* 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); +} + + +/* 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); +} + + +/* at the very end, verify all if, ifdef, and ifndef clauses are closed */ + +void +chk_ifdefs() + +{ + if (If_count != 0) { + yyerror("missing endif"); + } +} + + +/* 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); +} + + +/* 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; + +} + + +/* 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'; +} + + +/* push a character back into input. This allows another C file to + * access the unput macro */ + +void +pushback(c) + +int c; + +{ + unput(c); +} + + +/* 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); + } +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* Give error message for invalid input character, as actual character + * if printable, otherwise as hex value. */ + +static void +bad_input(where) + +char *where; /* describes where the bad input was found */ + +{ + if (isgraph(yytext[0])) { + l_yyerror(Curr_filename, yylineno, + "invalid character in %s: '%c'", + where, yytext[0]); + } + else { + l_yyerror(Curr_filename, yylineno, + "invalid character in %s: 0x%x", + where, (int) yytext[0]); + } +} diff --git a/mup/mup/locvar.c b/mup/mup/locvar.c new file mode 100644 index 0000000..7979307 --- /dev/null +++ b/mup/mup/locvar.c @@ -0,0 +1,2359 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2003, 2004 by Arkkra Enterprises */ +/* All rights reserved */ + +/* +There are 3 classes of location variables: + + A. Those associated with a specific staff of a specific score. + This includes those for GRPSYLs and NOTES. + + B. Those associated with a specific score. These are for bars. + + C. Those associated with the current page. These are the builtin + variables such as _win and _page, or absolute coordinates. + +Type B variables, associated with bars, are extra strange. The y of a bar +in not particularly useful. If the bar line happens to wind up at the end +of a score, special consideration applies, because the right side of the +bar is effectively at the beginning of the next score after the clefsig. +So here are the rules: + +1. If a bar does not occur at the end of a score, the location variable +associated with it, if any, is handled normally. + +2. If a bar does fall on the end of a score, if the x coordinate derived from +a location variable associated with that bar in +an INPCOORD, after offsetting, comes out to be either left of the x of +the bar, or equal to the x of the bar, it will be handled normally. + +3. If a bar falls on the end of a score, and +if the x coordinate derived from an INPCOORD, after offsetting, comes out +to be right of the x of the bar, +the x coordinate will be recalculated using the pseudo +bar at the beginning of the following score, +and if the y coordinate of the same INPCOORD is also associated +with the same bar coordinate, it will also be recalculated from the pseudo bar. + +4. If rule 3 would normally apply, but there is no following score, rule 3 +will be ignored, and the coordinate will be used as is. + +A PRHEAD contains only a single location variable, so it should always +be taken just as is. + +Lines and curves are more exciting, since they can have multiple +coordinates, and thus may need to be split into 2 or more pieces +across scores and/or pages. Lines are a degenerate case of curves, +so if we can deal with curves, we've got it made. + +For drawing a specific curve, here are the rules: + +1. If any coordinate is associated with a staff that is invisible, the entire +curve will be ignored. + +2. Type C variables are always used as is, never themselves causing splitting. +Taking any adjacent pair of points in a curve, if either of them is of type C, +the line segment between those 2 points will not be split. + +3. If all variables of type A and B are on the same score of the same page, +then the curve can be printed as is, with no splitting needed. + +4. If the x and y components of a single INPCOORD are associated with +different scores, this will be an error condition. + +5. If the x and y components of a single INPCOORD are associated with +different staffs, but the same score, the point will be treated as if +it were associated with the staff associated with the y coordinate. + +6. If 2 adjacent points of a curve are associated with different +scores, the line segment must be split. The number of segments that will +need to be generated will be equal to the number of FEEDs between +the coordinates plus one. + +7. Splitting will only be done to forward scores. In other words, if the +coordinates of a curve would require splitting part of the curve onto a +preceeding score, that will be an error. This is to keep things simpler, +since I can't think of any times this restriction would cause a problem. + +8. If a segment needs to be split, the first piece will extend in the +x direction from the first point to 0.1 inch left of the right edge of the +score associated with the first point. +However, if the starting x is already at the right edge of the score, a line of length 0.1 inches will be drawn instead. +The last piece of the split line segment will extend in +the x direction from the pseudo bar of the clefsig. + +8a. If there are additional scores +between the one associated with the beginning point and the one associated +with the endpoint, for each intervening score a line will be drawn with +its x coordinates from the pseudo bar to the right margin. + +9. To calculate the y coordinates of each piece of a split line segment, +there are several cases. First the easy case, where the y coordinates of +the beginning and ending point are both associated with the same staff. +Conceptionally, the scores are lined up on a single line without score +feeds. The slope of the line is then calculated. The y coordinates of +the derived points are then calculated using this slope. Thus, for example, +if the ending y coordinate would be A inches from of the beginning y coordinate +in the x direction (if they were on the same score), +and the line segment is split into 2 segments, with the first having +a length in the x direction of B and the second having a length in the x +direction of C, the y coordinate of the end of the first segment would be +y[begin] + (A/(B+C)) * B, and the y coordinate of the beginning of the second +piece would be y[end] - (A/(B+C)) * C. + +10. If the y coordinates of the 2 points are associated with different staffs. +the slope is calculated based on the distance of the endpoints from their +respective staffs. Then for each segment, the slope and endpoints are adjusted +based on the ratio of the distance between the two staffs on the current score +relative to the widest distance. + +11. For purposes of determining y coordinates, the y and n values of a bar +are considered to be associated with the top visible score, and the s value +is considered to be associated with the bottom visible score. +Then rules 9 and 10 above are applied as for with type A coordinates. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +static int Total_pages = 1; /* how many pages of output */ + +/* if lines must be added for intervening scores, save info about them */ +struct SEGINFO { + struct MAINLL *mll_p; /* FEED where line segment must go */ + double xlength; /* x length prior to current score */ + struct SEGINFO *next; /* linked list */ +}; +struct SEGINFO *Seginfo_p; + +static void gather_coord_info P((void)); +static void save_coord_info P((struct COORD_INFO *coord_info_p, + int coordtype, int page, int score, int staff, + struct MAINLL *mll_feed_p, int vis)); +static void coord_staff P((struct STAFF *staff_p, int page, + int score, struct MAINLL *mll_feed_p)); +static void split_lines_and_curves P((void)); +static void chkline P((struct MAINLL *mll_p)); +static void coordcheck P((struct COORD_INFO *x_info_p, + struct COORD_INFO *y_info_p, char *fname, int lineno)); +static void add_segment P((struct SEGINFO *seginfo_p, double slope, + double y_offset, int staffno1, int linetype)); +static double find_effXlength P((double seg1xlen, double seg2xlen, + struct COORD_INFO *x1info_p, struct COORD_INFO *x2info_p, + int save_feed_info)); +static void svfeed P((struct MAINLL *mll_feed_p, double xlength)); +static int eff_staff P((struct COORD_INFO *yinfo_p)); +static double getYstaff P((struct MAINLL *mll_p, int staffno)); +static void chkcurve P((struct MAINLL *mll_p)); +static int bulgedir P((struct CURVE *curve_p, int index, char *inputfile, + int inputlineno)); +static int cmpcoords P((struct CURVE *curve_p, int p1, int p2)); +static int abs2rel P((int vtype)); +static void add_crv_seg P((struct SEGINFO *seginfo_p, double slope, + double y_offset, int staffno1, int curvetype, int bulge, + char *filename, int lineno)); +static int is_invis P((struct COORD_INFO *cinfo_p)); +static int is_builtin P((struct COORD_INFO *cinfo_p)); +static void move2correct_page P((void)); +static void move_it P((struct MAINLL *m_p, struct MAINLL *im_p, int page)); +static void move2pseudo P((void)); +static void do_pseudo P((struct INPCOORD *inpc_p, struct MAINLL *mll_p)); +static void fix_inpcoords P((struct MAINLL *mll_p)); +static void adj_coord P((struct INPCOORD *coord_p, struct MAINLL *mll_p, + struct INPCOORD *prev_coord_p)); +static void calc_bulge P((struct CURVE *curve_p, char *fname, int lineno, + int is_split, struct MAINLL *mll_p)); + + +/* 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(); +} + + +/* 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; + } + } +} + + +/* 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; + } +} + + +/* 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); + } + } + } + } +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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"); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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 ); + } + } + } +} + + +/* 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; + } + } + } +} + + +/* 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) ); + } +} + + +/* 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); +} + + +/* For manual curves that use "bulge" values, figure out the intermediate + * points for curves, and put them in the coordlist, getting rid of the + * bulgelist. + */ + +static void +calc_bulge(curve_p, fname, lineno, is_split, mll_p) + +struct CURVE *curve_p; /* curve defined using bulge */ +char *fname; +int lineno; +int is_split; /* YES if goes across at least one FEED */ +struct MAINLL *mll_p; /* for finding effective margin */ + +{ + double x1, y1; /* start point location */ + double x2, y2; /* end point location */ + double xlen, ylen; /* distances between endpoints */ + double seg1xlen, seg2xlen; /* lengths of parts of curve on + * first and last score when split */ + double sintheta, costheta; /* for rotation */ + double length; /* between endpoints */ + double segX, segY; /* distance to intermediate point */ + int p1staff, p2staff; /* staff associated with each point */ + struct INPCOORD *coordlist_p; /* the new calculated curve */ + int n; /* index through bulge points */ + int nbulge; /* how many bulge points specified */ + double staffscale; + struct COORD_INFO *x1info_p, *y1info_p; /* to get staff info, etc */ + struct COORD_INFO *x2info_p, *y2info_p; + + + nbulge = curve_p->nbulge; + + /* The calculated curve will have the 2 endpoints plus nbulge + * intermediate points */ + MALLOC (INPCOORD, coordlist_p, 2 + nbulge); + + /* The endpoints just get copied. All the inner points will + * be calculated relative to the first, so for now we copy all of + * the INPCOORD data from the first point into them, then later + * we will overwrite the offset values appropriately. */ + for (n = 0; n < nbulge + 1; n++) { + coordlist_p[n] = curve_p->coordlist[0]; + } + coordlist_p[nbulge + 1] = curve_p->coordlist[1]; + + /* Find relevant information about the endpoints */ + x1 = inpc_x( &(curve_p->coordlist[0]), fname, lineno); + y1 = inpc_y( &(curve_p->coordlist[0]), fname, lineno); + x2 = inpc_x( &(curve_p->coordlist[1]), fname, lineno); + y2 = inpc_y( &(curve_p->coordlist[1]), fname, lineno); + + x1info_p = find_coord( curve_p->coordlist[0].hor_p); + y1info_p = find_coord( curve_p->coordlist[0].vert_p); + x2info_p = find_coord( curve_p->coordlist[1].hor_p); + y2info_p = find_coord( curve_p->coordlist[1].vert_p); + + /* If all coordinates associated with staffs having the same + * staffscale value, then use that, otherwise use score value + */ + if ((staffscale = svpath(x1info_p->staffno, STAFFSCALE)->staffscale) != + svpath(y1info_p->staffno, STAFFSCALE)->staffscale + || staffscale != + svpath(x2info_p->staffno, STAFFSCALE)->staffscale + || staffscale != + svpath(y2info_p->staffno, STAFFSCALE)->staffscale) { + staffscale = Score.staffscale; + } + + /* Find the length of the line segment + * that would go straight between the two endpoints. To do this, + * we get the x and y distances to use with Pythagorean theorem */ + if (is_split == NO) { + /* if all on same score, easier to find a and y */ + xlen = (x2 - x1); + ylen = (y2 - y1); + } + else { + /* Split curves take more work. First find x length + * on the score containing the first part of the curve */ + seg1xlen = PGWIDTH - eff_rightmargin(mll_p) - + inpc_x( &(curve_p->coordlist[0]), fname, lineno ); + + /* Find the x length of the score containing the last past. + * To do this, have to find the pseudo-bar inside the + * appropriate CLEFSIG, which should be on the main list + * immediately following the FEED + * of the score containing the ending x coordinate. */ + seg2xlen = inpc_x( &(curve_p->coordlist[1]), fname, lineno) - + x2info_p->mll_feed_p->next->u.clefsig_p->bar_p->c[AX]; + + /* Finally, add in the x lengths of any intervening scores */ + xlen = find_effXlength(seg1xlen, seg2xlen, + x1info_p, x2info_p, NO); + + /* Now we need the distance in the y direction. First, the + * easy case, when both endpoints are associated with the + * same staff */ + p1staff = eff_staff(y1info_p); + p2staff = eff_staff(y2info_p); + if (p1staff == p2staff) { + /* y length is the relative Y of the INPCOORD + * of the final point, offset by its vsteps, minus + * the similar value of the beginning point. */ + ylen = (curve_p->coordlist[1].vert_p + [abs2rel(curve_p->coordlist[1].vtype)] + + curve_p->coordlist[1].vsteps + * STEPSIZE * staffscale) + - (curve_p->coordlist[0].vert_p + [abs2rel(curve_p->coordlist[0].vtype)] + + curve_p->coordlist[0].vsteps + * STEPSIZE * staffscale); + } + else { + /* The endpoints are associated with different staffs. + * The y distance between these two staffs may vary + * from score to score, so to get things really + * accurate, we'd have to adjust the y proportionally + * on each intervening score, which may require adding + * lots of intermediate points and lots of complicated + * calculations which may or may not look much better + * than doing something more simple. So just do + * something fairly simple: Find the distance between + * each endpoint's y and its staff's y, and subtract + * those two distances to get an approximate ylen. + * As long as the distance between the two staffs is + * somewhat similar on both scores, + * which is likely to be the case, + * the results should be pretty good. */ + ylen = (y1info_p->mll_feed_p->next->u.clefsig_p->bar_p->c[AY] - y1) - + (y2info_p->mll_feed_p->next->u.clefsig_p->bar_p->c[AY] - y2); + } + } + + /* Find distance between the endpoints */ + length = sqrt( SQUARED(xlen) + SQUARED(ylen) ); + + /* Guard again divide by zero */ + if (length < 0.0001) { + l_ufatal(fname, lineno, "curve endpoints too close together"); + } + + /* We find the intermediate points as if the line were horizontal, + * then rotate it, so need the sine and cosine for rotation. + */ + sintheta = ylen / length; + costheta = xlen / length; + + /* Calculate the position of each inner point. */ + for (n = 1; n <= nbulge; n++) { + /* horizontal offset is based on a fraction of the length + * between endpoints: 1/2 if there is one bulge value, + * 1/3 and 2/3 if there are two values, etc, so use + * n/(nbulge + 1) to get the unrotated x lengths. + * Use the bulge value (which is already in stepsizes) + * for the unrotated y length. + * Then to do the rotation, use + * x' = x costheta - y sintheta + * y' = y costheta + x sintheta + */ + segX = (length * ((double) n / (double)(nbulge + 1))) + / (STEPSIZE * staffscale); + segY = curve_p->bulgelist[n-1]; + coordlist_p[n].hsteps += (segX * costheta) - (segY * sintheta); + coordlist_p[n].vsteps += (segY * costheta) + (segX * sintheta); + } + + /* free the old coord list, which just had the endpoints */ + FREE(curve_p->coordlist); + + /* replace the old coordlist with the newly calculated one */ + curve_p->coordlist = coordlist_p; + curve_p->ncoord = 2 + nbulge; + + /* don't need bulgelist anymore, since it has been converted to + * regular curve. */ + FREE(curve_p->bulgelist); + curve_p->bulgelist = 0; + curve_p->nbulge = 0; +} diff --git a/mup/mup/lyrics.c b/mup/mup/lyrics.c new file mode 100644 index 0000000..badeec4 --- /dev/null +++ b/mup/mup/lyrics.c @@ -0,0 +1,1266 @@ + +/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions called by the parse phase to deal with lyrics */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + +/* information about a measure-worth of lyrics */ +struct LYRINFO { + short place; /* PL_ABOVE, etc */ + short vno; /* verse number */ + struct GRPSYL *gs_p; /* the lyrics themselves */ + struct LYRINFO *next; /* for linked list of other verses on the + * same staff */ +}; + +/* current font/size for each staff/verse/place combination */ +struct LYRFONTSIZE { + short staffno; + short verse; + char place; /* PL_ABOVE, etc */ + char font; + char size; + char all; /* YES if "above all" or "below all". + * In that case, the staffno is + * irrelevant */ + struct LYRFONTSIZE *next; /* linked list */ +}; + +/* we keep the font/size info independently for each staff/verse/place combo + * and carry it forward from measure to measure. Info is stored here */ +struct LYRFONTSIZE *Lyrfontsizeinfo_p [MAXSTAFFS + 1]; + +/* for each staff, keep a list of all the GRPSYL lyric lists that will be + * associated with that staff. */ +static struct LYRINFO *Lyr_tbl[MAXSTAFFS + 1]; + +/* need to keep a list of all verse numbers ever used, for setting Maxverses */ +static struct RANGELIST *Above_vnumbers_used; +static struct RANGELIST *Below_vnumbers_used; +static struct RANGELIST *Between_vnumbers_used; + +/* for auto-numbering verses, keep track of the last verse number used + * for each staff/place */ +static short Prev_verse_num[MAXSTAFFS+1][NUM_PLACE]; + +/* static function declarations */ +static void free_lyrinfo P((struct LYRINFO *lyrinfo_p)); +static void assoc_lyr2staff P((int staffno, int verse, struct GRPSYL *gs_p, + char *lyrstring, int all, int place)); +static struct LYRFONTSIZE *getlyrfontsize P((int staffno, int verse, + int place, int all)); +static void updlyrfontsize P((struct LYRFONTSIZE *lyrfontsize_p, + int font, int size)); +static char *next_syl P((char **sylstring_p, int *font_p, int *size_p, + short *position_p, int staffno)); +static void do_sylwidth P((char *lyrstring, float *wid_b4_syl_p, + float *wid_real_syl_p, float *wid_after_syl_p, + int compensating)); +static void count_verses P((struct RANGELIST *used_p)); +static void vno_used P((int vno)); + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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); + } + } +} + + +/* 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); + } + } +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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; + } + } +} + + + +/* 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; \ + } \ + } + + + +/* break a string of lyrics into individual syllables. The following + * characters are special: + * marks end of syllable + * 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: + * [ pre-item ] syllable [ post-item ] + * where + * is a 1-byte font identifier, FONT_TR, FONT_TI etc + * 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 and 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 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 and characters. + * If this text is to be used for syllable placement, the + * header will be 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)); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* user wants us to derive the lyrics time values from corresponding music + * time values. Find the proper list of GRPSYLs to copy time values from, + * and make a copy of that list, with field set properly for lyrics. */ + +struct GRPSYL * +derive_lyrtime() + +{ + struct MAINLL *mll_p; /* to find STAFF to derive from */ + struct GRPSYL *new_list_p; /* the list of derived time values */ + struct GRPSYL *gs_p; /* to walk through new_list_p */ + struct GRPSYL *ref_gs_p; /* to walk through the reference list-- + * the list we are deriving from */ + int staff, voice; /* which list of GRPSYLs to clone */ + + + /* If there are no staffs associated with these lyrics, then nothing + * to do here. We should have already printed an error elsewhere */ + if (Staffrange_p == (struct RANGELIST *) 0) { + return (struct GRPSYL *) 0; + } + + /* find the proper music GRPSYL from which to derive time values */ + staff = leadstaff(); + for (mll_p = Mainlltc_p; mll_p != (struct MAINLL *) 0; + mll_p = mll_p->prev) { + + /* if back up all the way to a bar, user hasn't defined the + * right staff's music input yet */ + if (mll_p->str == S_BAR) { + /* pretend we fell off top of list and break out. + * That way we only need one copy of error message code */ + mll_p = (struct MAINLL *) 0; + break; + } + if (mll_p->str == S_STAFF && mll_p->u.staff_p->staffno == staff) { + /* found the right staff data */ + break; + } + } + + if (mll_p == (struct MAINLL *) 0) { + l_yyerror(Curr_filename, yylineno, + "can't derive lyrics time values: staff %d music not defined yet", staff); + return (struct GRPSYL *) 0; + } + + /* usually use voice 1 of first staff specified. Only exceptions + * are if voice 1 is invisible or nonexistent or if explicitly below, + * and there is a visible voice 2, in which case voice 2 is used */ + voice = 0; + if ((vvpath(staff, 1, VISIBLE)->visible == NO || + mll_p->u.staff_p->groups_p[0] == (struct GRPSYL *) 0 + || Place == PL_BELOW) + && mll_p->u.staff_p->groups_p[1] != (struct GRPSYL *) 0 + && vvpath(staff, 2, VISIBLE)->visible == YES) { + voice = 1; + } + /* One more exception. If both voices are invisible, but we would + * have used voice 2 if it was visible, use voice 2. Otherwise + * if times would normally be derived from voice 2, but the + * whole staff is invisible, we could derive the wrong values. */ + if (vvpath(staff, 1, VISIBLE)->visible == NO && + vvpath(staff, 2, VISIBLE)->visible == NO && + mll_p->u.staff_p->groups_p[1] != (struct GRPSYL *) 0 && + Place == PL_BELOW) { + voice = 1; + } + + if (mll_p->u.staff_p->groups_p[voice] == (struct GRPSYL *) 0) { + l_yyerror(Curr_filename, yylineno, + "can't derive lyrics time values: staff %d voice %d music not defined yet", staff, voice + 1); + return (struct GRPSYL *) 0; + } + + new_list_p = clone_gs_list(mll_p->u.staff_p->groups_p[voice], NO); + + /* grace notes don't count in the time derivation, so remove + * them from the cloned list */ + for (gs_p = new_list_p; gs_p != (struct GRPSYL *) 0; gs_p = gs_p->next) { + if (gs_p->grpvalue == GV_ZERO) { + struct GRPSYL *to_free_p; + to_free_p = gs_p; + if (gs_p->prev == 0) { + new_list_p = gs_p->next; + } + else { + gs_p->prev->next = gs_p->next; + } + /* Note that there should always be a 'next' after + * a grace note, so this 'if' shouldn't really be + * necessary, but it is here as defensive code. */ + if (gs_p->next != 0) { + gs_p->next->prev = gs_p->prev; + } + FREE(to_free_p); + } + } + + /* go through cloned list, changing type to lyrics and changing rests + * in the music to spaces for the lyrics. Also deal with ties and slurs, + * since notes that are tied or slurred to will be treated like a + * space, since there is probably only a single syllable wanted. */ + for (gs_p = new_list_p, ref_gs_p = mll_p->u.staff_p->groups_p[voice]; + gs_p != (struct GRPSYL *) 0; + gs_p = gs_p->next, ref_gs_p = ref_gs_p->next) { + /* Skip graces in reference list. (There aren't any in + * the new list since we removed them above.) */ + while (ref_gs_p->grpvalue == GV_ZERO) { + ref_gs_p = ref_gs_p->next; + if (ref_gs_p == 0) { + /* should be impossible to get here */ + pfatal("unexpected null ref_gs_p in derive_lyrtime"); + } + } + + gs_p->grpsyl = GS_SYLLABLE; + if (ref_gs_p->grpcont == GC_REST) { + gs_p->grpcont = GC_SPACE; + } + else if (ref_gs_p->grpcont == GC_NOTES && ref_gs_p->nnotes > 0) { + /* if the top note of the chord is tied or slurred, + * or the entire chord is tied, + * make the following lyrics GRPSYL, if any, a space. */ + if ((ref_gs_p->notelist[0].tie == YES || + ref_gs_p->tie == YES || + ref_gs_p->notelist[0].nslurto > 0) && + gs_p->next != (struct GRPSYL *) 0) { + gs_p->next->grpcont = GC_SPACE; + } + } + } + + /* One more detail: if the first note was tied-to or slurred-to from + * the previous measure, we have to change that to a space. To do that, + * we call prevgrpsyl, but it expects the staffno and vno to be filled + * in on the GRPSYL passed to it, and we're so early in parsing that + * that hasn't happened yet. So first have to patch that up. Later on, + * all the GRPSYLs will get the staffno and vno filled in, but it won't + * hurt anything that we've already done this one here; they will + * just be overwritten with the same values. */ + ref_gs_p = mll_p->u.staff_p->groups_p[voice]; + ref_gs_p->staffno = mll_p->u.staff_p->staffno; + ref_gs_p->vno = voice + 1; + if ((gs_p = prevgrpsyl(ref_gs_p, &mll_p)) != (struct GRPSYL *) 0) { + if (gs_p->grpcont == GC_NOTES && gs_p->nnotes > 0) { + if (gs_p->notelist[0].tie == YES || + gs_p->tie == YES || + gs_p->notelist[0].nslurto > 0) { + new_list_p->grpcont = GC_SPACE; + } + } + } + + return (new_list_p); +} + diff --git a/mup/mup/macros.c b/mup/mup/macros.c new file mode 100644 index 0000000..d6d6f63 --- /dev/null +++ b/mup/mup/macros.c @@ -0,0 +1,1322 @@ + +/* Copyright (c) 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions to support Mup macros */ + +/* When a macro is defined, its text is copied to a file. When a macro is + * invoked, information about the current input file is pushed on a stack, + * and the macro text is read from the macro file. This file also has the + * code to handle include files. They are handled similarly. Info about the + * current file is pushed on a stack, and text is read from the included + * file. */ + +#include +#include +#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)); + + + + +/* 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 +} + + +/* 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); +} + + +#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 + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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"); + } +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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; +} + + +/* 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 +} + + +/* 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 +} + + +/* 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); + } +} + + +/* 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 +} + + +/* 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); + } +} + + +/* 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)++; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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 ); +} + + +/* For "preprocessor" option, similar to the C compiler option to + * just run the macro preprocessor, instead of the usual yacc-generated + * yyparse(), we have this function that simply writes tokens out. + */ + +void +preproc() +{ + while (yylex() != 0) { + /* In strings, the backslashes before any embedded quotes + * will have been swallowed, so we have to recreate them. */ + if (yytext[0] == '"') { + char *t; + putchar('"'); + for (t = yytext + 1; *t != '\0'; t++) { + if (*t == '"' && *(t+1) != '\0') { + putchar('\\'); + } + putchar(*t); + } + } + else { + printf("%s", yytext); + } + } +} diff --git a/mup/mup/main.c b/mup/mup/main.c new file mode 100644 index 0000000..77ca530 --- /dev/null +++ b/mup/mup/main.c @@ -0,0 +1,1441 @@ +static char Copyright[] = + "Copyright (c) 1995-2006 by Arkkra Enterprises.\nAll rights reserved.\n"; + +/* main for "Mup" music publication program */ + +/* + * Command line arguments + * -cN Combine strings of N measures of rest into multirests (N > 1) + * -C Include comments in macro-processed output (with -E) + * -dn turns on debug level n + * 1 = yydebug + * 2 = parse phase high level trace + * 4 = parse phase low level trace + * 8 = reserved + * 16 = placement phase high level trace + * 32 = placement phase low level trace + * 64 = reserved + * 128 = print contents of main linked list + * 256 = print phase high level trace + * 512 = print phase low level trace + * This is a bitmap, so multiple levels can be on at once + * -DMACRO[=def] define a macro + * -e errfile write error output into errfile instead of stderr + * -E just do macro expansion + * -f file write output to file instead of stdout + * -F write output to file, deriving the name + * -m midifile generate MIDI output into specified file instead of the + * usual PostScript output to stdout. + * -M create MIDI file, deriving the file name + * -olist print only pages given in list + * -pN start numbering pages at N instead of from 1 + * -r print registration form + * -slist print only the staffs in list + * -v print verion number and exit + * -xN,M extract just measures N through M. + * Negative values are relative to the end of the song. + * The comma and second number are optional. + * + * Expects zero or more input files. If no file specified, reads stdin + * + * Exit code is 0 on success, or the number of errors found, up to 254, + * or 255 for internal error. + */ + + +#ifdef __WATCOMC__ +#include +#endif +#ifdef Mac_BBEdit +#include +#include +#include +#define main _mup /* rename entry point to _mup */ +#endif +#include +#include +#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)); + + + + +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); +} + + +/* 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); + } +} + + +/* 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"); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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"); + } + } + } +} + + +/* 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"); + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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++; + } + } +} + + +#ifdef NEED_GETOPT +/* for non-unix or other systems that don't have a getopt() function, + * define one here. This is NOT a general purpose implementation of getopt(), + * but something good enough to work with Mup */ + +int optind = 1; +char *optarg; +static int argoffset; +int opttype P((int option, char *optstring)); + +#define NOARG 1 +#define WITHARG 2 +#define BADOPT 3 + +int +getopt(argc, argv, optstring) + +#ifdef __STDC__ +int argc; +char * const *argv; +const char *optstring; +#else +int argc; +char **argv; +char *optstring; +#endif + +{ + int option; + + + if (optind >= argc) { + return(EOF); + } + + if (argoffset == 0) { +#ifdef __DOS__ + if (argv[optind][argoffset] == '-' + || argv[optind][argoffset] == '/') { +#else + if (argv[optind][argoffset] == '-') { +#endif + argoffset = 1; + } + else { + return(EOF); + } + } + + /* determine if option is valid and if should have an argument */ + option = argv[optind][argoffset] & 0x7f; + switch (opttype(option, (char *) optstring)) { + case NOARG: + /* valid option without argument. Keep track of where + * to look for next option */ + if (argv[optind][++argoffset] == '\0') { + optind++; + argoffset = 0; + } + break; + + case WITHARG: + /* valid option with argument. */ + if (argv[optind][++argoffset] != '\0') { + /* argument immediately follows in same argv */ + optarg = &(argv[optind][argoffset]); + optind++; + } + else { + /* white space. argument must be in next argv */ + optind++; + if (optind >= argc) { + fprintf(stderr, "missing argument to %c%c option\n", Optch, option); + return('?'); + } + optarg = &(argv[optind][0]); + optind++; + } + argoffset = 0; + break; + + default: + fprintf(stderr, "invalid option %c%c\n", Optch, option); + option = '?'; + } + return(option); +} + + +/* look up option in optstring and return type of option */ + +int +opttype(option, optstring) + +int option; +char *optstring; + +{ + char *p; + + for (p = optstring; *p != '\0'; ) { + if (*p++ == option) { + return(*p == ':' ? WITHARG : NOARG); + } + if (*p == ':') { + p++; + } + } + return(BADOPT); +} + +#endif diff --git a/mup/mup/mainlist.c b/mup/mup/mainlist.c new file mode 100644 index 0000000..c3061c6 --- /dev/null +++ b/mup/mup/mainlist.c @@ -0,0 +1,170 @@ + +/* Copyright (c) 1995, 2001, 2003 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions for manipulating the main list of structs, allocating, + * inserting and deleting. */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + + + +/* allocate a new MAINLL struct and return a pointer to it */ + +struct MAINLL * +newMAINLLstruct(structtype, lineno) + +int structtype; /* what kind to allocate: S_SSV, S_BAR, etc */ +int lineno; /* input line number that caused this call */ + +{ + struct MAINLL *new_p; /* the newly allocated struct */ + + + debug(4, "newMAINLLstruct lineno=%d structtype=%d", lineno, structtype); + + /* allocate the struct */ + CALLOC(MAINLL, new_p, 1); + + /* fill in the type to say which union member will be used */ + new_p->str = (short) structtype; + + /* initialize link pointers to point nowhere */ + new_p->next = new_p->prev = (struct MAINLL *) 0; + + + /* now allocate and initialize the proper S_* struct */ + switch (structtype) { + + case S_SSV: + CALLOC(SSV, new_p->u.ssv_p, 1); + break; + + case S_STAFF: + CALLOC(STAFF, new_p->u.staff_p, 1); + break; + + case S_BAR: + CALLOC(BAR, new_p->u.bar_p, 1); + break; + + case S_LINE: + CALLOC(LINE, new_p->u.line_p, 1); + break; + + case S_CURVE: + CALLOC(CURVE, new_p->u.curve_p, 1); + break; + + case S_PRHEAD: + CALLOC(PRHEAD, new_p->u.prhead_p, 1); + break; + + case S_CHHEAD: + CALLOC(CHHEAD, new_p->u.chhead_p, 1); + break; + + case S_FEED: + CALLOC(FEED, new_p->u.feed_p, 1); + /* negative value for margin means use score parameter */ + new_p->u.feed_p->rightmargin = -1.0; + new_p->u.feed_p->leftmargin = -1.0; + break; + + case S_BLOCKHEAD: + CALLOC(BLOCKHEAD, new_p->u.blockhead_p, 1); + break; + + case S_CLEFSIG: + CALLOC(CLEFSIG, new_p->u.clefsig_p, 1); + break; + + default: + pfatal("unknown structure type %d requested", structtype); + break; + } + + /* remember the user's input file and line number, + * so in case we have to print an error message later, + * we know which line number to print */ + new_p->inputlineno = (short) lineno; + new_p->inputfile = Curr_filename; + + /* return the newly allocated struct */ + return(new_p); +} + + +/* 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; + } +} + + +/* unlink a MAINLL struct from the main list + * (probably for re-inserting elsewhere). The struct is not freed. */ + +void +unlinkMAINLL(which_p) + +struct MAINLL *which_p; /* the one to unlink */ + +{ + if (which_p->prev != (struct MAINLL *) 0) { + which_p->prev->next = which_p->next; + } + if (which_p->next != (struct MAINLL *) 0) { + which_p->next->prev = which_p->prev; + } + + /* if this happened to be the tail cell, need to fix up */ + if (Mainlltc_p == which_p) { + Mainlltc_p = which_p->prev; + } + + /* likewise for head cell */ + if (Mainllhc_p == which_p) { + Mainllhc_p = which_p->next; + } +} diff --git a/mup/mup/map.c b/mup/mup/map.c new file mode 100644 index 0000000..2ec577a --- /dev/null +++ b/mup/mup/map.c @@ -0,0 +1,1242 @@ + +/* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* This file contains functions for mapping input to individual voices. + * The user can give a single line of input + * that gets expanded into several voices. + * There are two flavors of this: + * voice-at-a-time input and chord-at-a-time input. + * For the former, the GRPSYL list just gets cloned and altered as needed. + * For the latter, brand new GRPSYL lists are created + * by distributing individual notes from the user's input. + * For any given staff/voice, only one type of input can be used per measure. + * For chord-at-a-time, a given staff/voice can appear more than once + * within a single input line, but not on multiple input lines per measure. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* mark whether we mapped user data, only mapped implicit spaces, or nothing */ +#define MAPPED_NOTHING (0) +#define MAPPED_IMPLICIT (1) +#define MAPPED_EXPLICIT (2) + +/* This struct tells how to map one note for chord-at-a-time input, + * i.e., which staff/voice combinations it should be mapped to. + * Each map item in input (semicolon-separated) + * gets saved in one of these. */ +struct NOTEMAP { + struct SVRANGELIST *svlist_p; /* staffs/voices to map this note to */ + struct NOTEMAP *next; /* linked list */ +}; + +/* This struct gives the mapping for a particular number of notes. + * The set of things inside a pair of brackets gets saved in one of these. */ +struct MAP { + int num_entries; /* how many item in list */ + struct NOTEMAP *notemap_p; /* one entry for each note in chord */ + struct MAP *next; /* linked list */ +}; + +/* This points to the list of maps, or to 0 if doing voice-at-a-time input */ +static struct MAP *Map_p; +/* This points to where to add to the map list */ +static struct MAP **End_map_p_p = &Map_p; + +/* This is where to insert the next NOTEMAP */ +static struct NOTEMAP **Note_p_p; + +/* It is handy to be able to treat both input styles identically + * as much as possible. So for when input is voice-at-a-time, it can be handy + * to have a MAP that just points to Svrangelist_p. These two structs are + * used for that purpose. Since the value of Svrangelist_p changes + * at runtime, we have to set Sv_notemap->svlist_p each time + * before these are used. */ +static struct NOTEMAP Sv_notemap = { + (struct SVRANGELIST *) 0, (struct NOTEMAP *) 0 +}; +static struct MAP Voice_at_a_time_map = { + 1, &Sv_notemap, (struct MAP *) 0 +}; + +/* Keep track of which input style was used */ +static short Input_style[MAXSTAFFS][MAXVOICES]; + +static int map_groups P((void)); +static void clean_map_data P((void)); +static void free_maps P((struct MAP *map_p)); +static void free_notemaps P((struct NOTEMAP *notemap_p)); +static struct NOTEMAP *find_notemap P((int num_notes)); +static void map1note P((struct GRPSYL *from_gs_p, int n, int staff, int voice, + short allocated[MAXSTAFFS][MAXVOICES])); +static void do_link_groups P((void)); +static void link_a_grouplist P((int staffno, int vno, int copies)); +static void convert_rest_space P((struct GRPSYL *grpsyl_p, int staffno, int vno)); +static void conv_grpsyl P((struct GRPSYL *grpsyl_p, int staffno, int vno)); +static void mult_def P((int staff, int voice)); + + +/* 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; + } + } +} + + +/* 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]); +} + + +/* 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(); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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(); +} + + +/* 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++); + } + } + } + } + } +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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"); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* print error message for multiply defined voice */ + +static void +mult_def(staff, voice) + +int staff; +int voice; + +{ + l_yyerror(Curr_filename, yylineno, + "staff %d voice %d multiply defined (first defined on line %d)", + staff, voice, + Staffmap_p[staff]->u.staff_p->groups_p[voice-1]->inputlineno); +} diff --git a/mup/mup/midi.c b/mup/mup/midi.c new file mode 100644 index 0000000..a425c37 --- /dev/null +++ b/mup/mup/midi.c @@ -0,0 +1,2804 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* generate a MIDI file from the Mup internal representation */ + +#include +#include +#include +#ifdef __WATCOMC__ +#include +#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)); + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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]); +} + + +/* 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; + } +} + + +/* 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; + } +} + + +/* 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; + } + } +} + + +/* 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)); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); + } + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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; +} + + +/* 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; +} + + +/* 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; +} + + +/* 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; + } + } + } + } + } +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* return YES if specified staff/voice is used somewhere in the piece */ + +int +voice_used(staffno, vno) + +int staffno; +int vno; + +{ + return (Voice2track_map [staffno] [vno] != 0 ? YES : NO); +} diff --git a/mup/mup/midiutil.c b/mup/mup/midiutil.c new file mode 100644 index 0000000..85054c4 --- /dev/null +++ b/mup/mup/midiutil.c @@ -0,0 +1,1460 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + +/* utility functions for creating MIDI output from Mup input. These functions + * are split out into this file to keep midi.c from being so huge */ + +#ifdef __WATCOMC__ +#include +#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)); + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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]); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); + } + } + } +} + + +/* 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; + } + } +} + + +/* 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; + } +} + + +/* 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; +} + + +/* 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); + } + } +} + + +/* 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"); + } + } + } +} + + +/* 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; + } + } + } +} + + +/* 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; + } + } + } +} + + +/* 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); + } + } + } +} + + +/* 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; +} + + +/* Given the argument to a MIDI "parameter" command, extract and return + * (via pointers) the two numbers (the parameter number and its value). + * If successful, returns YES, else prints a warning and returns NO. + * If NO is returned, the pointed to return values are not fill in. + */ + +int +get_param(arg, inputfile, inputlineno, parmnum_p, parmval_p) + +char *arg; /* the argument part after "parameter=" */ +char *inputfile; /* for error messages */ +int inputlineno; /* for error messages */ +int *parmnum_p; /* parameter number is returned here */ +int *parmval_p; /* parameter value is returned here */ + +{ + int parmnum; /* parameter number */ + int parmval; /* parameter value */ + char *parm_p; /* pointer to current place in string */ + + + /* extract first number */ + parmnum = strtol(arg, &parm_p, 10); + if (parm_p == arg) { + l_warning(inputfile, inputlineno, + "parameter requires two values"); + return(NO); + } + /* skip white space, if any */ + while (*parm_p == ' ' || *parm_p == '\t') { + parm_p++; + } + /* next we better have a comma */ + if (*parm_p != ','){ + l_warning(inputfile, inputlineno, + "parameter is missing required comma"); + return(NO); + } + /* extract the second number */ + arg = parm_p + 1; + parmval = strtol(arg, &parm_p, 10); + if (parm_p == arg) { + l_warning(inputfile, inputlineno, + "parameter is missing second value"); + return(NO); + } + /* verify both numbers are within range */ + if ((l_rangecheck(parmnum, 0, 127, "parameter number", + inputfile, inputlineno) == YES) && + (l_rangecheck(parmval, 0, 127, "parameter value", + inputfile, inputlineno) == YES)) { + *parmnum_p = parmnum; + *parmval_p = parmval; + return(YES); + } + return(NO); +} diff --git a/mup/mup/mkchords.c b/mup/mup/mkchords.c new file mode 100644 index 0000000..6919e60 --- /dev/null +++ b/mup/mup/mkchords.c @@ -0,0 +1,1767 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 2002, 2003, 2004, 2006 + * by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: mkchords.c + * + * Description: This file contains functions for creating CHORD linked lists + * and erasing invisible voices. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + +static void swingmidi P((void)); +static struct GRPSYL *voicevis P((struct GRPSYL *gs_p)); +static void combine_voices P((void)); +static void chkhand1 P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p)); +static int chk2groups P((struct GRPSYL *hi_p, struct GRPSYL *lo_p, + struct MAINLL *mll_p, int qual)); +static void chkhand2 P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p)); +static int chk2neighbors P((struct GRPSYL *first_p, struct GRPSYL *second_p, + struct GRPSYL *gs1_p, struct MAINLL *mll_p)); +static void dohand P((struct GRPSYL *gs1_p, struct MAINLL *staffmll_p)); +static void comb2groups P((struct GRPSYL *dest_p, struct GRPSYL *src_p, + struct MAINLL *mll_p)); +static void addsrc2dest P((struct GRPSYL *dest_p, struct GRPSYL *src_p)); +static int setgrpptrs P((struct GRPSYL *gs1_p, struct GRPSYL *v_p[])); +static int hastieslur P((struct GRPSYL *gs_p)); + +/* + * 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(); + } +} + +/* + * 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; + } + } + } +} + +/* + * 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 */ +} + +/* + * 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; + } + } + } + } + } +} + +/* + * 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; + } +} + +/* + * 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 */ +} + +/* + * 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; + } + } + } +} + +/* + * 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); +} + +/* + * 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); + } + } +} + +/* + * 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? */ +} + +/* + * 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; +} + +/* + * 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); +} + +/* + * Name: hastieslur() + * + * Abstract: Is this group tied/slurred/bent to the next? + * + * Returns: YES or NO + * + * Description: This function checks whether there are any ties/slurs/bends to + * the next group. If the given group doesn't exist, the answer + * is NO. + */ + +static int +hastieslur(gs_p) + +struct GRPSYL *gs_p; /* group to check */ + +{ + int idx; /* index into note list */ + + + /* if there's no group, it isn't tied/slurred */ + if (gs_p == 0) { + return (NO); + } + + /* check group tie */ + if (gs_p->tie == YES) { + return (YES); + } + + /* check note ties and slurs (bends are covered by slurs) */ + for (idx = 0; idx < gs_p->nnotes; idx++) { + if (gs_p->notelist[idx].tie == YES || + gs_p->notelist[idx].nslurto != 0) { + return (YES); + } + } + + return (NO); +} diff --git a/mup/mup/muschar.h b/mup/mup/muschar.h new file mode 100644 index 0000000..b32dd5b --- /dev/null +++ b/mup/mup/muschar.h @@ -0,0 +1,113 @@ + +/* Copyright (c) 1995, 1999, 2000, 2004 by Arkkra Enterprises */ +/* All rights reserved */ + +/* + * Define the list of all the special music symbols. + */ + +/* The following set of symbols is in font FONT_MUSIC. + * Mapping between name and number is done via Mus_char_table[0][]. + */ +#define C_GCLEF (32) /* G clef (treble clef) */ +#define C_FCLEF (33) /* F clef (bass clef) */ +#define C_CCLEF (34) /* C clef (alto, tenor, etc. clef) */ +#define C_DBLWHOLE (35) /* double whole note */ +#define C_1N (36) /* whole note */ +#define C_2N (37) /* half note head */ +#define C_4N (38) /* quarter (and shorter) note head */ +#define C_UPFLAG (39) /* upward flag */ +#define C_DNFLAG (40) /* downward flag */ +#define C_QWHREST (41) /* quad rest */ +#define C_DWHREST (42) /* double whole rest */ +#define C_1REST (43) /* whole rest */ +#define C_2REST (44) /* half rest */ +#define C_4REST (45) /* quarter rest */ +#define C_8REST (46) /* eighth rest */ +#define C_16REST (47) /* sixteenth rest */ +#define C_32REST (48) /* thirty-second rest */ +#define C_64REST (49) /* sixty-fourth rest */ +#define C_128REST (50) /* 128th rest */ +#define C_256REST (51) /* 256th rest */ +#define C_LL1REST (52) /* legerline-less version of whole rest */ +#define C_LL2REST (53) /* legerline-less version of half rest */ +#define C_DOT (54) /* dot, as for after a note */ +#define C_NAT (55) /* natural sign (n) */ +#define C_SHARP (56) /* sharp sign (#) */ +#define C_FLAT (57) /* flat sign (&) */ +#define C_DBLSHARP (58) /* double sharp */ +#define C_DBLFLAT (59) /* double flat */ +#define C_XNOTE (60) /* X-shaped note head */ +#define C_DWHDIAMOND (61) /* double-whole diamond shaped note */ +#define C_DIAMOND (62) /* diamond-shaped note head */ +#define C_FILLDIAMOND (63) /* filled diamond note head */ +#define C_UP2N (64) /* half note with stem up */ +#define C_DN2N (65) /* half note with stem down */ +#define C_UP4N (66) /* quarter note with stem up */ +#define C_DN4N (67) /* quarter note with stem down */ +#define C_COM (68) /* common time */ +#define C_CUT (69) /* cut time */ +#define C_BEGPED (70) /* begin pedal */ +#define C_PEDAL (71) /* pedal up/down */ +#define C_ENDPED (72) /* end pedal */ +#define C_DNBOW (73) /* down bow */ +#define C_UPBOW (74) /* up bow */ +#define C_WEDGE (75) /* wedge mark */ +#define C_UWEDGE (76) /* upside-down wedge */ +#define C_FERM (77) /* fermata */ +#define C_UFERM (78) /* upside-down fermata */ +#define C_SIGN (79) /* for D.S. */ +#define C_CODA (80) /* the + over circle for jumping to coda */ +#define C_MOR (81) /* mordent */ +#define C_INVMOR (82) /* inverted mordent */ +#define C_TURN (83) /* "turn" ornament */ +#define C_INVTURN (84) /* inverted turn */ +#define C_ACC_GT (85) /* accent that looks like > */ +#define C_ACC_HAT (86) /* accent that looks like ^ */ +#define C_ACC_UHAT (87) /* upside down hat accent */ +#define C_TR (88) /* trill */ +#define C_LEG (89) /* legato mark */ +#define C_RR (90) /* railroad tracks */ +#define C_DIM (91) /* diminished (small circle) */ +#define C_HALFDIM (92) /* half diminished (small circle with slash) */ +#define C_TRIANGLE (93) /* triangle, as for a major 7th chord */ +#define C_MEASRPT (94) /* measure repeat */ +#define C_COPYRIGHT (95) /* c in circle */ +#define C_UP8N (96) /* 1/8 note with stem up */ +#define C_DN8N (97) /* 1/8 note with stem down */ +#define C_UP16N (98) /* 1/16 note with stem up */ +#define C_DN16N (99) /* 1/16 note with stem down */ +#define C_UP32N (100) /* 1/32 note with stem up */ +#define C_DN32N (101) /* 1/32 note with stem down */ +#define C_UP64N (102) /* 1/64 note with stem up */ +#define C_DN64N (103) /* 1/64 note with stem down */ +#define C_UP128N (104) /* 1/128 note with stem up */ +#define C_DN128N (105) /* 1/128 note with stem down */ +#define C_UP256N (106) /* 1/256 note with stem up */ +#define C_DN256N (107) /* 1/256 note with stem down */ + +/* The following set of symbols is in font FONT_MUSIC2. + * Mapping between name and number is done via Mus_char_table[1][]. + */ +#define C_DWHRIGHTTRIANGLE (32) /* double whole right triangle */ +#define C_RIGHTTRIANGLE (33) /* hollow right triangle */ +#define C_FILLRIGHTTRIANGLE (34) /* filled right triangle */ +#define C_UDWHRIGHTTRIANGLE (35) /* upside down double whole right tri*/ +#define C_URIGHTTRIANGLE (36) /* upside down hollow right triangle */ +#define C_UFILLRIGHTTRIANGLE (37) /* upside down filled right triangle */ +#define C_DWHRECTANGLE (38) /* double whole rectangle */ +#define C_RECTANGLE (39) /* hollow rectangle */ +#define C_FILLRECTANGLE (40) /* filled rectangle */ +#define C_DWHISOSTRIANGLE (41) /* double whole isosceles triangle */ +#define C_ISOSTRIANGLE (42) /* hollow isosceles triangle */ +#define C_FILLISOSTRIANGLE (43) /* filled isosceles triangle */ +#define C_DWHPIEWEDGE (44) /* double whole pie wedge */ +#define C_PIEWEDGE (45) /* hollow pie wedge */ +#define C_FILLPIEWEDGE (46) /* filled pie wedge */ +#define C_DWHSEMICIRCLE (47) /* double whole semicircle */ +#define C_SEMICIRCLE (48) /* hollow semicircle */ +#define C_FILLSEMICIRCLE (49) /* filled semicircle */ +#define C_DWHSLASHHEAD (50) /* double whole slash note head */ +#define C_SLASHHEAD (51) /* hollow slash note head */ +#define C_FILLSLASHHEAD (52) /* filled slash note head */ +#define C_BLANKHEAD (53) /* blank note head */ diff --git a/mup/mup/muschtbl.c b/mup/mup/muschtbl.c new file mode 100644 index 0000000..320805e --- /dev/null +++ b/mup/mup/muschtbl.c @@ -0,0 +1,113 @@ +/* Copyright (c) 1995, 1999, 2000, 2004 by Arkkra Enterprises */ +/* All rights reserved */ + +/* Machine-generated mapping of music char names to code numbers */ + +#include "defines.h" +#include "structs.h" + +struct SPECCHAR Mus_char_table[NUM_MFONTS][CHARS_IN_FONT+1] = { + { + { "128rest", C_128REST }, + { "16rest", C_16REST }, + { "1n", C_1N }, + { "1rest", C_1REST }, + { "256rest", C_256REST }, + { "2n", C_2N }, + { "2rest", C_2REST }, + { "32rest", C_32REST }, + { "4n", C_4N }, + { "4rest", C_4REST }, + { "64rest", C_64REST }, + { "8rest", C_8REST }, + { "acc_gt", C_ACC_GT }, + { "acc_hat", C_ACC_HAT }, + { "acc_uhat", C_ACC_UHAT }, + { "begped", C_BEGPED }, + { "cclef", C_CCLEF }, + { "coda", C_CODA }, + { "com", C_COM }, + { "copyright", C_COPYRIGHT }, + { "cut", C_CUT }, + { "dblflat", C_DBLFLAT }, + { "dblsharp", C_DBLSHARP }, + { "dblwhole", C_DBLWHOLE }, + { "diamond", C_DIAMOND }, + { "dim", C_DIM }, + { "dn128n", C_DN128N }, + { "dn16n", C_DN16N }, + { "dn256n", C_DN256N }, + { "dn2n", C_DN2N }, + { "dn32n", C_DN32N }, + { "dn4n", C_DN4N }, + { "dn64n", C_DN64N }, + { "dn8n", C_DN8N }, + { "dnbow", C_DNBOW }, + { "dnflag", C_DNFLAG }, + { "dot", C_DOT }, + { "dwhdiamond", C_DWHDIAMOND }, + { "dwhrest", C_DWHREST }, + { "endped", C_ENDPED }, + { "fclef", C_FCLEF }, + { "ferm", C_FERM }, + { "filldiamond", C_FILLDIAMOND }, + { "flat", C_FLAT }, + { "gclef", C_GCLEF }, + { "halfdim", C_HALFDIM }, + { "invmor", C_INVMOR }, + { "invturn", C_INVTURN }, + { "leg", C_LEG }, + { "ll1rest", C_LL1REST }, + { "ll2rest", C_LL2REST }, + { "measrpt", C_MEASRPT }, + { "mor", C_MOR }, + { "nat", C_NAT }, + { "pedal", C_PEDAL }, + { "qwhrest", C_QWHREST }, + { "rr", C_RR }, + { "sharp", C_SHARP }, + { "sign", C_SIGN }, + { "tr", C_TR }, + { "triangle", C_TRIANGLE }, + { "turn", C_TURN }, + { "uferm", C_UFERM }, + { "up128n", C_UP128N }, + { "up16n", C_UP16N }, + { "up256n", C_UP256N }, + { "up2n", C_UP2N }, + { "up32n", C_UP32N }, + { "up4n", C_UP4N }, + { "up64n", C_UP64N }, + { "up8n", C_UP8N }, + { "upbow", C_UPBOW }, + { "upflag", C_UPFLAG }, + { "uwedge", C_UWEDGE }, + { "wedge", C_WEDGE }, + { "xnote", C_XNOTE }, + { (char *) 0, 0 } + }, { + { "blankhead", C_BLANKHEAD }, + { "dwhisostriangle", C_DWHISOSTRIANGLE }, + { "dwhpiewedge", C_DWHPIEWEDGE }, + { "dwhrectangle", C_DWHRECTANGLE }, + { "dwhrighttriangle", C_DWHRIGHTTRIANGLE }, + { "dwhsemicircle", C_DWHSEMICIRCLE }, + { "dwhslashhead", C_DWHSLASHHEAD }, + { "fillisostriangle", C_FILLISOSTRIANGLE }, + { "fillpiewedge", C_FILLPIEWEDGE }, + { "fillrectangle", C_FILLRECTANGLE }, + { "fillrighttriangle", C_FILLRIGHTTRIANGLE }, + { "fillsemicircle", C_FILLSEMICIRCLE }, + { "fillslashhead", C_FILLSLASHHEAD }, + { "isostriangle", C_ISOSTRIANGLE }, + { "piewedge", C_PIEWEDGE }, + { "rectangle", C_RECTANGLE }, + { "righttriangle", C_RIGHTTRIANGLE }, + { "semicircle", C_SEMICIRCLE }, + { "slashhead", C_SLASHHEAD }, + { "udwhrighttriangle", C_UDWHRIGHTTRIANGLE }, + { "ufillrighttriangle", C_UFILLRIGHTTRIANGLE }, + { "urighttriangle", C_URIGHTTRIANGLE }, + { (char *) 0, 0 } + } +}; diff --git a/mup/mup/nxtstrch.c b/mup/mup/nxtstrch.c new file mode 100644 index 0000000..44be372 --- /dev/null +++ b/mup/mup/nxtstrch.c @@ -0,0 +1,938 @@ +/* Copyright (c) 1999, 2000, 2002, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + +/* Functions related to walking through strings, to get each character + * in turn, along with any font/size changes and horizontal/vertical + * motions that should be done before printing that character. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + +/* when entering pile, adjust size by PILE_A / PILE_B and when + * exiting pile, adjust by the recipocal of that. */ +#define PILE_A 65 +#define PILE_B 100 + + +/* This structure contains information about one line in a set of lines + * that are piled on top of one another. This might be used for figured + * bass or superscript/subscript or things like that. */ +struct PILED_LINE { + char *text; /* points to start of piled line */ + short align_offset; /* where the alignment is, relative to text */ + short length; /* bytes in this line */ + short last_char_offset; /* where the last character is */ + short last_digit_offset;/* where the last digit is */ + float width_left_of_align; /* width for this line */ + float width_right_of_align; + struct PILED_LINE *next;/* the next line in the pile */ +}; + +/* This keep track of an entire piled section of a string */ +struct PILED { + float curr_x, curr_y; /* where we are now, relative to pile start */ + struct PILED_LINE *lines_p; /* list of lines in pile */ + struct PILED_LINE *curr_line_p; /* which piled line we're processing */ + short curr_offset; /* offset into curr_line_p->text */ + float width_left_of_align; /* width of the entire pile */ + float width_right_of_align; + short orig_font; /* font coming into the pile */ + short orig_size; /* size coming into the pile */ + short new_size; /* size at beginning of pile */ + char *pile_end; /* last character of pile */ +}; + +/* One of these structs is passed to get_piled() with the current + * font and size filled in. If we are in piled mode, it will return 1 and + * will have filled in all the field. Otherwise it will return 0. + */ + +struct PILE_INFO { + char font; + char size; + char ch; /* the next character in the pile, or \0 if + * this only indicates motion */ + double hor; /* how much to adjust before printing ch */ + double vert; /* how much to adjust before printing ch */ +}; + +/* When a backspace is returned, this keeps track of its width, to + * potentially be returned via backsp_width() */ +static int Backspace_dist; + +/* This is all the info about the piled section we are currently processing. + * We only deal with one pile at a time, so a single static structure + * meets our needs. */ +static struct PILED Pile_info; + +static void begin_pile P((struct PILE_INFO *pile_info_p)); +static char *prep_pile P((char *string, struct PILE_INFO *pile_info_p)); +static int get_piled P((struct PILE_INFO *pile_info_p)); +static double vert_distance P((int vert_arg, int font, int size)); + + +/* 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); +} + + +/* 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'; +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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; + } +} + + +/* 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)); +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* given where a pile begins and the font/size at that point, return the + * width from the beginning to the pile to the alignment point of the pile. */ + +double +align_distance(string, font, size) + +char *string; /* pile starts here */ +int font; +int size; + +{ + struct PILE_INFO pile_info; + + pile_info.font = font; + pile_info.size = size; + (void) prep_pile(string, &pile_info); + return(Pile_info.width_left_of_align); +} diff --git a/mup/mup/parstssv.c b/mup/mup/parstssv.c new file mode 100644 index 0000000..bf79df2 --- /dev/null +++ b/mup/mup/parstssv.c @@ -0,0 +1,297 @@ +/* Copyright (c) 2003 by Arkkra Enterprises. */ +/* All rights reserved. */ + +/* This file contains parse-time functions related to TIMEDSSVs. + * These are used to specify mid-measure parameter changes, + * like change of clef. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* Mid-measure SSV's eventually get attached to the BAR, but we need + * to point to the list temporarily while the BAR doesn't exist yet. */ +static struct TIMEDSSV *Timedssv_p; + +/* When there is more than one TIMEDSSV at the same moment in time, + * we use user input order, so we add items to the end of the list. + * This keeps track of where to put the next one. + */ +static struct TIMEDSSV **Timed_tail_p_p = &Timedssv_p; + +static struct TIMEDSSV *tssv_new P((int context)); + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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"); + } + } + } + } +} + + + +/* 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); + } + } + } +} + + +/* Sort the current TIMEDSSV list by time and return pointer to the head + * of the sorted list. The sorting is done by time. When there is a tie + * things are put in user input order. Also re-inits for the next measure. + */ + +struct TIMEDSSV * +tssv_sort() + +{ + struct TIMEDSSV *ret; /* return value is pointer to sorted list */ + short moved; /* YES if something was moved during sort */ + + /* Most of the time, the list will be empty. */ + if (Timedssv_p == 0) { + return(0); + } + + /* Sort in time order. + * The list is almost certain to be very short, + * so sort needn't be very efficient. So we check pairs + * and swap ones that are backwards. */ + do { + struct TIMEDSSV **ts_p_p; + struct TIMEDSSV *tmp_ts_p; + + moved = NO; + for (ts_p_p = &Timedssv_p; (*ts_p_p)->next != 0; + ts_p_p = &((*ts_p_p)->next) ) { + if ( GT( (*ts_p_p)->time_off, (*ts_p_p)->next->time_off ) ) { + /* Wrong order. Swap them */ + tmp_ts_p = (*ts_p_p)->next; + (*ts_p_p)->next = (*ts_p_p)->next->next; + tmp_ts_p->next = *ts_p_p; + *ts_p_p = tmp_ts_p; + moved = YES; + break; + } + } + } while (moved == YES); + ret = Timedssv_p; + + /* re-init for next measure */ + Timedssv_p = 0; + Timed_tail_p_p = &(Timedssv_p); + return(ret); +} diff --git a/mup/mup/parstuff.c b/mup/mup/parstuff.c new file mode 100644 index 0000000..dff001d --- /dev/null +++ b/mup/mup/parstuff.c @@ -0,0 +1,1501 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004 by Arkkra Enterprises */ +/* All rights reserved */ + +/* parser functions related to STUFF */ + + +#include +#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)); + + +/* 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"); +} + + +/* return current stuff type */ + +int +get_stuff_type() + +{ + return(Curr_stuff_type); +} + + +/* 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; +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); + } + } +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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(); +} + + +/* 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; +} + + +/* 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; + } +} + + +/* 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; +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); + } +} + + +/* 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; + } +} + + +/* 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); + } + } +} + + +/* 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; + } + } + } +} + + +/* Translate STUFF text modifier to a printable string. */ + +char * +stuff_modifier(modifier) + +int modifier; + +{ + switch (modifier) { + + case TM_CHORD: + return("chord"); + case TM_ANALYSIS: + return("analysis"); + case TM_FIGBASS: + return("figbass"); + case TM_DYN: + return("dyn"); + case TM_NONE: + return("(no modifier)"); + default: + return("(invalid modifier)"); + } +} diff --git a/mup/mup/phrase.c b/mup/mup/phrase.c new file mode 100644 index 0000000..9cd6fa6 --- /dev/null +++ b/mup/mup/phrase.c @@ -0,0 +1,2148 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions to determine the curves that make up phrase marks, + * ties and slurs. */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* distance to the top/bottom of a V-shape (indicating a bend) relative to + * the line connecting the endpoints of the V */ +#define V_HEIGHT (2.7 * Stepsize) + +/* How much bulge to allow in curves. There are three slightly different + * approaches that are tried, each succeeding approach allows more bulge + * in a more despearate attempt to get a reasonable curve. */ +#define MINBULGE (1.2) +#define MAXBULGE (2.1) +#define MIN2BULGE (1.4) +#define MAX2BULGE (4.1) +#define MIN3BULGE (1.8) +#define MAX3BULGE (5.6) + +/* We'd normally want curves to begin and end (in the x direction) exactly in + * the middle of their note. But if one curve ends and another begins on + * the same note, the curve endpoints would collide, which could look bad. + * So we always offset the endpoints by a tiny amount (ends end a little + * west of center, and beginnings begin a little east) so they don't touch. + * This is the amount they are shifted from center. + */ +#define XOFFSET4CURVE (0.75 * Stdpad) + +/* Curves must be at least this far away from notes */ +#define CLEARANCE (3.0 * Stdpad) + +/* try_bulge() is called lots of times in a row with mostly the same values, + * and it needs lots of values, so it is convenient to put them in a struct, + * and just pass a pointer to it */ +struct TRYBULGE { + struct MAINLL *mll_p; /* STUFF hangs off here */ + struct GRPSYL *begin_gs_p; /* group at left end of curve */ + struct GRPSYL *end_gs_p; /* group at right end of curve */ + int place; /* PL_* */ + struct CRVLIST *curvelist_p; /* points to beginning of curve */ + struct CRVLIST *endlist_p; /* points to end of curve */ + double xlen; /* distance to midpoint */ + double ylen; /* how much bulge to add */ + double sintheta; /* for rotation from horizontal */ + double costheta; + double minbulge; /* first bulge factor to try */ + double maxbulge; /* last bulge to try before giving up */ + int leftcount; /* value is returned here. Count of + * how many "stick-outs" are near the + * left end of the curve */ + int rightcount; /* similar for right end */ +}; + +static int nowhere_slide P((struct STUFF *stuff_p)); +static void do_nowhere P((struct STUFF *stuff_p, double x1, double y1, + double x2, double y2)); +static void curve_points P((struct MAINLL *mll_p, struct STUFF *stuff_p, + int is_phrase)); +static double inner_adj P((struct GRPSYL *gs_p, struct NOTE *note_p, + double y_adj, int place)); +static double stick_out P((struct TRYBULGE *info_p)); +static double try_bulge P((struct TRYBULGE *info_p)); +static double tieslurx P((struct GRPSYL *gs_p, struct NOTE *note_p, int place)); +static struct MAINLL *next_staff P((int staff, struct MAINLL *mll_p)); +static void redo_steep P((struct CRVLIST *first_p, struct CRVLIST *last_p, + int place)); +static void final_touches P((struct MAINLL *mll_p, struct GRPSYL *begin_gs_p, + struct GRPSYL *end_gs_p, struct CRVLIST *crvlist_p, int place)); +static double eff_tupext P((struct GRPSYL * gs_p, struct STAFF *staff_p, int side)); +static int bulge_direction P((struct MAINLL *mll_p, struct GRPSYL *gs1_p, + int note_index, int curveno)); + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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; +} + + +/* 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); + } +} + + +/* 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; +} + + +/* 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"); +} + + +/* + * 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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); +} + +/* + * 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; + } + } +} + + +/* 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); + } + } +} + + +/* 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); +} + + +/* determine correct bend direction for curve, return UP or DOWN */ + +static int +bulge_direction(mll_p, gs1_p, note_index, curveno) + +struct MAINLL *mll_p; /* main list struct pointing to gs1_p */ +struct GRPSYL *gs1_p; /* curve will be from note in gs1_p to note in gs2_p */ +int note_index; /* which note in first group to tie */ +int curveno; /* index into slurto, or -1 for a tie */ + +{ + struct GRPSYL *gs_p; + RATIONAL vtime1, vtime2; /* beginning and ending time of group */ + int othervoice; /* array index of other voice */ + + + /* If user explicitly set a bend direction, use that */ + if (curveno == -1 && gs1_p->notelist[note_index].tiedir != UNKNOWN) { + return(gs1_p->notelist[note_index].tiedir); + } + else if (curveno >= 0 && gs1_p->notelist[note_index] + .slurtolist[curveno].slurdir != UNKNOWN) { + return(gs1_p->notelist[note_index].slurtolist[curveno].slurdir); + } + + /* If there are 2 voices on the staff, bend is toward the stem */ + /* However, if the other voice is all spaces, pretend there is only + * one voice */ + if ( (mll_p->u.staff_p->groups_p[0] != (struct GRPSYL *) 0) + && (mll_p->u.staff_p->groups_p[1] + != (struct GRPSYL *) 0) ) { + + /* there are 2 voices */ + + /* calculate begin and end time of tied group */ + vtime1 = Zero; + for (gs_p = mll_p->u.staff_p->groups_p[gs1_p->vno - 1]; + gs_p != gs1_p; gs_p = gs_p->next) { + vtime1 = radd(vtime1, gs_p->fulltime); + } + + /* ending time is vtime1 plus the length of group 1. If group + * 1 is a grace note, use a very short time */ + if (EQ(gs1_p->fulltime, Zero)) { + RATIONAL tiny; + + tiny.n = 1; + tiny.d = 4 * MAXBASICTIME; + vtime2 = radd(vtime1, tiny); + } + else { + vtime2 = radd(vtime1, gs1_p->fulltime); + } + + /* get array index of other voice to check it */ + othervoice = (gs1_p->vno == 1 ? 1 : 0); + + if (hasspace(mll_p->u.staff_p->groups_p[othervoice], + vtime1, vtime2) == NO) { + /* there IS another voice, so stem goes opposite */ + return(gs1_p->stemdir); + } + } + + /* if only one voice (either because there is actually only one + * or because there is effectively only one since the other is space) + * and there is only one note in group, then bend is opposite stem */ + if (gs1_p->nnotes < 2) { + /* quarter note grace groups are a special case, since they + * don't have a stem (they are for showing prebends). So we + * put the bend opposite the stem of the following group. */ + if (gs1_p->grpvalue == GV_ZERO && gs1_p->basictime == 4 && + gs1_p->next != (struct GRPSYL *) 0) { + return(gs1_p->next->stemdir == UP ? DOWN : UP); + } + return(gs1_p->stemdir == UP ? DOWN : UP); + } + + /* if one voice on staff with more than one note in the group, all + * bend opposite the stem except the top if the stem is up or the + * bottom if the stem is down */ + if ( ((gs1_p->stemdir == DOWN) && (note_index == gs1_p->nnotes - 1)) + || ((gs1_p->stemdir == UP) && (note_index == 0)) ) { + return(gs1_p->stemdir); + } + else { + return(gs1_p->stemdir == UP ? DOWN : UP); + } +} diff --git a/mup/mup/plutils.c b/mup/mup/plutils.c new file mode 100644 index 0000000..98f37fc --- /dev/null +++ b/mup/mup/plutils.c @@ -0,0 +1,2327 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: plutils.c + * + * Description: This file contains utility functions belonging to the placement + * phase. Some of them are also used by other phases. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +static int phrase_tieslur_note P((struct GRPSYL *gs_p, int nidx, int side, + int interfere)); +static int tied_to_nidx P((struct GRPSYL *gs_p, int nidx)); +static int slurred_to_nidx P((struct GRPSYL *gs_p, int nidx, int sidx)); +static RATIONAL lefttime P((double count, struct GRPSYL *firstgs_p, + int timeden)); +static RATIONAL righttime P((double count, struct GRPSYL *firstgs_p, + int timeden)); + +/* + * Name: nextnongrace() + * + * Abstract: Return next nongrace group in a GRPSYL list. + * + * Returns: pointer to GRPSYL of next nongrace group, 0 if none + * + * Description: This function loops down the GRPSYL linked list from the given + * starting point. It returns the next nongrace GRPSYL, or 0 + * if none. + */ + +struct GRPSYL * +nextnongrace(gs_p) + +struct GRPSYL *gs_p; /* current group */ + +{ + gs_p = gs_p->next; + while (gs_p != 0 && gs_p->grpvalue == GV_ZERO) + gs_p = gs_p->next; + return (gs_p); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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)); +} + +/* + * 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)); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } + } +} + +/* + * 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)); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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)); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * Name: stemroom() + * + * Abstract: Try to find how much room a "wrong way" stem needs. + * + * Returns: The room needed, measured in stepsizes. + * + * Description: This function is given a nongrace note group whose stem has + * been forced the wrong way (down for the top group or up for the + * bottom group) despite the other voice being nonspace. It tries + * to find how long the stem will be so that we can decide whether + * the groups need to be horizontally offset. It works well for + * nonbeamed groups, but for beamed groups it can only guess. It + * is to be used in places where we need to know the stem length + * (to the extent possible) even though beamstem.c hasn't run yet. + * + * WARNING: This code is similar to the nongrace section of + * proclist() in beamstem.c. If you change one, you probably + * will need to change the other. + */ + +double +stemroom(gs_p) + +struct GRPSYL *gs_p; /* the group in question */ + +{ + float room; /* the answer, in stepsizes */ + int bf; /* number of beams/flags */ + + + /* + * If user specified stem length, use that. + */ + if (IS_STEMLEN_KNOWN(gs_p->stemlen)) { + return (gs_p->stemlen / STEPSIZE); + } + + /* + * If this group is part of a beamed set, there is no way to know how + * long the stem will be, since the beaming hasn't been done yet, and + * can't be done until all horizontal placement has been done. So + * return the default stem length and hope for the best. + */ + if (gs_p->beamloc != NOITEM) { + return (DEFSTEMLEN); + } + + /* + * Only half notes and shorter have stems, but whole and double + * whole notes still need to have a pseudo stem length set if + * alternation beams are to be drawn between two neighboring + * groups, or the group has slashes. + */ + if (gs_p->basictime <= 1 && gs_p->slash_alt == 0) { + /* no (pseudo)stem */ + return (0.0); + } + + /* find default stemlen for this voice */ + room = vvpath(gs_p->staffno, gs_p->vno, STEMLEN)->stemlen; + if (room == 0.0) { + return (0.0); + } + + /* if small notes, reduce this default */ + room *= (allsmall(gs_p, gs_p) == YES ? SM_STEMFACTOR : 1.0); + + /* add more, if needed, for flags/beams/slashes/alternations */ + if (gs_p->basictime >= 8) { + bf = drmo(gs_p->basictime) - 2; /* no. of beams/flags*/ + } else { + bf = 0; /* none on quarter or longer */ + } + bf += abs(gs_p->slash_alt); /* slashes or alternations */ + if (gs_p->slash_alt > 0 && gs_p->basictime >= 16) { + bf++; /* slashes need an extra one if 16, 32, ... */ + } + if (bf > 2) { + room += (bf - 2) * FLAGSEP / STEPSIZE; + } + + /* + * If the note may have flag(s), is stem up, and has dot(s), we must + * prevent the flag(s) from hitting the dot(s), by lengthening the stem. + */ + if (gs_p->basictime >= 8 && gs_p->stemdir == UP && gs_p->dots != 0) { + if (gs_p->notelist[0].stepsup % 2 == 0) { + /* note is on a line */ + if (gs_p->basictime == 8) { + room += 1.0; + } else { + room += 2.0; + } + } else { + /* note is on a space */ + if (gs_p->basictime > 8) { + room += 1.0; + } + } + } + + return (room); +} diff --git a/mup/mup/print.c b/mup/mup/print.c new file mode 100644 index 0000000..ed1cb76 --- /dev/null +++ b/mup/mup/print.c @@ -0,0 +1,4089 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* make the final pass through the main list, writing out the PostScript output + * for printing the music. This file contains most of the general print + * phase functions. Those that are associated with printing + * things from S_STAFF structs are mostly in prntdata.c. + * Tablature is printed via printtab.c. + * Additional print functions are in prntmisc.c and utils.c. + */ + +#include +#include +#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<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); +} + + +/* 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); +} + + +/* 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) ); +} + + +/* 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(); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } + } +} + + +#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 + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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")); +} + + +/* 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")); +} + + +/* 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); +} + + +/* 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))); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* 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(); +} + + +/* 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]); +} + + +/* 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); +} + + +/* 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); + } + + } + } +} + + +/* 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); +} + + +/* 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)); +} + + + +/* output an integer value */ + +static void +outint(val) + +int val; + +{ + OUTP(("%d ", val)); +} + + +/* 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 +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* print font name */ + +static void +prfontname(font) + +int font; +{ + OUTP(("/%s ", Fontinfo[font_index(font)].ps_name)); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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]; + } + } +} + + +/* 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); + } + } +} + + +/* 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)); +} + + +/* output the current scale factor */ + +static void +setscale() + +{ + OUTP(("%f %f scale\n", Score.scale_factor, Score.scale_factor)); +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* To help with debugging the placement phase of Mup, + * or just to help a user see why things are laid out as they are, + * this function will draw colored bounding boxes around things that + * have "coordinates." The environment variable MUP_BB control which, + * if any, kinds of things this is done for. This function is given the + * main list item at the end of a page. It backs up through the list, back to + * the beginning of the page, generating PostScript code to cause + * printing of relevant boxes. Doing this last on a page ensures the boxes + * are drawn on top of other things, and is at least as easy as going forwards. + */ + +static void +show_bounding_boxes(mll_p) + +struct MAINLL *mll_p; /* FEED for end of current page, or could be + * Mainlltc_p if at end of song. */ + +{ + int v; /* voice/verse */ + int n; /* NOTE index */ + struct GRPSYL *gs_p; + struct CHORD *chord_p; + struct STUFF *stuff_p; + + /* We are at bottom of main list for current page. Work upwards, + * printing any coords we find. */ + if (mll_p->str == S_FEED) { + /* Skip this feed. + * We want to back up to previous page feed, if any */ + mll_p = mll_p->prev; + } + + for ( ; mll_p != 0; mll_p = mll_p->prev) { + switch (mll_p->str) { + + case S_BAR: + if (BB_IS_SET(BB_BAR)) { + show_coord(mll_p->u.bar_p->c, BB_BAR); + } + break; + + case S_FEED: + if (BB_IS_SET(BB_FEED)) { + show_coord(mll_p->u.feed_p->c, BB_FEED); + } + if (mll_p->u.feed_p->pagefeed == YES + || Feednumber == 1) { + if (BB_IS_SET(BB_BLOCKHEAD)) { + /* Do header/footer */ + if (Feednumber == 1) { + show_coord(Header.c, BB_BLOCKHEAD); + show_coord(Footer.c, BB_BLOCKHEAD); + } + else { + show_coord(Header2.c, BB_BLOCKHEAD); + show_coord(Footer2.c, BB_BLOCKHEAD); + } + if (mll_p->u.feed_p->top_p != 0){ + set_win_coord(mll_p->u.feed_p->top_p->c); + show_coord(mll_p->u.feed_p->top_p->c, BB_BLOCKHEAD); + set_win_coord(0); + } + if (mll_p->u.feed_p->bot_p != 0){ + set_win_coord(mll_p->u.feed_p->bot_p->c); + show_coord(mll_p->u.feed_p->bot_p->c, BB_BLOCKHEAD); + set_win_coord(0); + } + } + if (mll_p->u.feed_p->pagefeed == YES) { + /* reached top of current page; we're done */ + return; + } + } + break; + + case S_STAFF: + if (mll_p->u.staff_p->visible == NO) { + break; + } + + /* show the staff itself */ + if (BB_IS_SET(BB_STAFF)) { + show_coord(mll_p->u.staff_p->c, BB_STAFF); + } + + /* Do groups and notes */ + if (BB_IS_SET(BB_GRPSYL) || BB_IS_SET(BB_NOTE)) { + for (v = 0; v < MAXVOICES; v++) { + + if (vvpath(mll_p->u.staff_p->staffno, + v+1, VISIBLE)->visible + == NO) { + /* Skip invisible voices */ + continue; + } + + for (gs_p = mll_p->u.staff_p->groups_p[v]; + gs_p != 0; + gs_p = gs_p->next) { + if (BB_IS_SET(BB_GRPSYL)) { + show_coord(gs_p->c, BB_GRPSYL); + } + if (gs_p->nnotes > 0 && + BB_IS_SET(BB_NOTE)) { + for (n = 0; n < gs_p->nnotes; n++) { + show_coord(gs_p->notelist[n].c, BB_NOTE); + } + } + } + } + } + + /* now do lyrics */ + if (BB_IS_SET(BB_GRPSYL)) { + for (n = 0; n < mll_p->u.staff_p->nsyllists; n++) { + for (gs_p = mll_p->u.staff_p->syls_p[n]; + gs_p != 0; + gs_p = gs_p->next) { + show_coord(gs_p->c, BB_GRPSYL); + } + } + } + + /* do the other "stuff" */ + if (BB_IS_SET(BB_STUFF)) { + for (stuff_p = mll_p->u.staff_p->stuff_p; + stuff_p != 0; + stuff_p = stuff_p->next) { + show_coord(stuff_p->c, BB_STUFF); + } + } + break; + + case S_CHHEAD: + if (BB_IS_SET(BB_CHORD)) { + for (chord_p = mll_p->u.chhead_p->ch_p; chord_p != 0; + chord_p = chord_p->ch_p) { + show_coord(chord_p->c, BB_CHORD); + } + } + break; + + default: + break; + } + } +} diff --git a/mup/mup/prntdata.c b/mup/mup/prntdata.c new file mode 100644 index 0000000..5258a18 --- /dev/null +++ b/mup/mup/prntdata.c @@ -0,0 +1,3668 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions for printing things off of STAFF structs: notes, stems, + * rests, flags, beams, etc */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + +/* This struct is used to build up a mesh that represents cross staff beams. + * This is used to figure out how far from the stem end to offset + * the end of a beam. + * There are a row of these linked horizontally via "next" for each beam. + * The stems are linked vertically via the above_p and below_p pointers. + * To get the stem offset for a given beam, + * the code finds the desired basictime on the appropriate stem, + * and counts how many beams that is from the end of the stem. + */ +struct CSBINFO { + struct CSBINFO *next; /* for next group in same beam */ + struct CSBINFO *above_p; /* beams above this beam */ + struct CSBINFO *below_p; /* beams below this beam */ + struct GRPSYL *gs_p; /* group this info is associated with. + * This is only used on the 8th beam, + * and is just for convenience, + * to save us from having to figure + * it out again later. + */ + int basictime; /* 8, 16, 32, etc represented by beam */ +}; + +/* static functions */ +static void do_syl_joins P((char *syl, double west, double y)); +static void pr_stuff P((struct STUFF *stufflist_p, int staffno, + struct MAINLL *mll_p)); +static int pr_grid P((struct STUFF *stuff_p, int staffnum)); +static void pr_tieslur P((struct STUFF *stuff_p, struct MAINLL *mll_p, + int staffno)); +static int get_ts_style P((struct STUFF *stuff_p, struct MAINLL *mll_p)); +static void pr_rest P((struct GRPSYL *gs_p, struct STAFF *staff_p)); +static double mr_y_loc P((int staffno)); +static void pr_note_dots P((struct NOTE *noteinfo_p, int numdots, + double xdotr, double group_x, double group_y)); +static void pr_parens P((struct NOTE *note_p, struct GRPSYL *gs_p)); +static void pr_stems P((struct GRPSYL *grpsyl_p)); +static double slash_xlen P((struct GRPSYL *grpsyl_p)); +static void pr_flags P((struct GRPSYL *grpsyl_p, double x, double y)); +static void pr_accidental P((struct NOTE *noteinfo_p, struct GRPSYL *grpsyl_p)); +static void pr_leger P((struct NOTE *noteinfo_p, struct GRPSYL *gs_p, + int staffno)); +static int numlegers P((struct NOTE *noteinfo_p)); +static double leger_length P((struct NOTE *noteinfo_p, struct GRPSYL *othergs_p, + int lines, int other_is_prev, int is_intermediate)); +static void pr_tupnums P((struct GRPSYL *gs_p, struct STAFF *staff_p)); +static void pr_beams P((struct GRPSYL *grpsyl_p, int grpvalue, int grpsize)); +static struct CSBINFO *mkcsbmesh P((struct GRPSYL *begin_p, + struct GRPSYL *end_p)); +static int draw_beams P((struct GRPSYL *gs_p, struct GRPSYL *endbeam_p, + int basictime, int grpsize, int grpvalue)); +static double beam_offset P((int nbeams, int gsize, int stemdir)); +static struct GRPSYL *neighboring_note_beam_group P((struct GRPSYL *gs_p, + struct GRPSYL *first_p, int backwards) ); +static int chkgroupings P((int *side_p, struct GRPSYL *thisgs_p)); +static void do_beam P((double x1, double y1, double x2, double y2, + double halfwidth)); +static void pr_cresc P((struct STUFF *stuff_p)); +static void extend P((struct STUFF *stuff_p)); +static int tupdir1voice P((struct GRPSYL *gs_p)); +static int mirror P((char *str, int ch, int font)); + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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 ); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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; + } +} + + +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)); +} + + +/* 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); + } +} + + +/* 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); + } + } +} + + +/* 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; + } + } +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* 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); +} + + +/* 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; + } + } + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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) ); +} + + +/* 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)); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + +/* + * 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 */ +} + + +/* 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(); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* Some characters have upside-down versions that are used + * if stem is down. This table maps such characters to their flips versions. + */ + +static struct MIRRCHAR { + int font; /* Which music font. Note that both the + * normal and inverted characters must be + * in the same font. (We could relax + * this constraint by storing a font for each, + * and returning both character and font, + * but there's no hardship in this simple way.) + */ + char norm; + char inverted; +} mirrtbl[] = { + { FONT_MUSIC, C_FERM, C_UFERM }, + { FONT_MUSIC, C_ACC_HAT, C_ACC_UHAT }, + { FONT_MUSIC, C_WEDGE, C_UWEDGE }, + { 0, 0 } +}; + + +/* Given a string and the first character in it, if it is a music symbol + * that has a mirrored version, return that, otherwise, return + * it as it was. + */ + +static int +mirror(str, ch, font) + +char *str; /* the string to check */ +int ch; /* the first character (which better be a music character) */ +int font; /* FONT_MUSIC or some other music font */ + +{ + int i; + + for (i = 0; mirrtbl[i].norm != '\0'; i++) { + if (string_is_sym(str, mirrtbl[i].norm, mirrtbl[i].font) == YES) { + return((int) mirrtbl[i].inverted); + } + } + return(ch); +} diff --git a/mup/mup/prntmisc.c b/mup/mup/prntmisc.c new file mode 100644 index 0000000..5b0a3ff --- /dev/null +++ b/mup/mup/prntmisc.c @@ -0,0 +1,1421 @@ + +/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions for printing endings, pedal marks, phrase marks, etc */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* width of tapered curve at endpoint relative to maximum width */ +#define TAPERWID (0.4) + + +/* + * Define a structure for storing points of a curve, whether generated (like + * for phrase marks) or user-specified. It also stores information used in + * calculating Bezier curves that will be drawn between each pair of + * neighboring points. The "control points" are points 1 and 2 for the + * Bezier curve going from this point to the next point. These structures + * get their x and y filled in from CURVE or CRVLIST structures. + */ +struct CURVEINFO { + float x, y; /* point's coords */ + float len; /* length of line segment from here to next point */ + float ang; /* angle between the 2 segments at this point */ + int bend; /* bend direction at point: 1=clockwise, -1=counter */ + float slopetan; /* slope of line "tangent" to this point if axes are */ + /* rotated such that segment starting here is horiz. */ + float x1, y1; /* control point 1 for segment starting at this point */ + float x2, y2; /* control point 2 for segment starting at this point */ +}; + +/* static functions */ +static void do_endings P((struct MAINLL *first_p, struct MAINLL *last_p, + char *endlabel, int carryout)); +static void draw_ending P((int staffno, double ry, struct MAINLL *first_p, + struct MAINLL *last_p, char *endlabel, int carryout)); +static void pr_endlabel P((double x, double y, char *label)); +static void pr_end_line P((double begin_x, double end_x, double y, + int carryout)); +static int is_top_visible_in_range P((int staffno, int top)); +static void calccurve P((struct CURVEINFO v[], int num)); +static void findcontrol P((struct CURVEINFO v[], int num)); + + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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)); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* Print 'atend' grids */ + +void +pr_atend() + +{ + float x; /* of first grid of row */ + float y; /* of row; top line of grid */ + float gridx; /* x of grid being printed */ + float north; /* of the grid */ + float space; /* distance between grid lines */ + struct GRID *grid_p; + int g; /* index through grid_p array */ + int staff = -1; /* always -1 to indicate atend. Using a + * variable rather than hard-coding where + * used just on general principles. */ + int column; /* how many columns printed so far in row */ + int rows_to_print; /* how many rows to print per page. */ + struct MAINLL *main_feed_p; /* for getting top/bottom blocks */ + struct FEED *feed_p; /* for getting top/bottom blocks */ + + + x = Atend_info.firstgrid_x; + y = Atend_info.firstgrid_y; + rows_to_print = Atend_info.rows_per_page; + space = gridspace(staff); + column = 0; + + /* Find the last FEED. We use that to get top/bottom blocks */ + for (main_feed_p = Mainlltc_p; main_feed_p->str != S_FEED; + main_feed_p= main_feed_p->prev) { + ; + } + feed_p = main_feed_p->u.feed_p; + for (g = 0; g < Atend_info.grids_used; g++) { + grid_p = Atend_info.grid_p[g]; + gridsize(grid_p, staff, &north, (float *) 0, (float *) 0, (float *) 0); + /* calculate horizontal position of this grid */ + gridx = x + column * Atend_info.horz_sep; + + /* print the name of the grid */ + pr_string(gridx - strwidth(grid_p->name) / 2.0, + y + north + strdescent(grid_p->name), + grid_p->name, J_LEFT, (char *) 0, -1); + + /* print the grid itself */ + do_grid(gridx - space * (grid_p->numstr - 1) / 2.0, + y, space, grid_p, staff); + + if (++column >= Atend_info.grids_per_row && + g < Atend_info.grids_used - 1) { + /* move to next row */ + column = 0; + y -= Atend_info.vert_sep; + rows_to_print--; + if (Atend_info.separate_page == YES && + rows_to_print <= 0) { + rows_to_print = Atend_info.rows_per_page; + y = Atend_info.firstgrid_y; + /* print top/bottom blocks, if any */ + /* use *2 blocks for any subsequent pages */ + feed_p->top_p = feed_p->top2_p; + feed_p->bot_p = feed_p->bot2_p; + pr_feed(main_feed_p); + } + } + } +} diff --git a/mup/mup/prnttab.c b/mup/mup/prnttab.c new file mode 100644 index 0000000..c2d98c3 --- /dev/null +++ b/mup/mup/prnttab.c @@ -0,0 +1,886 @@ +/* Copyright (c) 1997, 1998, 1999, 2001, 2003, 2004 by Arkkra Enterprises */ +/* All rights reserved. */ + +/* functions to support printing of tab staffs */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* position of the last bend arrow for each staff, or 0.0 if no + * arrow on previous group */ +static double Last_x_arrow[MAXSTAFFS + 1], Last_y_arrow[MAXSTAFFS + 1]; + +static double pr_tab_note P((int note_index, struct GRPSYL *gs_p, + double y_adjust, struct MAINLL *mll_p)); +static double pr_bstring P((struct GRPSYL *gs_p, struct NOTE *note_p, + int note_index, double y_adjust, struct MAINLL *mll_p)); +static void pr_b_arrow P((struct GRPSYL *gs_p, struct MAINLL *mll_p, + double y_adjust)); +static void pr_b_curve P((float *xlist, float *ylist, struct GRPSYL *gs_p, + double y_adjust)); +static void pr_arrowhead P((struct GRPSYL *gs_p, double y_adjust, int headchar)); +static int bends_up P((struct GRPSYL *gs_p, int n, struct GRPSYL *pgs_p, + int carried_in)); +static int is_carried_in_bend P((struct MAINLL *mll_p, + struct MAINLL *prev_mll_p)); + + + +/* 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]); + } + } + } +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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); + } + } +} + + +/* 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); +} + + +/* 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]; +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* print a TAB "clef" which is really just the word "TAB" written vertically. + * By convention, this only gets printed once per staff at the very beginning + * of the song. To keep things simple, the width of the clef is always + * returned as if the clef was printed even when it really isn't */ + +double +pr_tabclef(staffno, x, really_print, size) + +int staffno; +double x; +int really_print; +int size; + +{ + static int did_tab_clef[MAXSTAFFS + 1]; /* set to YES once we print a + * TAB clef on a given staff. Convention is to print + * this "clef" only at the very beginning of a song. */ + int stafflines; + int ptsize; /* point size to use for "TAB" */ + double width, widest; /* of the letters in "TAB" */ + double height = 0.0; + char letter[4]; /* internal format version of one letter of "TAB" */ + char *tabstr; /* pointer through "TAB" */ + double y = 0.0; + + + /* adjust the size based on how many stafflines there are */ + stafflines = svpath(staffno, STAFFLINES)->stafflines; + if (stafflines < 4) { + ptsize = 7; + } + else if (stafflines == 4) { + ptsize = 13; + } + else if (stafflines == 5) { + ptsize = 16; + } + else { + ptsize = 20; + } + + /* if small clef, adjust the size (actually, this shouldn't + * ever happen unless we change some other things some day, but this + * way we will be prepared if/when that happens). */ + if (size != DFLT_SIZE) { + ptsize = (int) (ptsize * (size / DFLT_SIZE)); + } + ptsize = adj_size(ptsize, Staffscale, (char *) 0, -1); + + /* print/get width of "TAB" */ + for (widest = 0, tabstr = "TAB"; *tabstr != '\0'; tabstr++) { + + /* create internal format string for current letter */ + (void) sprintf(letter, "%c%c%c", FONT_HB, ptsize, *tabstr); + /* get its width */ + width = strwidth(letter); + + /* save the widest letter width */ + if (width > widest) { + widest = width; + } + + /* if we're really supposed to print, + * print this letter of "TAB" */ + if (really_print == YES && did_tab_clef[staffno] == NO) { + + /* figure out where to place vertically */ + if (*tabstr == 'T') { + /* place the top letter */ + height = strheight(letter); + y = Staffs_y[staffno] + height / 2.0 + + Stdpad; + } + else { + /* move subsequent letters down by height + * of the previous */ + y -= height; + } + + /* print the letter with a little space before */ + pr_string(x + 3.0 * Stdpad, y, letter, J_LEFT, + (char *) 0, -1); + } + } + + /* only print once per staff */ + if (really_print == YES) { + did_tab_clef[staffno] = YES; + } + + /* allow some space on either side */ + return(widest + 6.0 * Stdpad); +} diff --git a/mup/mup/prolog.c b/mup/mup/prolog.c new file mode 100644 index 0000000..605b782 --- /dev/null +++ b/mup/mup/prolog.c @@ -0,0 +1,1769 @@ +/* Copyright 1995, 1996, 1997, 1998 by Arkkra Enterprises */ + +#include +#include "globals.h" + +char *prolog_text[] = { + "% Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004 by Arkkra Enterprises", + "% All rights reserved", + "", + "% Mup PostScript Prolog 5.3 for use with Mup 5.3", + "", + "% lwid is used as the width of a standard (thin) line in the music", + "% character definitions.", + "/lwid 70 def", + "/halflwid lwid 2 div def", + "", + "% Define the following for use in do_upshortnote, do_dnshortnote, and", + "% do_shortrest; it has to be done outside of the music font definition.", + "/utildict 10 dict def", + "utildict begin", + " /setnumflags { /numflags exch def } def", + " /sethooksm1 { /hooksm1 exch def } def", + " /setoffsets { /offsets exch def } def", + " /setx { /x exch def } def", + " /sety { /y exch def } def", + "end", + "", + "% Define a music character font. Each music character is defined as if it", + "% were a normal ASCII character in a strange font where \"A\" looks like a", + "% treble clef, \"B\" looks like a bass clef, etc.", + "", + "/mfont0 100 dict def", + "mfont0 begin", + " /FontType 3 def", + " /FontMatrix [ .001 0 0 0.001 0 0 ] def", + " /FontBBox [ -2000 -4030 2000 4030 ] def", + " /FontName (Mfont0) def", + "", + " % set up Encoding vector with standard names", + " /Encoding 256 array def", + " StandardEncoding Encoding copy", + " pop", + "", + " % the following definitions are used for quarter rests", + " /topx -170 def /topy 950 def", + " /cor1x 250 def /cor1y 450 def", + " /cor2x -300 def /cor2y 200 def", + " /cor3x 250 def /cor3y -400 def", + "", + " % the following definitions are used for double sharps", + " /limit 300 halflwid add def", + " /off 70 def", + " /inbendsmall limit 200 sub def", + " /inbendbig limit 20 sub def", + " /outbendsmall 100 def", + " /outbendbig outbendsmall off add def", + "", + " %%%%% define routines that will be used by multiple characters %%%%%", + " /do_1n {", + " gsave", + " newpath -10 rotate 1.6 1 scale", + " 0 0 325 0 360 arc %outer ellipse", + " 1 1.6 div 1 scale 10 rotate %back to original", + " 35 rotate 0.85 1.1 scale", + " 0 0 275 0 360 arc %inner ellipse", + " eofill", + " grestore", + " } def", + " /do_upflag {", + " -315 0 moveto", + " -300 100 -100 480 0 600 curveto", + " 300 960 350 1500 200 1700 curveto", + " 130 1700 lineto", + " 350 1200 50 650 -315 600 curveto", + " fill", + " } def", + " /do_flat {", + " -250 -400 moveto %outer edge of loop", + " 500 0 350 650 -250 160 curveto", + " -250 160 lwid sub lineto %inner edge of loop", + " 100 400 300 0 -250 -400 lwid add curveto", + " fill", + "", + " lwid setlinewidth %stem", + " -250 1100 moveto -250 -400 lineto stroke", + " } def", + " /do_diamond {", + " newpath", + " 420 0 moveto 0 300 lineto -420 0 lineto", + " 0 -300 lineto closepath", + " 259 -29 moveto -41 185 lineto -259 29 lineto", + " 41 -185 lineto closepath", + " eofill", + " } def", + " /do_2n {", + " gsave", + " newpath 25 rotate 1.4 1 scale", + " 0 0 315 0 360 arc %outer ellipse", + " 1 1.4 div 1 scale %back to original", + " 1.3 0.5 scale", + " 0 0 310 0 360 arc %inner ellipse", + " eofill", + " grestore", + " } def", + " /do_4n {", + " gsave", + " newpath 25 rotate 1.35 1 scale", + " 0 0 310 0 360 arc fill", + " grestore", + " } def", + " /do_com {", + " newpath", + " 330 250 150 0 360 arc fill %knob at upper right", + " 465 300 moveto %outer boundary", + " 410 500 200 635 0 635 curveto", + " -750 635 -750 -635 0 -635 curveto", + " 350 -635 480 -300 500 -100 curveto", + " 430 -100 lineto %inner boundary", + " 380 -300 250 -565 0 -565 curveto", + " -450 -565 -450 565 0 565 curveto", + " 200 565 370 350 395 300 curveto", + " fill", + " } def", + " /do_ferm {", + " 0 0 800 lwid sub 0 180 arc %inner arc", + " -800 0 lineto", + " 0 270 lwid sub 800 180 0 arcn %outer arc", + " 800 0 lineto fill", + " 0 120 120 0 360 arc fill %the dot", + " } def", + " /do_mor {", + " gsave", + " 0.7 1 scale %scrunch the following horizontally", + " 45 rotate %to pretend all lines horz or vertical", + " 0 1 1 {", + " pop %we don't need the loop variable", + " %one half of the mordent", + " 0 40 moveto 350 40 lineto 350 -460 lineto", + " 750 -460 lineto 750 -540 lineto", + " 150 -540 lineto 150 -40 lineto", + " 0 -40 lineto fill", + " 180 rotate %to do the other half", + " } for", + " grestore", + " } def", + " /do_turn {", + " gsave", + " 0 1 1 {", + " pop %we don't need the loop variable", + " 0 -100 moveto %outer boundary", + " 200 -400 625 -400 625 0 curveto", + " 625 200 500 325 300 325 curveto", + " 300 185 lineto %inner boundary", + " 450 255 555 150 555 0 curveto", + " 555 -350 250 -250 0 100 curveto", + " fill", + " 300 255 70 0 360 arc fill %knob on end", + " 180 rotate %to do the other half", + " } for", + " grestore", + " } def", + "", + " /do_upshortnote {", + " utildict begin", + " setnumflags %set numflags from the stack", + " gsave", + " -330 0 translate %half a flag width", + " do_4n %do a quarter note head", + " lwid setlinewidth", + " 370 0 moveto", + " 370 2100 numflags 2 sub flagsep mul add lineto stroke", + " 670 2100 numflags 2 sub flagsep mul add translate", + " 1 -1 scale %reflect across X axis", + " 0 1 numflags 1 sub {", + " do_upflag %do an upflag", + " pop %we don't need the loop variable", + " 0 flagsep translate", + " } for", + " grestore", + " end", + " } def", + "", + " /do_dnshortnote {", + " utildict begin", + " setnumflags %set numflags from the stack", + " do_4n %do a quarter note head", + " lwid setlinewidth", + " -370 0 moveto", + " -370 -2100 numflags 2 sub flagsep mul sub lineto stroke", + " gsave", + " -70 -2100 numflags 2 sub flagsep mul sub translate", + " 0 1 numflags 1 sub {", + " do_upflag %do an upflag", + " pop %we don't need the loop variable", + " 0 flagsep translate", + " } for", + " grestore", + " end", + " } def", + "", + " /do_shortrest {", + " utildict begin", + " sety setx setoffsets sethooksm1 %set variable from the stack", + " gsave", + " -105.8 offsets mul -600 offsets mul translate", + " 0 1 hooksm1 { %loop once per hook", + " newpath", + " 1 setlinewidth", + " gsave", + " 1 1.2 scale", + " -150 300 1.2 div 140 0 360 arc fill %the dot", + " grestore", + " lwid setlinewidth", + " -50 700 550 255 315 arc %rest of the hook", + " hooksm1 lt { stroke 105.8 600 translate } if", + " } for", + " x y lineto stroke", + " grestore", + " end", + " } def", + "", + "", + " % subsidiary dictionary of character definitions", + " /CharStrings 128 dict def", + " CharStrings begin", + "", + " /.notdef {} def", + "", + " % Here are the definitions of the characters. A stepsize here", + " % is 300 units (assuming the character is drawn at its default", + " % size).", + "", + " % gclef", + " /A {", + " newpath", + " %start with inner curl, inside boundary", + " -50 -300 moveto", + " -450 600 700 700 750 0 curveto", + " 750 -800 -700 -800 -700 200 curveto", + " -700 900 500 1400 520 2250 curveto", + " 520 2900 300 3000 200 3000 curveto", + " 100 3000 -400 2500 -200 1800 curveto", + " 350 -600 lineto", + " 720 -1600 0 -1650 -400 -1400 curveto", + "", + " %go back to start, drawing the other boundary", + " -400 -1480 lineto", + " 0 -1700 800 -1700 430 -600 curveto", + " -120 1800 lineto", + " -300 2400 200 2800 250 2800 curveto", + " 400 2800 430 2700 430 2450 curveto", + " 430 1800 -900 1200 -900 300 curveto", + " -750 -900 800 -900 850 0 curveto", + " 900 1100 -750 900 -120 -300 curveto fill", + "", + " %circle at the bottom", + " -300 -1250 250 0 360 arc fill", + " } def", + "", + " % fclef", + " /B {", + " newpath", + " %start with outside boundary, at bottom", + " -1000 -1700 moveto", + " 100 -1100 500 -600 450 0 curveto", + " 450 850 -1100 850 -950 0 curveto", + "", + " %go back to start, drawing the other boundary", + " -880 0 lineto", + " -920 400 -600 560 -300 560 curveto", + " 0 560 150 400 150 0 curveto", + " 150 -400 100 -900 -1000 -1620 curveto fill", + "", + " %circle at the left", + " newpath", + " -700 0 250 0 360 arc fill", + "", + " %do the two dots after the main curve", + " 700 -300 100 0 360 arc fill", + " 700 300 100 0 360 arc fill", + " } def", + "", + " % cclef", + " /C {", + " gsave", + " %do upper curved part, then scale to do mirror image", + " 0 1 1 {", + " pop %we don't need the loop variable", + " %outer boundary of curve", + " -170 0 moveto 100 300 lineto", + " 400 -200 750 300 750 650 curveto", + " 750 1100 450 1235 250 1235 curveto", + " 0 1235 -143 1100 -143 950 curveto", + "", + " %inner boundary of curve", + " 0 950 lineto", + " 0 1100 30 1165 250 1165 curveto", + " 300 1165 450 1100 450 650 curveto", + " 450 400 400 -100 100 400 curveto", + " -270 0 lineto fill", + " %stroke", + " %-270 0 moveto 100 400 lineto", + " %400 -100 450 400 450 650 curveto", + " %450 1100 300 1165 250 1165 curveto", + " %30 1165 0 1100 0 950 curveto", + " %stroke", + "", + " %elliptical ball at end of curve", + " gsave", + " 1.3 1 scale", + " 10 950 120 0 360 arc fill", + " grestore", + " 1 -1 scale %reflect across X axis", + " } for", + " grestore", + "", + " % two vertical lines on the left", + " 300 setlinewidth -600 -1200 halflwid sub moveto", + " -600 1200 halflwid add lineto stroke", + " lwid setlinewidth -300 -1200 halflwid sub moveto", + " -300 1200 halflwid add lineto stroke", + " } def", + "", + " % dblwhole", + " /D {", + " do_1n %do a whole note", + " lwid setlinewidth", + " -490 -600 moveto -490 600 lineto stroke", + " 490 -600 moveto 490 600 lineto stroke", + " } def", + "", + " % 1n", + " /E {", + " do_1n %do a whole note", + " } def", + "", + " % 2n", + " /F {", + " do_2n %do a half note", + " } def", + "", + " % 4n", + " /G {", + " do_4n %do a quarter note head", + " } def", + "", + " % upflag", + " /H {", + " do_upflag %do an upflag", + " } def", + "", + " % dnflag", + " /I {", + " gsave", + " 1 -1 scale %reflect across X axis", + " do_upflag %do an upflag", + " grestore", + " } def", + "", + " % dwhrest", + " /J {", + " 300 setlinewidth", + " 0 0 moveto 0 600 lineto stroke", + " } def", + "", + " % 1rest", + " /K {", + " lwid setlinewidth", + " -750 600 moveto 750 600 lineto stroke", + " 300 setlinewidth", + " -400 450 moveto 400 450 lineto stroke", + " } def", + "", + " % 2rest", + " /L {", + " lwid setlinewidth", + " -750 0 moveto 750 0 lineto stroke", + " 300 setlinewidth", + " -400 150 moveto 400 150 lineto stroke", + " } def", + "", + " % 4rest", + " /M {", + " newpath", + " cor3x cor3y halflwid add moveto", + " %-400 -200 -450 -650 50 -950 lwid add curveto", + " -450 -50 -450 -650 50 -950 lwid add curveto", + " -150 -650 -100 -250 cor3x cor3y halflwid sub curveto", + " fill", + "", + " cor1x cor1y moveto cor1x 200 sub cor1y 200 add lineto", + " cor2x cor2y lineto cor2x 200 add cor2y 200 sub lineto", + " fill", + "", + " lwid setlinewidth", + " topx topy moveto cor1x cor1y lineto stroke", + " cor2x cor2y moveto cor3x cor3y lineto stroke", + " } def", + "", + " % 8rest", + " /N {", + " 0 0 0 -600 do_shortrest", + " } def", + "", + " % 16rest", + " /O {", + " 1 1 100 -1200 do_shortrest", + " } def", + "", + " % 32rest", + " /P {", + " 2 1 0 -1800 do_shortrest", + " } def", + "", + " % 64rest", + " /Q {", + " 3 2 -80 -2100 do_shortrest", + " } def", + "", + " % 128rest", + " /R {", + " 4 2 -150 -2700 do_shortrest", + " } def", + "", + " % 256rest", + " /S {", + " 5 3 -280 -3300 do_shortrest", + " } def", + "", + " % dot", + " /T {", + " newpath", + " 0 0 120 0 360 arc fill", + " } def", + "", + " % nat", + " /U {", + " % fill crossbars so that we can do parallelograms", + " -235 -470 moveto -235 -270 lineto", + " 235 -130 lineto 235 -330 lineto fill", + " -235 130 moveto -235 330 lineto", + " 235 470 lineto 235 270 lineto fill", + "", + " % vertical strokes", + " lwid setlinewidth", + " -200 -380 moveto -200 850 lineto stroke", + " 200 -850 moveto 200 380 lineto stroke", + " } def", + "", + " % sharp", + " /V {", + " % fill crossbars so that we can do parallelograms", + " -325 -480 moveto -325 -280 lineto", + " 325 -120 lineto 325 -320 lineto fill", + " -325 120 moveto -325 320 lineto", + " 325 480 lineto 325 280 lineto fill", + "", + " % vertical strokes", + " lwid setlinewidth", + " -150 -930 moveto -150 880 lineto stroke", + " 150 -880 moveto 150 930 lineto stroke", + " } def", + "", + " % flat", + " /W {", + " do_flat %do a flat", + " } def", + "", + " % dblsharp", + " /X {", + " gsave", + " 0 1 3 { %loop once for each of 4 sticks", + " pop %we don't need the loop variable", + " 0 off neg moveto", + " outbendbig outbendsmall lineto", + " inbendbig inbendsmall lineto", + " limit limit lineto", + " inbendsmall inbendbig lineto", + " outbendsmall outbendbig lineto", + " off neg 0 lineto", + " fill", + " -90 rotate", + " } for", + " grestore", + " } def", + "", + " % dblflat", + " /Y {", + " -290 580 290 { %loop once for each flat", + "", + " gsave", + " 1 setlinewidth", + " 0 translate %translate left/right (loop var)", + " do_flat %do a flat", + " grestore", + "", + " } for", + " } def", + "", + " % xnote", + " /Z {", + " gsave", + " 1.15 1 scale 120 setlinewidth 1 setlinecap %round", + " -300 -300 moveto 300 300 lineto stroke", + " -300 300 moveto 300 -300 lineto stroke", + " grestore", + " } def", + "", + " % dwhdiamond", + " /a {", + " do_diamond %do a diamond", + " lwid setlinewidth", + " -420 -600 moveto -420 600 lineto stroke", + " 420 -600 moveto 420 600 lineto stroke", + " } def", + "", + " % diamond", + " /b {", + " do_diamond %do a diamond", + " } def", + "", + " % filldiamond", + " /c {", + " 420 0 moveto 0 300 lineto", + " -420 0 lineto 0 -300 lineto fill", + " } def", + "", + " % up2n", + " /d {", + " lwid setlinewidth", + " 380 0 moveto 380 2100 lineto stroke", + " do_2n %do a half note", + " } def", + "", + " % dn2n", + " /e {", + " lwid setlinewidth", + " -380 0 moveto -380 -2100 lineto stroke", + " do_2n %do a half note", + " } def", + "", + " % up4n", + " /f {", + " do_4n %do a quarter note head", + " lwid setlinewidth", + " 370 0 moveto 370 2100 lineto stroke", + " } def", + "", + " % dn4n", + " /g {", + " do_4n %do a quarter note head", + " lwid setlinewidth", + " -370 0 moveto -370 -2100 lineto stroke", + " } def", + "", + " % up8n", + " /h {", + " gsave", + " -330 0 translate % half a flag width", + " do_4n %do a quarter note head", + " lwid setlinewidth", + " 370 0 moveto 370 2100 lineto stroke", + " 670 2100 translate", + " 1 -1 scale %reflect across X axis", + " do_upflag %do an upflag", + " grestore", + " } def", + "", + " % dn8n", + " /i {", + " do_4n %do a quarter note head", + " lwid setlinewidth", + " -370 0 moveto -370 -2100 lineto stroke", + " gsave", + " -70 -2100 translate", + " do_upflag %do an upflag", + " grestore", + " } def", + "", + " % up16n", + " /j {", + " 2 do_upshortnote", + " } def", + "", + " % dn16n", + " /k {", + " 2 do_dnshortnote", + " } def", + "", + " % up32n", + " /l {", + " 3 do_upshortnote", + " } def", + "", + " % dn32n", + " /m {", + " 3 do_dnshortnote", + " } def", + "", + " % up64n", + " /n {", + " 4 do_upshortnote", + " } def", + "", + " % dn64n", + " /o {", + " 4 do_dnshortnote", + " } def", + "", + " % up128n", + " /p {", + " 5 do_upshortnote", + " } def", + "", + " % dn128n", + " /q {", + " 5 do_dnshortnote", + " } def", + "", + " % up256n", + " /r {", + " 6 do_upshortnote", + " } def", + "", + " % dn256n", + " /s {", + " 6 do_dnshortnote", + " } def", + "", + " % com", + " /t {", + " do_com %do a common time symbol", + " } def", + "", + " % cut", + " /u {", + " do_com %do a common time symbol", + " lwid setlinewidth", + " 0 -900 moveto 0 900 lineto stroke", + " } def", + "", + " % begped", + " /v {", + " lwid setlinewidth", + " -200 600 moveto -200 0 lineto 200 0 lineto stroke", + " } def", + "", + " % pedal", + " /w {", + " lwid setlinewidth", + " -500 0 moveto -450 0 lineto 0 600 lineto", + " 450 0 lineto 500 0 lineto stroke", + " } def", + "", + " % endped", + " /x {", + " lwid setlinewidth", + " 200 600 moveto 200 0 lineto -200 0 lineto stroke", + " } def", + "", + " % dnbow", + " /y {", + " lwid setlinewidth", + " -350 0 moveto -350 900 lineto stroke", + " 350 0 moveto 350 900 lineto stroke", + " 200 setlinewidth", + " -350 800 moveto 350 800 lineto stroke", + " } def", + "", + " % upbow", + " /z {", + " lwid setlinewidth", + " -300 900 moveto 0 0 lineto 300 900 lineto stroke", + " } def", + "", + " % wedge", + " /one {", + " 0 0 moveto -150 500 lineto 150 500 lineto fill", + " } def", + "", + " % uwedge", + " /two {", + " -150 0 moveto 150 0 lineto 0 500 lineto fill", + " } def", + "", + " % ferm", + " /three {", + " newpath", + " do_ferm %do a right side up fermata", + " } def", + "", + " % uferm", + " /four {", + " newpath", + " gsave", + " 0 270 lwid sub 800 add translate %baseline at bottom", + " 180 rotate %upside down", + " do_ferm %do a right side up fermata", + " grestore", + " } def", + "", + " % sign", + " /five {", + " gsave", + " %do upper left curved part, upper right dot;", + " %then rotate 180 to do other half", + " 0 1 1 {", + " pop %we don't need the loop variable", + " 0 100 moveto %inner boundary", + " -1000 300 -400 750 -200 700 curveto", + " -200 800 lineto %outer boundary", + " -550 900 -1100 100 0 -100 curveto", + " fill", + " %dot at end of curve", + " -200 700 100 0 360 arc fill", + " %dot in upper right quadrant", + " 500 200 70 0 360 arc fill", + " 180 rotate", + " } for", + " grestore", + "", + " %slash through middle", + " lwid setlinewidth", + " -400 -800 moveto 400 800 lineto stroke", + " } def", + "", + " % coda", + " /six {", + " newpath", + " gsave", + " 0.6 1 scale", + " 0 0 550 0 360 arc %outside boundary", + " 1 0.6 div 1 scale %back to original", + " 0.9 1 scale", + " 0 0 650 0 360 arc %inside boundary", + " eofill", + " grestore", + " lwid setlinewidth", + " 0 -850 moveto 0 850 lineto stroke", + " -800 0 moveto 800 0 lineto stroke", + " } def", + "", + " % mor", + " /seven {", + " do_mor %do a mordent", + " } def", + "", + " % invmor", + " /eight {", + " do_mor %do a mordent", + " lwid setlinewidth", + " 0 -450 moveto 0 450 lineto stroke", + " } def", + "", + " % turn", + " /nine {", + " do_turn %do a turn", + " } def", + "", + " % invturn", + " /zero {", + " gsave", + " 1 -1 scale %reflect across X axis", + " do_turn %do a turn", + " grestore", + " } def", + "", + " % acc_gt", + " /numbersign {", + " lwid setlinewidth", + " -500 300 moveto 500 0 lineto -500 -300 lineto stroke", + " } def", + "", + " % acc_hat", + " /dollar {", + " newpath", + " -365 0 moveto 0 860 lineto 365 0 lineto", + " 150 0 lineto -75 530 lineto -300 0 lineto fill", + " } def", + "", + " % acc_uhat", + " /quotedbl {", + " newpath", + " 365 860 moveto 0 0 lineto -365 860 lineto", + " -150 860 lineto 75 330 lineto 300 860 lineto fill", + " } def", + "", + " % tr", + " /asterisk {", + " %vertical bar of t", + " -350 1000 moveto -550 200 lineto", + " -612.5 -50 -212.5 -50 -160 200 curveto", + " -230 200 lineto", + " -300 50 -420 50 -400 200 curveto", + " -200 1000 lineto fill", + "", + " %crossbar of t and vertical bar of r", + " -700 600 moveto -160 600 lineto", + " 20 600 30 520 60 440 curveto", + " -50 0 lineto 70 0 lineto 180 440 lineto", + " 190 480 100 670 -150 670 curveto", + " -690 670 lineto fill", + "", + " %horizontal curve of r", + " 100 480 moveto", + " 300 630 450 700 650 550 curveto", + " 560 480 lineto", + " 450 630 300 560 100 390 curveto", + " fill", + "", + " %knob at end of r", + " 600 460 100 0 360 arc fill", + " } def", + "", + " % leg", + " /comma {", + " 100 setlinewidth", + " -400 0 moveto 400 0 lineto stroke", + " } def", + "", + " % rr", + " /hyphen {", + " 100 setlinewidth", + " -400 0 moveto 0 1000 lineto stroke", + " 0 0 moveto 400 1000 lineto stroke", + " } def", + "", + " % measrpt", + " /period {", + " newpath -450 400 150 0 360 arc fill", + " newpath 450 -400 150 0 360 arc fill", + " 200 setlinewidth", + " -550 -600 moveto 550 600 lineto stroke", + " } def", + "", + " % copyright", + " /slash {", + " lwid setlinewidth", + " newpath 0 400 400 0 360 arc stroke", + " newpath 0 400 200 45 315 arc stroke", + " } def", + "", + " % dim", + " /quoteleft {", + " 50 setlinewidth", + " newpath 0 640 220 0 360 arc stroke", + " } def", + "", + " % halfdim", + " /quoteright {", + " 50 setlinewidth", + " newpath 0 640 220 0 360 arc stroke", + " newpath -340 300 moveto 340 980 lineto stroke", + " } def", + "", + " % triangle", + " /asciicircum {", + " 50 setlinewidth", + " newpath -340 -10 moveto 0 710 lineto", + " 340 -10 lineto closepath stroke", + " } def", + "", + " % qwhrest", + " /ampersand {", + " 300 setlinewidth", + " 0 -600 moveto 0 600 lineto stroke", + " } def", + "", + " % ll1rest", + " /exclam {", + " 310 setlinewidth", + " -400 455 moveto 400 450 lineto stroke", + " } def", + "", + " % ll2rest", + " /at {", + " 310 setlinewidth", + " -400 145 moveto 400 150 lineto stroke", + " } def", + " end", + "", + " /BuildChar {", + "", + " exch begin", + " Encoding exch get", + "", + " dup", + " Mcbbox0 exch get", + " aload pop setcachedevice", + "", + " CharStrings exch get", + " exec", + " end", + " } def", + "end", + "", + "", + "% Define another music character font, since there are too many to fit in one", + "% font. It works the same way as the first one.", + "", + "/mfont1 100 dict def", + "mfont1 begin", + " /FontType 3 def", + " /FontMatrix [ .001 0 0 0.001 0 0 ] def", + " /FontBBox [ -2000 -4030 2000 4030 ] def", + " /FontName (Mfont1) def", + "", + " % set up Encoding vector with standard names", + " /Encoding 256 array def", + " StandardEncoding Encoding copy", + " pop", + "", + " %%%%% define routines that will be used by multiple characters %%%%%", + "", + " /do_dwh_bars {", + " % the two bars surrounding a double whole note", + " lwid setlinewidth", + " -420 -600 moveto -420 600 lineto stroke", + " 420 -600 moveto 420 600 lineto stroke", + " } def", + " /do_righttriangle {", + " newpath", + " 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto", + " 350 150 moveto -140 150 lineto 350 -213 lineto", + " eofill", + " } def", + " /do_fillrighttriangle {", + " newpath", + " 420 270 moveto -420 270 lineto 350 -300 lineto 420 -300 lineto", + " fill", + " } def", + " /do_rectangle {", + " newpath", + " 420 270 moveto -420 270 lineto -420 -270 lineto 420 -270 lineto", + " 350 150 moveto -350 150 lineto -350 -150 lineto 350 -150 lineto", + " eofill", + " } def", + " /do_isostriangle {", + " newpath", + " 0 300 moveto -420 -270 lineto 420 -270 lineto", + " 0 182 moveto -245 -150 lineto 245 -150 lineto", + " eofill", + " } def", + " /do_piewedge {", + " newpath", + " 0 -300 moveto 0 -244 514 35 145 arc", + " 0 -209 moveto 0 -244 394 43 137 arc", + " eofill", + " } def", + " /do_semicircle {", + " newpath", + " gsave", + " 1 1.357 scale 420 199 moveto 0 199 420 180 360 arc", + " 1 1.09 scale 350 111 moveto 0 199 350 194.1 345.9 arc", + " eofill", + " grestore", + " } def", + " /do_slashhead {", + " newpath", + " lwid setlinewidth", + " -620 -530 moveto -480 -670 lineto 620 530 lineto 480 670 lineto", + " closepath stroke", + " } def", + "", + " % subsidiary dictionary of character definitions", + " /CharStrings 128 dict def", + " CharStrings begin", + "", + " /.notdef {} def", + "", + " % Here are the definitions of the characters. A stepsize here", + " % is 300 units (assuming the character is drawn at its default", + " % size).", + "", + " % dwhrighttriangle", + " /A {", + " do_righttriangle", + " do_dwh_bars", + " } def", + "", + " % righttriangle", + " /B {", + " do_righttriangle", + " } def", + "", + " % fillrighttriangle", + " /C {", + " newpath", + " 420 270 moveto -420 270 lineto 350 -300 lineto", + " 420 -300 lineto", + " fill", + " } def", + "", + " % udwhrighttriangle", + " /D {", + " gsave", + " 180 rotate", + " do_righttriangle", + " do_dwh_bars", + " grestore", + " } def", + "", + " % urighttriangle", + " /E {", + " gsave", + " 180 rotate", + " do_righttriangle", + " grestore", + " } def", + "", + " % ufillrighttriangle", + " /F {", + " gsave", + " 180 rotate", + " do_fillrighttriangle", + " grestore", + " } def", + "", + " % dwhrectangle", + " /G {", + " do_rectangle", + " do_dwh_bars", + " } def", + "", + " % rectangle", + " /H {", + " do_rectangle", + " } def", + "", + " % fillrectangle", + " /I {", + " newpath", + " 420 270 moveto -420 270 lineto -420 -270 lineto", + " 420 -270 lineto", + " fill", + " } def", + "", + " % dwhisostriangle", + " /J {", + " do_isostriangle", + " do_dwh_bars", + " } def", + "", + " % isostriangle", + " /K {", + " do_isostriangle", + " } def", + "", + " % fillisostriangle", + " /L {", + " newpath", + " 0 300 moveto -420 -270 lineto 420 -270 lineto", + " fill", + " } def", + "", + " % dwhpiewedge", + " /M {", + " do_piewedge", + " do_dwh_bars", + " } def", + "", + " % piewedge", + " /N {", + " do_piewedge", + " } def", + "", + " % fillpiewedge", + " /O {", + " newpath", + " 0 -300 moveto 0 -244 514 35 145 arc", + " fill", + " } def", + "", + " % dwhsemicircle", + " /P {", + " do_semicircle", + " do_dwh_bars", + " } def", + "", + " % semicircle", + " /Q {", + " do_semicircle", + " } def", + "", + " % fillsemicircle", + " /R {", + " newpath", + " gsave", + " 1 570 420 div scale", + " 420 199 moveto 0 199 420 180 360 arc", + " fill", + " grestore", + " } def", + "", + " % dwhslashhead", + " /S {", + " do_slashhead", + " lwid setlinewidth", + " -650 -600 moveto -650 600 lineto stroke", + " 650 -600 moveto 650 600 lineto stroke", + " } def", + "", + " % slashhead", + " /T {", + " do_slashhead", + " } def", + "", + " % fillslashhead", + " /U {", + " newpath", + " 200 setlinewidth", + " -550 -600 moveto 550 600 lineto stroke", + " } def", + "", + " % blankhead", + " /V {", + " %print nothing", + " } def", + " end", + "", + " /BuildChar {", + "", + " exch begin", + " Encoding exch get", + "", + " dup", + " Mcbbox1 exch get", + " aload pop setcachedevice", + "", + " CharStrings exch get", + " exec", + " end", + " } def", + "end", + "", + "", + "% General routines for printing any music character, invoked by each music", + "% character's specific routine below. The scaling factor (default 1) needs", + "% to be multiplied by 10 to get the actual size. These routines restore the", + "% preexisting current font when they are done.", + "", + "/printmchar0 {", + " gsave", + " /musicchar exch def", + " /Mfont0 findfont exch 10 mul scalefont setfont moveto ", + " musicchar show", + " grestore", + "} def", + "/printmchar1 {", + " gsave", + " /musicchar exch def", + " /Mfont1 findfont exch 10 mul scalefont setfont moveto ", + " musicchar show", + " grestore", + "} def", + "", + "% Define each music character name to be a routine that prints the character.", + "% Each character is to be invoked as in this example:", + "% 100 200 1 gclef % at (100, 200), scale to default size & print", + "", + "/gclef { (A) printmchar0 } def", + "/fclef { (B) printmchar0 } def", + "/cclef { (C) printmchar0 } def", + "/dblwhole { (D) printmchar0 } def", + "/1n { (E) printmchar0 } def", + "/2n { (F) printmchar0 } def", + "/4n { (G) printmchar0 } def", + "/upflag { (H) printmchar0 } def", + "/dnflag { (I) printmchar0 } def", + "/dwhrest { (J) printmchar0 } def", + "/1rest { (K) printmchar0 } def", + "/2rest { (L) printmchar0 } def", + "/4rest { (M) printmchar0 } def", + "/8rest { (N) printmchar0 } def", + "/16rest { (O) printmchar0 } def", + "/32rest { (P) printmchar0 } def", + "/64rest { (Q) printmchar0 } def", + "/128rest { (R) printmchar0 } def", + "/256rest { (S) printmchar0 } def", + "/dot { (T) printmchar0 } def", + "/nat { (U) printmchar0 } def", + "/sharp { (V) printmchar0 } def", + "/flat { (W) printmchar0 } def", + "/dblsharp { (X) printmchar0 } def", + "/dblflat { (Y) printmchar0 } def", + "/xnote { (Z) printmchar0 } def", + "/dwhdiamond { (a) printmchar0 } def", + "/diamond { (b) printmchar0 } def", + "/filldiamond { (c) printmchar0 } def", + "/up2n { (d) printmchar0 } def", + "/dn2n { (e) printmchar0 } def", + "/up4n { (f) printmchar0 } def", + "/dn4n { (g) printmchar0 } def", + "/up8n { (h) printmchar0 } def", + "/dn8n { (i) printmchar0 } def", + "/up16n { (j) printmchar0 } def", + "/dn16n { (k) printmchar0 } def", + "/up32n { (l) printmchar0 } def", + "/dn32n { (m) printmchar0 } def", + "/up64n { (n) printmchar0 } def", + "/dn64n { (o) printmchar0 } def", + "/up128n { (p) printmchar0 } def", + "/dn128n { (q) printmchar0 } def", + "/up256n { (r) printmchar0 } def", + "/dn256n { (s) printmchar0 } def", + "/com { (t) printmchar0 } def", + "/cut { (u) printmchar0 } def", + "/begped { (v) printmchar0 } def", + "/pedal { (w) printmchar0 } def", + "/endped { (x) printmchar0 } def", + "/dnbow { (y) printmchar0 } def", + "/upbow { (z) printmchar0 } def", + "/wedge { (1) printmchar0 } def", + "/uwedge { (2) printmchar0 } def", + "/ferm { (3) printmchar0 } def", + "/uferm { (4) printmchar0 } def", + "/sign { (5) printmchar0 } def", + "/coda { (6) printmchar0 } def", + "/mor { (7) printmchar0 } def", + "/invmor { (8) printmchar0 } def", + "/turn { (9) printmchar0 } def", + "/invturn { (0) printmchar0 } def", + "/acc_gt { (#) printmchar0 } def", + "/acc_hat { ($) printmchar0 } def", + "/acc_uhat { (\") printmchar0 } def", + "/tr { (*) printmchar0 } def", + "/leg { (,) printmchar0 } def", + "/rr { (-) printmchar0 } def", + "/measrpt { (.) printmchar0 } def", + "/copyright { (/) printmchar0 } def", + "/dim { (`) printmchar0 } def", + "/halfdim { (') printmchar0 } def", + "/triangle { (^) printmchar0 } def", + "/qwhrest { (&) printmchar0 } def", + "/ll1rest { (!) printmchar0 } def", + "/ll2rest { (@) printmchar0 } def", + "/dwhrighttriangle { (A) printmchar1 } def", + "/righttriangle { (B) printmchar1 } def", + "/fillrighttriangle { (C) printmchar1 } def", + "/udwhrighttriangle { (D) printmchar1 } def", + "/urighttriangle { (E) printmchar1 } def", + "/ufillrighttriangle { (F) printmchar1 } def", + "/dwhrectangle { (G) printmchar1 } def", + "/rectangle { (H) printmchar1 } def", + "/fillrectangle { (I) printmchar1 } def", + "/dwhisostriangle { (J) printmchar1 } def", + "/isostriangle { (K) printmchar1 } def", + "/fillisostriangle { (L) printmchar1 } def", + "/dwhpiewedge { (M) printmchar1 } def", + "/piewedge { (N) printmchar1 } def", + "/fillpiewedge { (O) printmchar1 } def", + "/dwhsemicircle { (P) printmchar1 } def", + "/semicircle { (Q) printmchar1 } def", + "/fillsemicircle { (R) printmchar1 } def", + "/dwhslashhead { (S) printmchar1 } def", + "/slashhead { (T) printmchar1 } def", + "/fillslashhead { (U) printmchar1 } def", + "/blankhead { (V) printmchar1 } def", + "", + "", + "% Define routines for Mup output other than music characters.", + "", + "/stepsize 3 def % define a step size as 3 points (at default magnification)", + "", + "% x1 y1 x2 lines dist staffscale staff", + "% draw a staff starting at x1, y1 and extending to x2 with \"lines\"", + "% lines, 2*dist*stepsize apart, scaled by staffscale", + "/staff {", + " /staffscale exch def", + " /dist exch def", + " /lines exch def", + " /x2 exch def", + " /y1 exch def", + " /x1 exch def", + " 0.7 staffscale mul sb setlinewidth", + " 1 lines sub 2 lines 1 sub { % loop from bottom line to top line", + " dup stepsize mul staffscale mul dist mul y1 add x1 exch moveto", + " stepsize mul staffscale mul dist mul y1 add x2 exch lineto stroke", + " } for", + "} def", + "", + "% x y1 y2 bracket draw a bracket; y1 is the top", + "/bracket {", + " /y2 exch def", + " /y1 exch def", + " /x exch def", + " gsave", + " 3 setlinewidth", + " x 2 sub y1 1 add moveto", + " x 2 sub y2 1 sub lineto", + " stroke", + " x 2 sub y1 1 add moveto", + " x 1 sub y1 1 add x 3 add y1 1 add x 5 add y1 6 add curveto", + " x 6 add y1 5 add lineto", + " x 5 add y1 2 add x 1 add y1 2 sub x 2 sub y1 2 sub curveto", + " fill", + " x 2 sub y2 1 sub moveto", + " x 1 sub y2 1 sub x 3 add y2 1 sub x 5 add y2 6 sub curveto", + " x 6 add y2 5 sub lineto", + " x 5 add y2 2 sub x 1 add y2 2 add x 2 sub y2 2 add curveto", + " fill", + " grestore", + "} def", + "", + "% x y1 y2 brace draw a brace; y1 is the top", + "/brace {", + " /y2 exch def", + " /y1 exch def", + " /x exch def", + " gsave", + " x 9 sub y1 y2 add 2 div translate", + " /topy y1 y2 sub 2 div 1 sub def", + " 0 1 1 {", + " pop", + " %0 topy moveto 0 0 lineto stroke", + " 0 0 moveto", + " 16 topy 0.2 mul -11 topy 0.6 mul 8 topy curveto", + " 8.7 topy lineto", + " -7 topy 0.7 mul 20 topy 0.3 mul 1 0 curveto", + " fill", + " 1 -1 scale % flip to do bottom half", + " } for", + " grestore", + "} def", + "", + "% endx endy wavy staffscale draw a wavy line from current point to here,", + "% scaled by staffscale", + "/wavy {", + " /staffscale exch def", + " /endy exch def % define the end point of the line", + " /endx exch def", + " currentpoint % line starts at current point", + " /begy exch def % define the beginning point of the line", + " /begx exch def", + " gsave", + " /dx endx begx sub def % find delta x and delta y", + " /dy endy begy sub def", + " /r dx dx mul dy dy mul add sqrt def % hypotenuse", + " /theta dy dx atan def % angle with positive x axis", + " begx begy translate % change axes so that we can draw the line", + " theta rotate % from (0, 0) to (r, 0)", + " staffscale staffscale scale % scale everything by staffscale", + " /scaledr r staffscale div def % but scale r in reverse to keep length", + "", + " % Each outer loop draws one cycle of the squiggle. It continues until", + " % we are at or beyond the desired end point.", + " 0 0 moveto", + " 0 6 scaledr {", + " gsave", + " % first loop draws left half of squiggle; second draws right", + " 0 1 1 {", + " 0.0 0.4 moveto", + " 2.0 1.9 3.4 2.3 3.9 0.0 curveto", + " 2.1 0.0 lineto", + " 1.9 0.8 1.4 0.7 0.0 -0.4 curveto", + " fill", + " pop 180 rotate -6 0 translate", + " } for", + " grestore", + "", + " pop 6 0 translate % shift axes right one squiggle", + " } for", + "", + " grestore", + "} def", + "", + "% x y space frets fretno numvert curvel curver [ f1 f2 f3 ... ] grid", + "% print a guitar grid diagram", + "/grid {", + " /grid_positions exch def % 0=\"o\", -1=\"x\", -2=nothing, positive=dot", + " /curver exch def % right string for curve, 0 if none", + " /curvel exch def % left string for curve, 0 if none", + " /numvert exch def % vertical position to print fretno, 0 if none", + " /fretno exch def % fret no. to print at right, 0 if none", + " /frets exch def % number of fret lines", + " /space exch def % points between two neighboring lines", + " /y exch def % y coord of top fret line", + " /x exch def % x coord of left strings", + "", + " gsave", + " /strings grid_positions length def % number of strings", + " /lmarky 0.4 space mul y add def % lowest Y of a \"o\" or \"x\"", + " space 10 div setlinewidth", + " 2 setlinecap", + "", + " % draw the lines of the grid", + " 0 1 strings 1 sub { % loop from left string to right string", + " dup space mul x add y moveto", + " space mul x add frets 1 sub space mul y exch sub lineto stroke", + " } for", + " 0 -1 1 frets sub { % loop from top fret (nut) to bottom fret", + " dup space mul y add x exch moveto", + " space mul y add strings 1 sub space mul x add exch lineto stroke", + " } for", + "", + " % draw the curved line if there is one", + " curvel 0 gt {", + " % within strings curvel to curver, find smallest positive fret", + " /minfret 1000 def", + " curvel 1 curver {", + " /strno exch def", + " /grid_p grid_positions strno 1 sub get def", + " grid_p 0 gt grid_p minfret lt and {", + " /minfret grid_p def", + " } if", + " } for", + "", + " % if curve goes above top fret, other marks must be higher", + " minfret 1 eq {", + " /hmarky 1.2 space mul y add def", + " } {", + " /hmarky lmarky def", + " } ifelse", + "", + " /strdiff curver curvel sub def", + " space 8 div setlinewidth", + "", + " % set endpoint coords of curve; higher if curve is short", + " /curvex1 curvel 1 sub space mul x add def", + " /curvex2 curver 1 sub space mul x add def", + " /curvey 1 minfret sub space mul y add def", + " strdiff 3 lt {", + " /curvey 0.2 strdiff div space mul curvey add def", + " } if", + "", + " % move to left end, set other points, draw curve", + " curvex1 curvey moveto", + "", + " curvex1 curvex2 curvex1 sub 3 div add", + " curvey space 0.4 strdiff sqrt mul mul add", + "", + " curvex2 curvex2 curvex1 sub 3 div sub", + " curvey space 0.4 strdiff sqrt mul mul add", + "", + " curvex2 curvey curveto stroke", + " } if", + "", + " space 10 div setlinewidth", + "", + " % draw dots and x and o marks", + " 0 1 strings 1 sub { % loop from left string to right string", + " /strno exch def % first string is 0", + " /grid_p grid_positions strno get def", + " /strx strno space mul x add def", + "", + " % set Y of mark higher if curved line covers this string", + " strno 1 add curvel ge strno 1 add curver le and {", + " /marky hmarky def", + " } {", + " /marky lmarky def", + " } ifelse", + "", + " grid_p -1 eq { % draw an X above the string", + " /xhwid space 3 div def", + " strx xhwid sub marky xhwid sub moveto", + " strx xhwid add marky xhwid add lineto stroke", + " strx xhwid sub marky xhwid add moveto", + " strx xhwid add marky xhwid sub lineto stroke", + " } if", + " grid_p 0 eq { % draw a circle above the string", + " strx marky space 0.3 mul 0 360 arc stroke", + " } if", + " grid_p 1 ge { % draw a dot by the proper fret", + " strx y grid_p space mul sub space 3 div add", + " space 3 div 0 360 arc fill", + " } if", + " } for", + "", + " % print \"X fr\" if requested", + " fretno 0 gt {", + " /Palatino-Roman findfont space 1.9 mul scalefont setfont", + " x strings 0.5 sub space mul add", + " y space numvert 0.3 add mul sub moveto", + " fretno 2 string cvs show ( fr) show", + " } if", + " grestore", + "} def", + "", + "% x1 y1 x2 y2 whitebox draw a white rectangle with opposite", + "% corners of (x1,y1) and (x2,y2)", + "/whitebox {", + " /y2 exch def", + " /x2 exch def", + " /y1 exch def", + " /x1 exch def", + " 1.0 setgray", + " newpath", + " x1 y1 moveto", + " x1 y2 lineto", + " x2 y2 lineto", + " x2 y1 lineto", + " closepath", + " fill", + " stroke", + " 0.0 setgray", + "} def", + "", + "", + "/LineNum 0 def", + "/InputFile (unknown) def", + "", + "% n linenum", + "/linenum {", + " /LineNum exch def", + "} def", + "", + "% (inputfilename) inputfile", + "/inputfile {", + " /InputFile exch def", + "} def", + "", + "% find size of Encoding and make a dictionary", + "% that size for bounding box information", + "mfont0 begin", + "/dictsize Encoding length def", + "mfont0 /Mcbbox0 dictsize dict put", + "", + "% temporarily redefine printmchar0 to get code", + "5 dict begin", + "/printmchar0 { {} forall } def", + "", + "Mcbbox0 Encoding 128rest get [ 1140.0 0 -515.0 -1515.0 615.0 1685.0 ] put", + "Mcbbox0 Encoding 16rest get [ 830.0 0 -415.0 -1215.0 405.0 485.0 ] put", + "Mcbbox0 Encoding 1n get [ 1080.0 0 -535.0 -335.0 535.0 345.0 ] put", + "Mcbbox0 Encoding 1rest get [ 1540.0 0 -765.0 -5.0 765.0 645.0 ] put", + "Mcbbox0 Encoding 256rest get [ 1250.0 0 -625.0 -2115.0 615.0 1685.0 ] put", + "Mcbbox0 Encoding 2n get [ 880.0 0 -435.0 -345.0 435.0 355.0 ] put", + "Mcbbox0 Encoding 2rest get [ 1540.0 0 -765.0 -45.0 765.0 315.0 ] put", + "Mcbbox0 Encoding 32rest get [ 940.0 0 -415.0 -1215.0 515.0 1085.0 ] put", + "Mcbbox0 Encoding 4n get [ 840.0 0 -415.0 -335.0 415.0 345.0 ] put", + "Mcbbox0 Encoding 4rest get [ 650.0 0 -345.0 -885.0 295.0 985.0 ] put", + "Mcbbox0 Encoding 64rest get [ 1040.0 0 -515.0 -1515.0 515.0 1085.0 ] put", + "Mcbbox0 Encoding 8rest get [ 750.0 0 -305.0 -615.0 435.0 485.0 ] put", + "Mcbbox0 Encoding acc_gt get [ 1170.0 0 -525.0 -335.0 635.0 345.0 ] put", + "Mcbbox0 Encoding acc_hat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put", + "Mcbbox0 Encoding acc_uhat get [ 780.0 0 -385.0 -5.0 385.0 875.0 ] put", + "Mcbbox0 Encoding begped get [ 470.0 0 -245.0 -45.0 215.0 615.0 ] put", + "Mcbbox0 Encoding cclef get [ 1540.0 0 -765.0 -1245.0 765.0 1255.0 ] put", + "Mcbbox0 Encoding coda get [ 1640.0 0 -815.0 -855.0 815.0 865.0 ] put", + "Mcbbox0 Encoding com get [ 1100.0 0 -575.0 -635.0 515.0 655.0 ] put", + "Mcbbox0 Encoding copyright get [ 920.0 0 -455.0 -45.0 455.0 855.0 ] put", + "Mcbbox0 Encoding cut get [ 1100.0 0 -575.0 -905.0 515.0 915.0 ] put", + "Mcbbox0 Encoding dblflat get [ 1170.0 0 -595.0 -405.0 565.0 1115.0 ] put", + "Mcbbox0 Encoding dblsharp get [ 720.0 0 -355.0 -345.0 355.0 355.0 ] put", + "Mcbbox0 Encoding dblwhole get [ 1090.0 0 -535.0 -605.0 545.0 615.0 ] put", + "Mcbbox0 Encoding diamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put", + "Mcbbox0 Encoding dim get [ 540.0 0 -265.0 -5.0 265.0 905.0 ] put", + "Mcbbox0 Encoding dn128n get [ 840.0 0 -415.0 -3545.0 415.0 345.0 ] put", + "Mcbbox0 Encoding dn16n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put", + "Mcbbox0 Encoding dn256n get [ 840.0 0 -415.0 -3965.0 415.0 345.0 ] put", + "Mcbbox0 Encoding dn2n get [ 880.0 0 -435.0 -2105.0 435.0 355.0 ] put", + "Mcbbox0 Encoding dn32n get [ 840.0 0 -415.0 -2585.0 415.0 345.0 ] put", + "Mcbbox0 Encoding dn4n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put", + "Mcbbox0 Encoding dn64n get [ 840.0 0 -415.0 -3065.0 415.0 345.0 ] put", + "Mcbbox0 Encoding dn8n get [ 840.0 0 -415.0 -2105.0 415.0 345.0 ] put", + "Mcbbox0 Encoding dnbow get [ 810.0 0 -395.0 -5.0 405.0 915.0 ] put", + "Mcbbox0 Encoding dnflag get [ 640.0 0 -335.0 -1705.0 295.0 15.0 ] put", + "Mcbbox0 Encoding dot get [ 280.0 0 -135.0 -125.0 135.0 135.0 ] put", + "Mcbbox0 Encoding dwhdiamond get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put", + "Mcbbox0 Encoding dwhrest get [ 340.0 0 -165.0 -5.0 165.0 615.0 ] put", + "Mcbbox0 Encoding endped get [ 480.0 0 -215.0 -45.0 255.0 615.0 ] put", + "Mcbbox0 Encoding fclef get [ 1840.0 0 -1015.0 -1705.0 815.0 655.0 ] put", + "Mcbbox0 Encoding ferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put", + "Mcbbox0 Encoding filldiamond get [ 880.0 0 -435.0 -305.0 435.0 315.0 ] put", + "Mcbbox0 Encoding flat get [ 580.0 0 -295.0 -405.0 275.0 1115.0 ] put", + "Mcbbox0 Encoding gclef get [ 1790.0 0 -915.0 -1605.0 865.0 3015.0 ] put", + "Mcbbox0 Encoding halfdim get [ 760.0 0 -375.0 -5.0 375.0 1015.0 ] put", + "Mcbbox0 Encoding invmor get [ 1320.0 0 -655.0 -455.0 655.0 465.0 ] put", + "Mcbbox0 Encoding invturn get [ 1300.0 0 -645.0 -335.0 645.0 345.0 ] put", + "Mcbbox0 Encoding leg get [ 840.0 0 -415.0 -55.0 415.0 65.0 ] put", + "Mcbbox0 Encoding ll1rest get [ 840.0 0 -415.0 -5.0 415.0 625.0 ] put", + "Mcbbox0 Encoding ll2rest get [ 840.0 0 -415.0 -15.0 415.0 315.0 ] put", + "Mcbbox0 Encoding measrpt get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put", + "Mcbbox0 Encoding mor get [ 1320.0 0 -655.0 -285.0 655.0 295.0 ] put", + "Mcbbox0 Encoding nat get [ 520.0 0 -255.0 -855.0 255.0 865.0 ] put", + "Mcbbox0 Encoding pedal get [ 1040.0 0 -515.0 -45.0 515.0 675.0 ] put", + "Mcbbox0 Encoding qwhrest get [ 340.0 0 -165.0 -605.0 165.0 615.0 ] put", + "Mcbbox0 Encoding rr get [ 940.0 0 -465.0 -25.0 465.0 1035.0 ] put", + "Mcbbox0 Encoding sharp get [ 700.0 0 -345.0 -935.0 345.0 945.0 ] put", + "Mcbbox0 Encoding sign get [ 1340.0 0 -665.0 -825.0 665.0 835.0 ] put", + "Mcbbox0 Encoding tr get [ 1440.0 0 -715.0 -5.0 715.0 1015.0 ] put", + "Mcbbox0 Encoding triangle get [ 800.0 0 -395.0 -45.0 395.0 785.0 ] put", + "Mcbbox0 Encoding turn get [ 1300.0 0 -645.0 -325.0 645.0 345.0 ] put", + "Mcbbox0 Encoding uferm get [ 1640.0 0 -815.0 -5.0 815.0 1015.0 ] put", + "Mcbbox0 Encoding up128n get [ 1390.0 0 -745.0 -335.0 635.0 3555.0 ] put", + "Mcbbox0 Encoding up16n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put", + "Mcbbox0 Encoding up256n get [ 1390.0 0 -745.0 -335.0 635.0 3975.0 ] put", + "Mcbbox0 Encoding up2n get [ 880.0 0 -435.0 -345.0 435.0 2115.0 ] put", + "Mcbbox0 Encoding up32n get [ 1390.0 0 -745.0 -335.0 635.0 2595.0 ] put", + "Mcbbox0 Encoding up4n get [ 850.0 0 -415.0 -335.0 425.0 2115.0 ] put", + "Mcbbox0 Encoding up64n get [ 1390.0 0 -745.0 -335.0 635.0 3075.0 ] put", + "Mcbbox0 Encoding up8n get [ 1390.0 0 -745.0 -335.0 635.0 2115.0 ] put", + "Mcbbox0 Encoding upbow get [ 720.0 0 -355.0 -115.0 355.0 925.0 ] put", + "Mcbbox0 Encoding upflag get [ 640.0 0 -335.0 -5.0 295.0 1715.0 ] put", + "Mcbbox0 Encoding uwedge get [ 340.0 0 -165.0 -5.0 165.0 505.0 ] put", + "Mcbbox0 Encoding wedge get [ 340.0 0 -165.0 5.0 165.0 515.0 ] put", + "Mcbbox0 Encoding xnote get [ 880.0 0 -435.0 -365.0 435.0 375.0 ] put", + "", + "end", + "end", + "", + "/Mfont0 mfont0 definefont", + "", + "", + "% find size of Encoding and make a dictionary", + "% that size for bounding box information", + "mfont1 begin", + "/dictsize Encoding length def", + "mfont1 /Mcbbox1 dictsize dict put", + "", + "% temporarily redefine printmchar1 to get code", + "5 dict begin", + "/printmchar1 { {} forall } def", + "", + "Mcbbox1 Encoding blankhead get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put", + "Mcbbox1 Encoding dwhisostriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put", + "Mcbbox1 Encoding dwhpiewedge get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put", + "Mcbbox1 Encoding dwhrectangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put", + "Mcbbox1 Encoding dwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put", + "Mcbbox1 Encoding dwhsemicircle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put", + "Mcbbox1 Encoding dwhslashhead get [ 1410.0 0 -695.0 -725.0 705.0 735.0 ] put", + "Mcbbox1 Encoding fillisostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put", + "Mcbbox1 Encoding fillpiewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put", + "Mcbbox1 Encoding fillrectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put", + "Mcbbox1 Encoding fillrighttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put", + "Mcbbox1 Encoding fillsemicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put", + "Mcbbox1 Encoding fillslashhead get [ 1300.0 0 -645.0 -675.0 645.0 685.0 ] put", + "Mcbbox1 Encoding isostriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put", + "Mcbbox1 Encoding piewedge get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put", + "Mcbbox1 Encoding rectangle get [ 880.0 0 -435.0 -275.0 435.0 285.0 ] put", + "Mcbbox1 Encoding righttriangle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put", + "Mcbbox1 Encoding semicircle get [ 880.0 0 -435.0 -305.0 435.0 285.0 ] put", + "Mcbbox1 Encoding slashhead get [ 1380.0 0 -685.0 -725.0 685.0 735.0 ] put", + "Mcbbox1 Encoding udwhrighttriangle get [ 950.0 0 -465.0 -605.0 475.0 615.0 ] put", + "Mcbbox1 Encoding ufillrighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put", + "Mcbbox1 Encoding urighttriangle get [ 880.0 0 -435.0 -275.0 435.0 315.0 ] put", + "", + "end", + "end", + "", + "/Mfont1 mfont1 definefont", + "", + "/makeExtEncoding {", + " /extendedencoding 256 array def", + " StandardEncoding extendedencoding copy", + " extendedencoding 32 /exclamdown put", + " extendedencoding 33 /cent put", + " extendedencoding 34 /sterling put", + " extendedencoding 35 /yen put", + " extendedencoding 36 /quotedblleft put", + " extendedencoding 37 /guillemotleft put", + " extendedencoding 38 /guillemotright put", + " extendedencoding 39 /guilsinglleft put", + " extendedencoding 40 /guilsinglright put", + " extendedencoding 41 /dagger put", + " extendedencoding 42 /daggerdbl put", + " extendedencoding 43 /bullet put", + " extendedencoding 44 /quotedblbase put", + " extendedencoding 45 /quotedblright put", + " extendedencoding 46 /questiondown put", + " extendedencoding 47 /grave put", + " extendedencoding 48 /acute put", + " extendedencoding 49 /macron put", + " extendedencoding 50 /breve put", + " extendedencoding 51 /dotaccent put", + " extendedencoding 52 /dieresis put", + " extendedencoding 53 /ring put", + " extendedencoding 54 /cedilla put", + " extendedencoding 55 /hungarumlaut put", + " extendedencoding 56 /ogonek put", + " extendedencoding 57 /caron put", + " extendedencoding 58 /emdash put", + " extendedencoding 59 /AE put", + " extendedencoding 60 /ae put", + " extendedencoding 61 /ordfeminine put", + " extendedencoding 62 /ordmasculine put", + " extendedencoding 63 /Lslash put", + " extendedencoding 64 /lslash put", + " extendedencoding 65 /Oslash put", + " extendedencoding 66 /oslash put", + " extendedencoding 67 /OE put", + " extendedencoding 68 /oe put", + " extendedencoding 69 /dotlessi put", + " extendedencoding 70 /germandbls put", + " extendedencoding 71 /Aacute put", + " extendedencoding 72 /aacute put", + " extendedencoding 73 /Acircumflex put", + " extendedencoding 74 /acircumflex put", + " extendedencoding 75 /Adieresis put", + " extendedencoding 76 /adieresis put", + " extendedencoding 77 /Agrave put", + " extendedencoding 78 /agrave put", + " extendedencoding 79 /Aring put", + " extendedencoding 80 /aring put", + " extendedencoding 81 /Atilde put", + " extendedencoding 82 /atilde put", + " extendedencoding 83 /Ccedilla put", + " extendedencoding 84 /ccedilla put", + " extendedencoding 85 /Eacute put", + " extendedencoding 86 /eacute put", + " extendedencoding 87 /Ecircumflex put", + " extendedencoding 88 /ecircumflex put", + " extendedencoding 89 /Edieresis put", + " extendedencoding 90 /edieresis put", + " extendedencoding 91 /Egrave put", + " extendedencoding 92 /egrave put", + " extendedencoding 93 /Iacute put", + " extendedencoding 94 /iacute put", + " extendedencoding 95 /Icircumflex put", + " extendedencoding 96 /icircumflex put", + " extendedencoding 97 /Idieresis put", + " extendedencoding 98 /idieresis put", + " extendedencoding 99 /Igrave put", + " extendedencoding 100 /igrave put", + " extendedencoding 101 /Ntilde put", + " extendedencoding 102 /ntilde put", + " extendedencoding 103 /Oacute put", + " extendedencoding 104 /oacute put", + " extendedencoding 105 /Ocircumflex put", + " extendedencoding 106 /ocircumflex put", + " extendedencoding 107 /Odieresis put", + " extendedencoding 108 /odieresis put", + " extendedencoding 109 /Ograve put", + " extendedencoding 110 /ograve put", + " extendedencoding 111 /Otilde put", + " extendedencoding 112 /otilde put", + " extendedencoding 113 /Scaron put", + " extendedencoding 114 /scaron put", + " extendedencoding 115 /Uacute put", + " extendedencoding 116 /uacute put", + " extendedencoding 117 /Ucircumflex put", + " extendedencoding 118 /ucircumflex put", + " extendedencoding 119 /Udieresis put", + " extendedencoding 120 /udieresis put", + " extendedencoding 121 /Ugrave put", + " extendedencoding 122 /ugrave put", + " extendedencoding 123 /Ydieresis put", + " extendedencoding 124 /ydieresis put", + " extendedencoding 125 /Zcaron put", + " extendedencoding 126 /zcaron put", + " extendedencoding 127 /space put", + "} def", + "", + "/makeExtendedFont {", + " findfont", + " dup length dict /newdict exch def", + " { 1 index /FID ne", + " { newdict 3 1 roll put }", + " { pop pop }", + " ifelse", + " } forall", + " newdict /Encoding extendedencoding put", + " newdict /UniqueID newdict /UniqueID get 1 add put", + " newdict definefont pop", + "} def", +(char *) 0 +}; + +/* generate the PostScript prolog */ + +void +ps_prolog() +{ + int line; + + for (line = 0; prolog_text[line] != (char *) 0; line++) { + (void) printf("%s\n", prolog_text[line]); + } +} diff --git a/mup/mup/range.c b/mup/mup/range.c new file mode 100644 index 0000000..c7cc22c --- /dev/null +++ b/mup/mup/range.c @@ -0,0 +1,432 @@ + +/* Copyright (c) 1995, 1997, 1998, 1999, 2002, 2004 by Arkkra Enterprises */ +/* All rights reserved */ + +/* Functions for saving away ranges of staff numbers or vno's when user + * is defining groups, lyrics, or stuff for one or more staffs and/or + * voices/verses. */ + + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* special marker for "all." use something that can't possibly be a staff num */ +#define ALL (-1) + + +static void free_rangelist P((struct RANGELIST *list_p)); + + + +/* When a line of input is being gathered for groups, lyrics, or stuff, + * this function should be called first. It makes + * sure the current range list is set to empty and makes a note of the place, + * (PL_ABOVE, PL_BELOW, or PL_BETWEEN) for later reference + */ + +void +begin_range(place) + +int place; /* PL_ABOVE, etc */ + +{ + Staffrange_p = (struct RANGELIST *) 0; + Vnorange_p = (struct RANGELIST *) 0; + Place = (short) place; +} + + +/* 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; +} + + +/* 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; +} + + +/* 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(); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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'"); + } +} + + +/* 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; + } + } +} + + +/* 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"); +} + + +/* start a new staff-voice list */ + +void +begin_sv_list() + +{ + Svrangelist_p = (struct SVRANGELIST *) 0; +} + + +/* 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; +} + + +/* 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); +} + + +/* return the staff number of the first staff on the current list of staffs. + * In this context, the "first staff" means the first staff the user defined, + * so if they said something like 5,6,9-12,2 this would return 5 */ + +int +leadstaff() + +{ + struct RANGELIST *r_p; + + if (Staffrange_p == (struct RANGELIST *) 0) { + pfatal("leadstaff called when no staffs on list"); + } + + /* since new ranges are linked onto the head of the list, we need + * to find the last range on the list. That will be the first one + * the user specified. */ + for (r_p = Staffrange_p; r_p->next != (struct RANGELIST *) 0; + r_p = r_p->next) { + ; + } + return(r_p->begin); +} diff --git a/mup/mup/rational.c b/mup/mup/rational.c new file mode 100644 index 0000000..90bf411 --- /dev/null +++ b/mup/mup/rational.c @@ -0,0 +1,1158 @@ +/* Copyright (c) 1995, 1996, 2001 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * rational.c functions to do operations on rational numbers + * + * Contents: + * + * radd(), rsub(), rmul(), rdiv(), rneg(), rinv(), rrai(), rred(), + * ator(), rtoa(); also gtrat(), called by macros GT,GE,LT,LE + * + * ratmsg(), add64_64(), mul32_64(), divmod64(), red64_64() + * + * The first group of functions are for the user. The second + * are for internal use only. + * + * Description: + * The functions in this file do operations on rational numbers. + * The rational arguments to functions that the users can call + * must be in standard form (lowest terms, with positive + * denominator) except for rred(). There are checks for division + * by zero and for overflow of numerators and denominators. + * (The absolute values of each are limited to MAXLONG, defined + * in rational.h.) If there is an error, the external int + * raterrno is set to RATDIV0 or RATOVER, as the case may be, + * and *raterrfuncp is checked. If nonzero, it is assumed to + * point at the user's error handler, and it is called with a + * parameter equal to raterrno. Otherwise, a message is printed + * to stderr. In any case, the answer returned to the user is + * 0/1. If there was no error, raterrno is set to RATNOERR. + * + * In general, the functions assume they are being called with + * valid parameters. If they are not, results are not guaranteed + * to be correct. However, they are defensive enough so that + * invalid parameters will not cause a crash in these routines. + * They will not always detect invalid parameters, but if they + * do, they will use the raterrno/raterrfuncp mechanism described + * above, with the value RATPARM. + * + * These routines depend on a INT32B being a 32-bit number, + * stored in two's complement form, and UINT32B being the same + * for unsigned. See rational.h. Numerators and denominators + * are assumed to be INT32B. Furthermore, the number 0x80000000 + * is not allowed. The routines should work on any machine and + * compiler where these requirements are met. + * + * Internally, when 64-bit numbers are used, they are represented + * by an array of two INT32B. The 0 subscript contains the low + * order bits and the 1 subscript contains the high order bits. + * The numbers are usually used as two's complement signed + * integers, so the high bit of the 1 subscript is a sign bit. + */ + +#ifndef stderr +# include +#endif + +#ifndef isspace +# include +#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}; + +/* + * 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); +} + +/* + * 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)); +} + +/* + * 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); +} + +/* + * 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)); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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)); +} + +/* + * 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); + } +} + +/* + * 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]; +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * red64_64() reduce a 64 bit over 64 bit rational to lowest terms + * + * This function takes two 64-bit numbers as numerator and denominator + * of a rational number, and reduces them to lowest terms, with the + * denominator positive. If the user called this package correctly, the + * denominator cannot be zero, but to be defensive we check for that, and + * if it happens, set raterrno to RATPARM and either print a message or + * call a user-supplied error handler. + * + * Parameters: num numerator + * den denominator + * + * Return value: none + * + * Side effects: num and den are altered to be the result + */ + +static void +red64_64(num, den) + +INT32B num[2]; +INT32B den[2]; + +{ + INT32B b[2], c[2], r[2]; /* temp variables for Euclidean algorithm */ + INT32B junk[2]; /* placeholder for calling divmod64 */ + int sign; /* answer is pos (1) or neg (-1) */ + + + if (den[1] == 0 && den[0] == 0) { /* if den == 0 */ + /* + * This is an error. The user must have called a routine with + * an invalid number for us to get here, in fact a number with + * a zero denominator, since "den" here always was created as + * the product of denominators. Report the error and return + * zero. + */ + num[1] = 0; /* set num = 0 */ + num[0] = 0; + den[1] = 0; /* set den = 1 */ + den[0] = 1; + ratmsg(RATPARM); /* set raterrno, report error */ + return; + } + + if (num[1] == 0 && num[0] == 0) { /* if num == 0 */ + den[1] = 0; /* set den = 1; answer is 0/1 */ + den[0] = 1; + return; + } + + /* now figure out sign of answer, and make num & den positive */ + sign = 1; /* init to positive */ + if (num[1] < 0) { /* if numerator neg */ + sign = -sign; /* reverse the sign */ + NEG64(num); + } + if (den[1] < 0) { /* if denominator neg */ + sign = -sign; /* reverse the sign */ + NEG64(den); + } + + /* now check whether numerator or denominator is larger */ + if (EQ64(num, den)) { + num[0] = sign; /* answer is +1 or -1 */ + + if (sign < 0) /* set high order word to sign bit */ + num[1] = -1; + else + num[1] = 0; + + den[1] = 0; /* set den to 1 */ + den[0] = 1; + + return; + } + + /* set up c and b so that one is num, the other den, and c > b */ + if (LT64(num, den)) { /* if num < den */ + c[0] = den[0]; /* c = den */ + c[1] = den[1]; + b[0] = num[0]; /* b = num */ + b[1] = num[1]; + } else { + c[0] = num[0]; /* c = num */ + c[1] = num[1]; + b[0] = den[0]; /* b = den */ + b[1] = den[1]; + } + + /* use Euclidean Algorithm to find greatest common divisor of c & b */ + do { + divmod64(c, b, junk, r); /* r = c % b */ + c[0] = b[0]; /* c = b */ + c[1] = b[1]; + b[0] = r[0]; /* b = r */ + b[1] = r[1]; + } while (r[0] != 0 || r[1] != 0); /* while r != 0 */ + + /* now c is the greatest common divisor of num and den */ + + /* divide out the greatest common divisor and put the sign in */ + divmod64(num, c, num, junk); /* num /= c */ + if (sign < 0) /* if should be negative */ + NEG64(num); /* negate the numerator */ + divmod64(den, c, den, junk); /* den /= c */ + + return; +} diff --git a/mup/mup/rational.h b/mup/mup/rational.h new file mode 100644 index 0000000..8530dca --- /dev/null +++ b/mup/mup/rational.h @@ -0,0 +1,108 @@ +/* Copyright (c) 1995, 1996, 1997, 2001 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * rational.h definitions for using rational numbers + */ +#ifndef _RATIONAL +#define _RATIONAL + + +/* + * The code in rational.h/rational.c is written in a way that depends on + * certain variables being 32-bit numbers stored in two's complement form. For + * most compilers, "long" works for this, but for some compilers, "long" is + * 64 bits, or maybe something else. C standards after (and not including) the + * 1994 version guarantee the existence of a header file stdint.h which defines + * typedefs int32_t and uint32_t. So for those standards we will use those + * typedefs from that header when defining our INT32B and UINT32B. Otherwise + * we will just use long and unsigned long. If these aren't 32-bit, two's + * complement, you will have to change this code. + */ +#if __STDC_VERSION__ > 199409L +#include +#define INT32B int32_t +#define UINT32B uint32_t +#else +#define INT32B long +#define UINT32B unsigned long +#endif + +/* + * Define the structure that represents a rational number. The number + * should be kept in standard form; that is, in lowest terms with a positive + * denominator. Zero should be stored as 0/1. + */ +struct rational { + INT32B n; /* numerator */ + INT32B d; /* denominator */ +}; + +typedef struct rational RATIONAL; + + +/* macros for comparing rational numbers */ +/* numbers must be in standard form */ + +#define EQ(a, b) ((a).n == (b).n && (a).d == (b).d) +#define NE(a, b) ((a).n != (b).n || (a).d != (b).d) + +/* must call function for inequalities, because overflow possibilities */ + +#define GT(a, b) gtrat(a, b) +#define LT(a, b) gtrat(b, a) +#define GE(a, b) ( ! gtrat(b, a) ) +#define LE(a, b) ( ! gtrat(a, b) ) + + +/* macros for testing a rational number */ +/* numbers must be in standard form, or at least have positive denominator */ + +#define ZE(a) ((a).n == 0) +#define PL(a) ((a).n > 0) +#define MI(a) ((a).n < 0) +#define NZ(a) ((a).n != 0) +#define NM(a) ((a).n >= 0) +#define NP(a) ((a).n <= 0) + + +/* definitions for error handling */ + +#define RATNOERR 0 +#define RATOVER 1 +#define RATDIV0 2 +#define RATPARM 3 + +#ifndef MAXLONG +#define MAXLONG 0x7fffffff +#endif + +extern int raterrno; /* holds error code */ +#ifdef __STDC__ +extern void (*raterrfuncp)(int); /* pointer to user error handler */ +#else +extern void (*raterrfuncp)(); /* pointer to user error handler */ +#endif + + +/* functions to do operations on rational numbers */ + +#ifdef __STDC__ +extern RATIONAL radd(RATIONAL x, RATIONAL y); +extern RATIONAL rsub(RATIONAL x, RATIONAL y); +extern RATIONAL rmul(RATIONAL x, RATIONAL y); +extern RATIONAL rdiv(RATIONAL x, RATIONAL y); +extern RATIONAL rneg(RATIONAL x); +extern RATIONAL rinv(RATIONAL x); +extern RATIONAL rrai(RATIONAL x, int n); +extern void rred(RATIONAL *ap); +extern char *ator(RATIONAL *rp, char s[]); +extern char *rtoa(char s[], RATIONAL *rp); +extern int gtrat(RATIONAL x, RATIONAL y); +#else +extern RATIONAL radd(), rsub(), rmul(), rdiv(), rneg(), rinv(), rrai(); +extern void rred(); +extern char *ator(), *rtoa(); +extern int gtrat(); +#endif + +#endif diff --git a/mup/mup/relvert.c b/mup/mup/relvert.c new file mode 100644 index 0000000..f0b623e --- /dev/null +++ b/mup/mup/relvert.c @@ -0,0 +1,2758 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: relvert.c + * + * Description: This file contains functions for setting all remaining + * relative vertical coordinates. + */ + +#include +#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)); + +/* + * 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); +} + +/* + * 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; + } + } +} + +/* + * 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(); +} + +/* + * 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); + } + } +} + +/* + * 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(); + } + } + } +} + +/* + * 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); + } + } + } + } + } +} + +/* + * 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)); +} + +/* + * 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); +} + +/* + * 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(); + } +} + +/* + * 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); + } + } + } +} + +/* + * 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); + } + } +} + +/* + * 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(); + } +} + +/* + * 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); + } + } + } + } + } +} + +/* + * 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)); +} + +/* + * 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; + } + } +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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(); + } +} + +/* + * 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; + } +} + +/* + * 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; + } +} + +/* + * 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); + } + } +} + +/* + * 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); +} + +/* + * Name: inc_reclim() + * + * Abstract: Increment no. of rectangles, and realloc more if we run out. + * + * Returns: void + * + * Description: This function increments reclim, the index into rectab. If it + * finds that rectab[reclim] is now beyond the end of the space + * that's been allocated, it does a realloc to get more space. + */ + +static void +inc_reclim() +{ + /* when first called, relvert will have allocated this many */ + static int rectabsize = RECTCHUNK; + + + reclim++; + + /* if rectab[reclim] is still valid, no need to allocate more */ + if (reclim < rectabsize) + return; + + /* must allocate another chunk of rectangles */ + rectabsize += RECTCHUNK; + REALLOC(RECTAB, rectab, rectabsize); +} diff --git a/mup/mup/restsyl.c b/mup/mup/restsyl.c new file mode 100644 index 0000000..54a006b --- /dev/null +++ b/mup/mup/restsyl.c @@ -0,0 +1,2682 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: restsyl.c + * + * Description: This file contains functions for setting the relative + * horizontal and vertical coordinates of all groups that + * contain a rest or space (grpcont != GC_NOTES), and the relative + * horizontal coordinates of syllables. It then completes + * the relative horizontal work by setting the relative + * horizontal coords of chords. But before it does that last + * step, it scales all the relative coords set so far according + * to staffscale. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +#define PK_LEFT (0) +#define PK_RIGHT (1) +#define PK_CENTER (2) +#define PK_NONE (3) + +static double highcoord P((struct GRPSYL *gs_p, struct GRPSYL *altgs_p)); +static double lowcoord P((struct GRPSYL *gs_p, struct GRPSYL *altgs_p)); +static void procrests P((struct CHORD *ch_p, struct STAFF *staff_p, + struct GRPSYL *gs_p, double limhigh, double limlow)); +static void procspaces P((struct GRPSYL *gs_p)); +static struct GRPSYL *finalgroupproc P((struct GRPSYL *gs1_p)); +static int v3pack P((struct GRPSYL *g_p[], int numgrps)); +static void fixclef P((struct GRPSYL *gs1_p)); +static void restsize P((struct GRPSYL *gs_p, float *wid_p, float *asc_p, + float *des_p)); +static void procsyls P((struct GRPSYL *gs_p)); +static void apply_staffscale P((void)); +static void relxchord P((void)); +static double effwest P((struct MAINLL *mainll_p, struct CHORD *ch_p, + struct GRPSYL *gs_p)); +static double effeast P((struct CHORD *ch_p, struct GRPSYL *gs_p)); +static int collision_danger P((struct GRPSYL *g1_p, struct GRPSYL *g2_p)); +static struct CHORD *prevchord P((struct MAINLL *mainll_p, struct CHORD *ch_p)); +static struct GRPSYL *nextchsyl P((struct GRPSYL *gs_p, struct CHORD *ch_p)); +static struct GRPSYL *prevchsyl P((struct GRPSYL *gs_p, + struct CHORD *prevch_p)); +static void pedalroom P((void)); +static struct CHORD *closestchord P((double count, struct CHORD *firstch_p)); +static double rightped P((int pedstyle, int pedchar)); +static double leftped P((int pedstyle, int pedchar)); +static void fixspace P((void)); + +/* + * 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(); +} + +/* + * 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)); +} + +/* + * 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)); +} + +/* + * 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); + } + } +} + +/* + * 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; + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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); +} + +/* + * 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, ' '); + } + } +} + +/* + * 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); + } + } + } +} + +/* + * 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 */ +} + +/* + * 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)); +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } + } +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * 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 */ +} + +/* + * Name: fixspace() + * + * Abstract: Reset width, if need be, for chords of all spaces. + * + * Returns: void + * + * Description: This function loops through chord lists, looking for each chord + * that is all spaces (as shown by the fact that its width is 0). + * If any voice has a nonspace during the time value of this + * chord, we reset its width to a very small positive number, to + * prevent abshorz from treating it like it "deserves" no width + * (rather than what its duration would imply). + */ + +static void +fixspace() + +{ + struct CHORD *ch_p; /* point at a chord */ + struct MAINLL *mainll_p; /* point at items in main linked list*/ + struct MAINLL *m2_p; /* another pointer down the MLL */ + int crunch; /* should chord be crunched to 0 width*/ + int v; /* voice number, 0 or 1 */ + + + debug(16, "fixspace"); + /* + * Loop down the main linked list looking for each chord list headcell. + */ + for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) { + + if (mainll_p->str != S_CHHEAD) + continue; /* skip everything but chord HC */ + + /* + * Loop through the chord list, looking for all-space chords. + * Skip the first one in the list; we always want that one to + * be crunched to zero width, since there's nothing earlier + * that could extend into it. + */ + for (ch_p = mainll_p->u.chhead_p->ch_p->ch_p; ch_p != 0; + ch_p = ch_p->ch_p) { + + if (ch_p->width != 0) + continue; /* skip nonspace chord */ + + crunch = YES; /* init to crunch */ + + /* loop through every staff and every voice in meas */ + for (m2_p = mainll_p->next; m2_p->str == S_STAFF; + m2_p = m2_p->next) { + + for (v = 0; v < MAXVOICES && m2_p->u.staff_p-> + groups_p[v] != 0; v++) { + + /* if voice has nonspace, don't crunch*/ + if ( ! hasspace(m2_p->u.staff_p-> + groups_p[v], ch_p->starttime, + radd(ch_p->starttime, ch_p->duration))){ + crunch = NO; + break; + } + } + + if (crunch == NO) + break; + } + + /* if should not crunch, set nonzero width to stop it */ + if (crunch == NO) + ch_p->width = 0.001; + + } /* for every chord in this measure */ + + } /* looping through MLL, dealing with chord headcells */ +} diff --git a/mup/mup/roll.c b/mup/mup/roll.c new file mode 100644 index 0000000..ad58d18 --- /dev/null +++ b/mup/mup/roll.c @@ -0,0 +1,661 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2002, 2004 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions to deal with rolls. This includes both parse phase and print + * phase code for rolls. */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + + +/* each "roll" input statement can have multiple beat offsets to specify + * more than one roll. This is a linked list struct to hold these offsets */ +struct ROLLOFFSET { + float offset; /* beat offset where roll is */ + struct ROLLOFFSET *next; /* linked list */ +}; + + +/* struct to hold all needed info about a roll input statement */ +struct ROLLINFO { + short topstaff; /* roll goes from here */ + short topvoice; + short botstaff; /* roll ends here */ + short botvoice; + short rolldir; /* UP, DOWN, or UNKNOWN. UNKNOWN really means + * UP but with no arrow drawn (the default) */ + short error; /* YES if got bad value for some parameter */ + int lineno; /* input line number where defined */ + char *inputfile; /* input file where defined */ + struct ROLLOFFSET *offsets_p; /* list of beat offsets */ + struct ROLLINFO *next; /* linked list */ +}; + +static struct ROLLINFO *Roll_list_p; /* rolls defined in current measure */ + /* rolls are linked to the head of this list, so this pointer + * will point to the roll currently being defined */ + + +/* static functions declarations */ +static void do_a_roll P((struct ROLLINFO *roll_p, struct MAINLL *mll_p)); +static void roll P((struct MAINLL * mll_p, struct ROLLINFO *roll_p, + struct ROLLOFFSET * offset_p)); +static void set_roll P((struct GRPSYL *gs_p, int item, + struct ROLLINFO *roll_p)); +static void draw_roll P((double x, double y1, double y2, int rolldir)); + + + +/* 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; +} + + +/* alter the roll direction (default is UNKNOWN) */ + +void +setrolldir(int dir) + +{ + Roll_list_p->rolldir = dir; +} + + +/* 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; + } +} + + +/* 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; +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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; + } +} + + +/* 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); + } + } +} + + +/* return YES if given group is the top group that gets a roll drawn by it, + * NO if not. This is called from the print phase */ + +int +gets_roll(gs_p, staff_p, v) + +struct GRPSYL *gs_p; /* check if this group gets a roll */ +struct STAFF *staff_p; /* it's connected to this staff */ +int v; /* and is in this voice */ + +{ + float width1, width2; /* widest note heads in each group */ + float maxwide; /* widest notehead */ + struct GRPSYL *othergs_p; /* group in other voice */ + + + if (gs_p->roll != STARTITEM && gs_p->roll != LONEITEM) { + return(NO); + } + + /* check for strange case where we don't print a roll because groups + * are incompatible (had to be moved horizontally because they + * overlapped), and both have rolls. If the group's RX is greater + * than (maxwide - W_NORMAL * POINT) / 2 where + * maxwide is the maximum of width of the note head characters + * the two groups, then don't print the roll. */ + if (svpath(staff_p->staffno, VSCHEME)->vscheme == V_1) { + /* strange case only happens with 2 voices */ + return(YES); + } + else { + /* find width of widest note of this group */ + width1 = widest_head(gs_p) * Staffscale; + + /* find other group. If this is first voice, + * just look down the chord link */ + if (v == 0) { + othergs_p = gs_p->gs_p; + } + else { + /* follow groups until we find the one linked to this + * one */ + for (othergs_p = staff_p->groups_p[0]; + othergs_p != (struct GRPSYL *) 0; + othergs_p = othergs_p->next) { + if (othergs_p->gs_p == gs_p) { + break; + } + } + } + + if (othergs_p != (struct GRPSYL *) 0 && + othergs_p->grpcont == GC_NOTES) { + + /* find width of widest note of the other group */ + width2 = widest_head(othergs_p) * Staffscale; + + maxwide = MAX(width1, width2); + + if (gs_p->c[RX] > ((maxwide - W_NORMAL * POINT) / 2.0)){ + /* we hit the strange case */ + return(NO); + } + } + } + return(YES); +} diff --git a/mup/mup/setgrps.c b/mup/mup/setgrps.c new file mode 100644 index 0000000..3f520bf --- /dev/null +++ b/mup/mup/setgrps.c @@ -0,0 +1,2920 @@ +/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2004, 2005, 2006 + * by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: setgrps.c + * + * Description: This file contains functions for setting the relative + * horizontal coordinates of all groups that contain notes + * (grpcont == GC_NOTES) and of all objects in these groups. + * It also sets relative vertical coordinates for the dots + * after notes. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +struct NOTEPTRS { + struct NOTE *top_p; /* point at a note in top group */ + struct NOTE *bot_p; /* point at same note in bottom group*/ + float wid; /* width of the note head */ +}; + +static struct GRPSYL *procallvoices P((struct MAINLL *mll_p, + struct GRPSYL *gs_p)); +static void proc1or2voices P((struct MAINLL *mll_p, struct STAFF *staff_p, + struct GRPSYL *gs1_p, struct GRPSYL *gs2_p)); +static int compat P((struct NOTEPTRS noteptrs[], struct GRPSYL *gs1_p, + struct GRPSYL *gs2_p)); +static int can_overlap P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p)); +static void procsome P((struct NOTEPTRS noteptrs[], struct MAINLL *mll_p, + struct STAFF *staff_p, struct GRPSYL *gs1_p, + struct GRPSYL *gs2_p)); +static void procgrace P((struct NOTEPTRS noteptrs[], struct MAINLL *mll_p, + struct STAFF *staff_p, struct GRPSYL *gsnorm_p)); +static void procbunch P((struct NOTEPTRS noteptrs[], struct MAINLL *mll_p, + struct STAFF *staff_p, struct GRPSYL *gs1_p, + struct GRPSYL *gs2_p)); +static void doacc P((struct NOTEPTRS noteptrs[], double halfwide, + double halfhigh, int collinear)); +static int nextacc P((struct NOTEPTRS noteptrs[], int found)); +static void dodot P((struct STAFF *staff_p, struct GRPSYL *gs1_p, + struct GRPSYL *gs2_p, double halfwide, int collinear)); +static void dogrpdot P((struct STAFF *staff_p, struct GRPSYL *gs_p, + struct GRPSYL *ogs_p, double halfwide, int uppermost, + int lowermost, int push)); +static void westwith P((struct GRPSYL *gs_p)); +static void eastwith P((struct GRPSYL *gs_p)); +static void csbstempad P((struct MAINLL *mll_p, struct GRPSYL *gs_p)); +static void proctab P((struct MAINLL *mll_p, struct STAFF *staff_p, + struct GRPSYL *gs1_p)); +static void noterparen P((struct NOTEPTRS noteptrs[], struct GRPSYL *gs1_p, + struct GRPSYL *gs2_p, double halfwide, double halfhigh, + int collinear)); + +/* + * 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); + } + } + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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]; + } +} + +/* + * 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; + } + } +} + +/* + * 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 */ +} + +/* + * 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); + } +} + +/* + * 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; + } + } + } +} + +/* + * 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; + } +} + +/* + * 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; + } +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * Name: noterparen() + * + * Abstract: Finds horizontal position notes' right parentheses. + * + * Returns: void + * + * Description: If any of the notes in the given group(s) are to have + * parentheses around them, this function finds the horizontal + * positions of the right parentheses. The left ones were done + * in doacc() along with accidentals. For each group, it uses + * the appropriate size of parentheses (based on normal versus + * cue/grace), and places them appropriately, considering also + * the size of the notes. However, if there are two groups, + * the note head sizes could be different. The halfwide and + * halfhigh passed in are supposed to be the right size for the + * bigger of the two sizes, and accidentals will not be packed + * as tightly against the other notes. This doesn't hurt, and + * isn't worth the trouble to do it "right". + */ + +static void +noterparen(noteptrs, gs1_p, gs2_p, halfwide, halfhigh, collinear) + +struct NOTEPTRS noteptrs[]; /* array of ptrs to notes to process */ +struct GRPSYL *gs1_p, *gs2_p; /* point at group(s) in this hand */ +double halfwide; /* half of max of width & height of (notes */ +double halfhigh; /* in group 1, notes in group 2) */ +int collinear; /* are stems collinear? */ + +{ + /* + * Each structure in this table represents either a note head that is + * farther right than normal, note dot(s), or right paren. A note head + * could be too far right for one of two reasons: either it was + * forced to be on the right ("wrong") side of a stem that points + * up, or it is a normal note in the bottom group when the stems are + * collinear. In the collinear case, to make this function easier, + * we start out regarding the top group as being normal, and + * the bottom group as being shifted right one note head, and we figure + * everything relative to the top group. But at the end we adjust + * so that every parenthesis is relative to its own group, like + * it's supposed to be. + * + * The coordinates define the rectangle that surrounds the note, dot(s), + * or paren, including standard padding, even on note heads, which don't + * normally have padding. First the notes and dots are put into this + * table, just one rectangle for a sequence of dots; then the right + * parens one at a time, making sure they don't overlap things already + * in the table. + * + * To see if the parenthesis being added overlaps, first its north + * and south are tested. All previous rectangles that are "out of + * its way" vertically are marked not "relevant"; the others are + * marked "relevant". As positions are tried, left to right, positions + * that fail to avoid overlap are marked "tried". + */ + struct { + float n, s, e, w; /* boundaries of a rectangle */ + short relevant; /* is rectangle relevant? */ + short tried; /* have we tried this one yet? */ + } rectab[2 * MAXHAND + 1]; /* enough for all notes & accidentals*/ + + struct NOTE *note_p; /* point at a note */ + int reclim; /* index after last rectangle in tab */ + int parensexist; /* does any note have parens? */ + float north, south, east, west; /* relative coords of new accidental */ + float parenwidth; /* width of note's left parenthesis */ + float parenv; /* half the vertical size of paren */ + float dotoff; /* additional offset caused by dots */ + float dotoff1, dotoff2; /* same, for groups 1 and 2 */ + int overlap; /* does our acc overlap existing ones*/ + int try; /* which element of rectab to try */ + int k, j; /* loop variables */ + int size; + + + /* + * If no notes have parentheses, we can get out because there is + * nothing to do. + */ + parensexist = NO; /* init to no parens */ + for (k = 0; (note_p = GETPTR(k)) != 0; k++) { + if (note_p->note_has_paren == YES) + parensexist = YES; + } + if (parensexist == NO) + return; + + reclim = 0; /* table initially empty */ + + /* set up dot offsets for both groups, zero if no dots */ + dotoff1 = gs1_p->dots * (width(FONT_MUSIC,DFLT_SIZE,C_DOT) + 2*STDPAD); + dotoff2 = 0.0; /* prevent useless 'used before set' warning */ + if (gs2_p != 0) { + dotoff2 = gs2_p->dots * (width(FONT_MUSIC, DFLT_SIZE, C_DOT) + + 2 * STDPAD); + } + + /* + * Loop through noteptrs, loading rectab with all the things that are + * already present that are to the right of the baseline. + */ + for (k = 0; (note_p = GETPTR(k)) != 0; k++) { + /* + * If note exists in top group, use its dot offset, else use + * bottom's. If it's in both, the results would be the same. + */ + if (noteptrs[k].top_p != 0) + dotoff = dotoff1; + else + dotoff = dotoff2; + + /* if note is right of normal position, put it in the table */ + if (note_p->c[RX] > 0) { + rectab[reclim].n = note_p->c[RY] + halfhigh + STDPAD; + rectab[reclim].s = note_p->c[RY] - halfhigh - STDPAD; + rectab[reclim].e = note_p->c[RE] + STDPAD; + rectab[reclim].w = note_p->c[RW] - STDPAD; + reclim++; + } + + /* if collinear, bottom group's notes go into table if normal */ + if (collinear && noteptrs[k].bot_p != 0) { + if (note_p->c[RX] == 0) { + rectab[reclim].n = note_p->c[RY] + halfhigh + + STDPAD; + rectab[reclim].s = note_p->c[RY] - halfhigh + - STDPAD; + rectab[reclim].e = W_NORMAL * POINT + + 3 * halfwide + STDPAD; + rectab[reclim].w = W_NORMAL * POINT + + halfwide - STDPAD; + reclim++; + } + } + + /* if this group has dots, do rectangle for dots */ + if (dotoff > 0) { + rectab[reclim].n = note_p->ydotr + STDPAD; + rectab[reclim].s = note_p->ydotr - STDPAD; + if (noteptrs[k].top_p != 0) + rectab[reclim].e = gs1_p->xdotr + dotoff; + else + rectab[reclim].e = gs2_p->xdotr + dotoff; + rectab[reclim].w = 0; + reclim++; + } + } + + /* + * Loop through all parentheses, finding where they will fit, storing + * that info in erparen, and adding them to rectab. + */ + for (k = 0; (note_p = GETPTR(k)) != 0; k++) { + + /* if no parens around the note, skip the note */ + if (note_p->note_has_paren == NO) + continue; + + /* get dimensions of note's right paren */ + size = (note_p->notesize == GS_NORMAL ? DFLT_SIZE : SMALLSIZE); + parenwidth = width(FONT_TR, size, ')'); + parenv = height(FONT_TR, size, ')') / 2.0; + + /* set the north and south of the paren */ + north = note_p->c[RY] + parenv; + south = note_p->c[RY] - parenv; + + /* + * For each rectangle in rectab, decide whether (based on + * its vertical coords) it could possibly overlap with our + * new paren. If it's totally above or below ours, it + * can't. We allow a slight overlap (FUDGE) so that round + * off errors don't stop us from packing things as tightly + * as possible. + */ + for (j = 0; j < reclim; j++) { + if (rectab[j].s + FUDGE > north || + rectab[j].n < south + FUDGE) + rectab[j].relevant = NO; + else + rectab[j].relevant = YES; + } + + /* + * Mark that none of the relevant rectangles' boundaries have + * been tried yet for positioning our paren. + */ + for (j = 0; j < reclim; j++) { + if (rectab[j].relevant == YES) + rectab[j].tried = NO; + } + + /* + * Set up first trial position for this paren, just to the + * right of normal notes, allowing padding. + */ + west = halfwide + STDPAD; + east = west + parenwidth; + + /* + * Keep trying positions for this paren, working left to + * right. When we find one that doesn't overlap an existing + * rectangle, break. This has to succeed at some point, + * at the rightmost rectangle position if not earlier. + */ + for (;;) { + overlap = NO; + for (j = 0; j < reclim; j++) { + /* ignore ones too far north or south */ + if (rectab[j].relevant == NO) + continue; + + /* if all west or east, okay; else overlap */ + if (rectab[j].w + FUDGE <= east && + rectab[j].e >= west + FUDGE) { + overlap = YES; + break; + } + } + + /* if no rectangle overlapped, we found a valid place*/ + if (overlap == NO) + break; + + /* + * Something overlapped, so we have to try again. + * Find the westermost relevant east rectangle boundary + * that hasn't been tried already, to use as the next + * trial position for our paren's west. + */ + try = -1; + for (j = 0; j < reclim; j++) { + /* ignore ones too far north or south */ + if (rectab[j].relevant == NO || + rectab[j].tried == YES) + continue; + + /* + * If this is the first relevant one we haven't + * tried, or if this is farther west than the + * westernmost so far, save it as being the + * new westernmost so far. + */ + if (try == -1 || rectab[j].e < rectab[try].e) + try = j; + } + + if (try == -1) + pfatal("bug in noterparen()"); + + /* + * Mark this one as having been tried (for next time + * around, if necessary). Set new trial values for + * east and west of our paren. + */ + rectab[try].tried = YES; + west = rectab[try].e; + east = west + parenwidth; + + } /* end of while loop trying positions for this acc */ + + /* + * We have the final position for the new paren. Enter it into + * rectab. Store its east in erparen in the NOTE structure for + * whichever groups have this note. + */ + rectab[reclim].n = north; + rectab[reclim].s = south; + rectab[reclim].e = east; + rectab[reclim].w = west; + reclim++; + if (noteptrs[k].top_p != 0) { + noteptrs[k].top_p->erparen = east; + } + if (noteptrs[k].bot_p != 0) { + noteptrs[k].bot_p->erparen = east; + } + + } /* end of loop for each accidental */ + + /* + * Finally, if the stems were collinear, we have to adjust erparen for + * all the notes of the bottom group, so that it's relative to the + * bottom group instead of the top group. + */ + if (collinear) { + for (k = 0; (note_p = GETPTR(k)) != 0; k++) { + if (noteptrs[k].bot_p != 0) { + noteptrs[k].bot_p->erparen -= 2 * halfwide + - W_NORMAL * POINT; + } + } + } +} diff --git a/mup/mup/setnotes.c b/mup/mup/setnotes.c new file mode 100644 index 0000000..47155b1 --- /dev/null +++ b/mup/mup/setnotes.c @@ -0,0 +1,1783 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2003, 2004, 2005, 2006 + * by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: setnotes.c + * + * Description: This file contains functions for setting relative vertical + * locations of notes. It also sets relative vertical locations + * of the groups that contain notes, considering only the notes. + * It also sets the directions of stems. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +static void locnotes P((void)); +static void locllnotes P((struct MAINLL *mll_p, int v, + struct MAINLL *nextbar_p)); +static void chktabcollision P((struct GRPSYL *start_p)); +static void intertab P((struct GRPSYL *gs_p, struct MAINLL *mll_p)); +static void setstems P((void)); +static void setonestem P((struct GRPSYL *gs_p)); +static void setopstem P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p)); +static void setfreestem P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p)); +static void set1freestem P((struct GRPSYL *this_p, struct GRPSYL *other_p, + int stemdir)); +static void setbeamedstem P((struct GRPSYL *start_p, int stemdir)); +static void dobunch P((struct GRPSYL *start_p, struct GRPSYL *end_p)); +static void dograce P((struct GRPSYL *gs1_p, struct GRPSYL *gs2_p)); +static int setv3stem P((struct GRPSYL *gs_p, int stemdir)); +static int dov3bunch P((struct GRPSYL *start_p, struct GRPSYL *end_p, + int stemdir)); +static void setheads P((void)); +static void setvoiceheads P((struct MAINLL *mll_p, struct GRPSYL *gs_p, + int stafflines, short *shapes, int is_tab, int allx_hsi, + int sharps, int keylet)); +static void fixoneline P((void)); + +/* + * 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(); +} + +/* + * 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; + } + } +} + +/* + * 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; + } +} + +/* + * 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; + } + } +} + +/* + * 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); + } +} + +/* + * 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; + } + } + } +} + +/* + * 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; + } +} + +/* + * 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; + } +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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; + } +} + +/* + * 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; + } + } + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); + } + } +} + +/* + * 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; + } + } + } +} + +/* + * Name: fixoneline() + * + * Abstract: Fix stemsup and vertical coord for notes on one-line staffs. + * + * Returns: void + * + * Description: stepsup and notes' vertical coords are set in locllnotes(). + * For one-line staffs, it assumes the notes are on the line. + * But if the notes are not to be on the line, that isn't right. + * It depends on which voice this is. Now that we have set the + * stem direction, we need to correct this info. + */ + +static void +fixoneline() + +{ + struct MAINLL *mainll_p; /* point at main linked list item */ + struct STAFF *staff_p; /* point at a STAFF */ + struct GRPSYL *gs_p; /* point along a GRPSYL list */ + int v; /* voice number, 0 or 1 */ + + + debug(16, "fixoneline"); + initstructs(); /* clean out old SSV info */ + + /* + * Loop once for each item in the main linked list. Apply any SSVs + * that are found. Move notes that are not to be on the line. + */ + for (mainll_p = Mainllhc_p; mainll_p != 0; mainll_p = mainll_p->next) { + + if (mainll_p->str == S_SSV) { + /* apply the SSV and go to the next item */ + asgnssv(mainll_p->u.ssv_p); + continue; + } + + /* deal only with visible staffs that aren't measure rpts */ + if (mainll_p->str != S_STAFF || + mainll_p->u.staff_p->visible == NO || + is_mrpt(mainll_p->u.staff_p->groups_p[0])) { + continue; + } + + staff_p = mainll_p->u.staff_p; + + /* deal only with non-tab one-line staffs */ + if (svpath(staff_p->staffno, STAFFLINES)->stafflines != 1 || + svpath(staff_p->staffno, CLEF)->clef + == TABCLEF) { + continue; + } + + /* + * Loop through voices 1 and 2, and process each list. Note + * that voice 3 is always on the line, so we don't need to do + * anything to it. + */ + for (v = 0; v < NORMVOICES && staff_p->groups_p[v] != 0; v++) { + + /* change stepsup from 0 only if notes not on the line*/ + if (vvpath(staff_p->staffno, v + 1, ONTHELINE)-> + ontheline == YES) { + continue; + } + + for (gs_p = staff_p->groups_p[v]; gs_p != 0; + gs_p = gs_p->next) { + + /* only notes are to be changed */ + if (gs_p->grpcont != GC_NOTES) { + continue; + } + + /* move up or down a step based on voice */ + if (gs_p->vno == 1) { + gs_p->notelist[0].stepsup = 1; + gs_p->notelist[0].c[RY] = STEPSIZE; + gs_p->notelist[0].c[RN] += STEPSIZE; + gs_p->notelist[0].c[RS] += STEPSIZE; + } else { + gs_p->notelist[0].stepsup = -1; + gs_p->notelist[0].c[RY] = -STEPSIZE; + gs_p->notelist[0].c[RN] -= STEPSIZE; + gs_p->notelist[0].c[RS] -= STEPSIZE; + } + } + } + } +} diff --git a/mup/mup/ssv.c b/mup/mup/ssv.c new file mode 100644 index 0000000..4ec37b2 --- /dev/null +++ b/mup/mup/ssv.c @@ -0,0 +1,1420 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2006 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: ssv.c + * + * Description: This file defines the instances of score, staff, and voice + * structures that are used for viewpathing. It also contains + * functions for accessing them. + */ + +#include +#include + +#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)); + +/* + * 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 */ + } +} + +/* + * 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; + } +} + +/* + * 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 */ +} + +/* + * 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; + } + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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; + } + } +} + +/* + * Name: setorder() + * + * Abstract: Assign an "order" field from an input SSV to a fixed one. + * + * Returns: void + * + * Description: This function is called by asgnssv() to assign to the + * appropriate part of the markorder array, based on above, below, + * or between. + */ + +static void +setorder(place, i_p, f_p) + +int place; /* PL_* */ +struct SSV *i_p; /* input SSV structure to be copied from */ +struct SSV *f_p; /* ptr to fixed SSV structure to copy into */ + +{ + int m; /* mark (MK_*) */ + int stk; /* stacking order */ + + + /* + * First assign all the marks' stacking orders as given. Keep track of + * the highest stacking order number found. + */ + stk = 0; + for (m = 0; m < NUM_MARK; m++) { + f_p->markorder[place][m] = i_p->markorder[place][m]; + + if (f_p->markorder[place][m] > stk) + stk = f_p->markorder[place][m]; + } + + /* + * For every mark type that the user didn't list, the stacking order is + * now 0. Set all these to default settings, higher than all the ones + * the user listed, but in the same order as Defmarkorder. They will + * all be separate numbers, none set equal, unlike Defmarkorder, where + * some are equal. + */ + for (m = 0; m < NUM_MARK; m++) { + if (f_p->markorder[place][m] == 0) { + f_p->markorder[place][m] = ++stk; + } + } +} diff --git a/mup/mup/ssvused.h b/mup/mup/ssvused.h new file mode 100644 index 0000000..24141f0 --- /dev/null +++ b/mup/mup/ssvused.h @@ -0,0 +1,104 @@ +/* Copyright (c) 2001, 2003, 2004, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _SSVUSED_H +#define _SSVUSED_H + +/* + * This file contains the array subscript definitions for the used[] array + * of an SSV struct. An SSV contains parameters associated with a + * Score, Staff, or Voice. The used[] array is a set of flags which say + * whether a given parameter is actually populated in the SSV instance. + * In the "score" SSV, all used flags are always set true. In SSVs for + * a staff or voice, a "used" flag is only set to true if the user + * specified a value for the parameter in that staff or voice context. + * + * The actual values are machine-generated so they get automatically + * renumbered if parameters are added or deleted or rearranged. + * + * We try to put things that are logically similar close together in + * this list, but they could be in any order, other than that NUMFLDS + * _must_ be last. + */ + +#define SCALE_FACTOR (0) +#define UNITS (1) +#define PAGEHEIGHT (2) +#define PAGEWIDTH (3) +#define PANELSPERPAGE (4) +#define TOPMARGIN (5) +#define BOTMARGIN (6) +#define LEFTMARGIN (7) +#define RIGHTMARGIN (8) +#define RESTCOMBINE (9) +#define FIRSTPAGE (10) +#define NUMSTAFF (11) +#define MINSCSEP (12) +#define MAXSCSEP (13) +#define MINSCPAD (14) +#define MAXSCPAD (15) +#define BRACELIST (16) +#define BRACKLIST (17) +#define BARSTLIST (18) +#define TIME (19) +#define DIVISION (20) +#define ENDINGSTYLE (21) +#define GRIDSATEND (22) +#define MEASNUM (23) +#define MEASNUMFAMILY (24) +#define MEASNUMFONT (25) +#define MEASNUMSIZE (26) +#define PACKFACT (27) +#define PACKEXP (28) +#define WARN (29) +#define STAFFSCALE (30) +#define VISIBLE (31) +#define STAFFLINES (32) +#define GRIDSWHEREUSED (33) +#define GRIDSCALE (34) +#define GRIDFRET (35) +#define NUMBERMRPT (36) +#define PRINTMULTNUM (37) +#define RESTSYMMULT (38) +#define VSCHEME (39) +#define VCOMBINE (40) +#define SHARPS (41) +#define CANCELKEY (42) +#define TRANSPOSITION (43) +#define ADDTRANSPOSITION (44) +#define CLEF (45) +#define REHSTYLE (46) +#define FONTFAMILY (47) +#define FONT (48) +#define SIZE (49) +#define LYRICSFAMILY (50) +#define LYRICSFONT (51) +#define LYRICSSIZE (52) +#define LYRICSALIGN (53) +#define SYLPOSITION (54) +#define MINSTSEP (55) +#define STAFFPAD (56) +#define ABOVEORDER (57) +#define BELOWORDER (58) +#define BETWEENORDER (59) +#define PEDSTYLE (60) +#define CHORDDIST (61) +#define DIST (62) +#define DYNDIST (63) +#define LABEL (64) +#define LABEL2 (65) +#define BEAMSTLIST (66) +#define BEAMSLOPE (67) +#define PAD (68) +#define STEMLEN (69) +#define STEMSHORTEN (70) +#define DEFOCT (71) +#define TIMEUNIT (72) +#define SWINGUNIT (73) +#define RELEASE (74) +#define ONTHELINE (75) +#define TABWHITEBOX (76) +#define NOTEHEADS (77) +#define NUMFLDS (78) + +#endif diff --git a/mup/mup/structs.h b/mup/mup/structs.h new file mode 100644 index 0000000..3c2c197 --- /dev/null +++ b/mup/mup/structs.h @@ -0,0 +1,1423 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * structs.h + * + * This file defines the structures needed for the Mup program. + */ + +#ifndef _STRUCTS +#define _STRUCTS + +#include +#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 + * that precede or follow the real syllable. + * + * WARNING: for groups, during the time when positions of phrase + * marks are being figured out, AN and AS are used in a strange way, + * denoting the offset from RN or RS where the phrase is. But later + * they get set to their normal values. + */ + float c[NUMCTYPE]; /* coordinates */ + + /* + * The basic time value is one of the following: -1, 0, power of 2 from + * 1 to 256, or less than -1. For normal (is_meas==NO) groups, -1 + * means quadruple whole, 0 means double whole, 1 is whole, 2 is half, + * etc. Less than -1 means a multirest of (-basictime) measures. For + * is_meas==YES groups, basictime is the same as the preceding for + * measure rests, where it just tells which rest to draw, but for ms + * and mrpt it is arbitrarily set to -1. + */ + short basictime; + + /* + * is_meas tells whether an "m" was used with the time in the input. + * This is used for "measure" rests, spaces, or repeats (mr, ms, mrpt). + * (Only mr can have a normal time value in addition to the "m"; it is + * stored as the basictime (defaults to 1) and tells which rest to + * draw.) Their fulltime is the time signature. mr and mrpt are + * centered in the measure. + */ + short is_meas; + + short dots; /* number of dots applied to time value */ + + short tuploc; /* none, start, inner, end, lone (for tuplet) */ + short tupcont; /* number to print for the tuplet */ + + /* + * Full time is basic time modified by dots, tuplets, etc. It's the + * actual time duration, and thus for grace it's always 0. + */ + RATIONAL fulltime; + + float padding; /* extra space to allow */ + + /* ======== ITEMS FOR GROUPS ONLY ======== */ + short pvno; /* pseudo voice number: normally equals vno, + * but when voice 3 is treated like voice 1 or + * or 2, that number is stored here */ + /* also used as scratch area in mkchords.c */ + short grpcont; /* note(s), rest, or space; although normally + * meaningful only for groups, gram.y uses it + * as scratch while processing syllables */ + short grpvalue; /* normal time value; or zero for grace group + * or for all-space chords in MIDI */ + short grpsize; /* size of items in group */ + short headshape; /* default shape of noteheads in group */ + short uncompressible; /* is this space a "us" (used for space only)*/ + + short beamloc; /* none, start, inner, end (only note groups)*/ + float beamslope; /* user specified angle of beam in degrees */ + + /* + * Stem length applies to groups shorter than a whole note and groups + * joined by "alternation" beams. It starts out based only on + * basictime and grpsize, but due to a beam or override, it could be + * changed. Direction is up or down, and applies to all groups, even + * whole note groups (useful for figuring ties). stemx is the + * horizontal position of the stem, relative to the X of the GRPSYL. + * These fields are valid only for note groups. + */ + float stemlen; + short stemdir; /* up or down */ + float stemx; + + /* + * beamto is always CS_SAME, except when this group is a notes or + * space group and is involved in cross staff beaming. It then tells + * whether we are beamed with the staff above us or below us. It is + * set for all the note and space groups on both staffs in the set. + * So on the top staff it's set to CS_BELOW, and on the bottom staff + * it's set to CS_ABOVE. + */ + short beamto; + + /* + * stemto is always CS_SAME, except when this group is a notes group + * and is involved in cross staff steming. It then tells whether we + * are stemmed with the staff above us or below us. When stemto is not + * CS_SAME, stemto_idx is an index into notelist[]. For CS_ABOVE, + * it indexes to the last note that is on the above staff. For + * CS_BELOW, it indexes to the first note that is on the below staff. + */ + short stemto; + short stemto_idx; + + /* YES if the last group in a subbeam */ + short breakbeam; + + /* + * printtup tells whether the user wants a tuplet number and bracket to + * be printed next to a note group. If PT_NEITHER, neither will be. + * If PT_BOTH, both will be. If PF_DEFAULT, at least the number will + * be. The bracket will be too, unless the tuplet contains only one + * group, or if all the groups' beamlocs are equal to their tuplocs + * (the groups are already beamed as a unit). If PT_NUMBER, the number + * (and only the number) will be printed. In any case, printtup + * is set for each group in the tuplet. + * + * tupextend is set only for the groups of a tuplet of notes that has + * printtup == Y. It is the vertical offset of where the tuplet + * bracket would be, from the AN or AS of the groups, as the case may + * be. If the bracket would be above the groups, it is positive and + * relative to AN; else it is negative and relative to AS. It is set + * even for the case where the bracket is not going to be printed, so + * that the tuplet number can still be placed as halfway between the + * invisible bracket's endpoints. + */ + short printtup; + float tupextend; + short tupside; /* should number & bracket be above or below?*/ + + short phraseside; /* relevant side(s) for phrase mark space */ + + /* + * nnotes says how many notes there are in the group. An array of + * that many note structures must be malloc'ed and notelist set to + * point at it. The notes are stored in order of descending pitch, + * regardless of the user's input ordering. These fields are valid + * only for note groups. + * But for measure repeats (mrpt), even though they are GC_NOTES, + * nnotes is 0 and notelist is a null pointer. + */ + short nnotes; /* no. of notes in group */ + struct NOTE *notelist; /* list of notes in group */ + + /* + * If tie is set to YES, all notes in the group are to be tied to + * corresponding notes in the following group. The "tie" flag will + * also be set on each individual note in its NOTE struct, but it + * turns out to be handy to have the whole group marked here too. + * This field is valid only for note groups. + */ + short tie; + + /* + * The slash_alt field is used for slashes on a group or between + * pairs of groups (for tremolo, or just dividing the time value of + * the group(s). 0 means normal group; >0 means draw that many + * slashes through the stem of this group (or, if basictime < 2, where + * the stem would have been); <0 means draw negative that many slashes + * between this and the next group. This field is valid only for note + * groups. + */ + short slash_alt; + + /* + * On a tablature staff, when an entire group is tied to the following + * group, the second group normally should not be printed. (Its + * corresponding tabnote group will be, though.) This flag says not to + * print this group. This is set by the parse phase when the preceding + * tab group is tied. It is cleared by the placement phase after + * scorefeeds. + */ + short inhibitprint; + + /* + * This is used for rests only. If not used, it is NORESTDIST. + * Otherwise, it is the vertical offset of the "center" of the rest + * (the part that normally is on the center line) from the center line. + * The rest is forced there. + */ + short restdist; + + /* + * These are for the user-specified horizontal offset of the group from + * the chord's X. The value is in stepsizes; negative to the left, and + * positive to the right. + */ + short ho_usage; /* HO_* */ + float ho_value; /* value to use when ho_usage is HO_VALUE */ + + + /* the X positions of dots are the same for every note in the group */ + float xdotr; /* relative coord of dots: x(dot)-x(group) */ + /* + * When symbols are to be drawn "with" a group, they are stored + * in the list below in order, starting from the group and moving + * outwards. When nwith is 0, there is no list. Otherwise, a + * list must be malloc'ed and the pointer must be set to point at + * it. Each item in the list is a pointer to a string, which must + * also be malloc'ed. Normally, the "with" items are on the note side + * of the group, but if there are two voices, they might need to be + * put on the stem side, so normwith says which side they go on. + * These fields are valid only for note groups. + */ + short nwith; /* no. of symbols with group */ + char **withlist; /* list of symbols with group */ + short normwith; /* does it go on the normal (note) end of grp?*/ + + short roll; /* where is this group in a roll, if at all? */ + short rolldir; /* is the roll's arrow UP, DOWN, or UNKNOWN? */ + /* (with UNKNOWN, roll is up, but no arrow) */ + + short clef; /* clef to be printed before this group */ + + /* ======== ITEMS FOR SYLLABLES ONLY ======== */ + char *syl; /* malloc a place for the syllable */ + short sylposition; /* points left of chord's X to start syl */ + + /* ======== LINKAGE ======== */ + struct GRPSYL *prev; /* point at previous group/syl in voice/verse*/ + struct GRPSYL *next; /* point at next group/syl in voice/verse */ + struct GRPSYL *gs_p; /* point at next group/syl in chord */ + +#else /* the same as above, optimized for space */ + + RATIONAL fulltime; + float c[NUMCTYPE]; + float padding; + float stemlen; + float stemx; + float tupextend; + float ho_value; + float xdotr; + float beamslope; + char *inputfile; + char **withlist; + char *syl; + struct GRPSYL *prev; + struct GRPSYL *next; + struct GRPSYL *gs_p; + struct NOTE *notelist; + short inputlineno; + short staffno; + short vno; + short basictime; + short dots; + short tupcont; + short pvno; + short nnotes; + short slash_alt; + short nwith; + short restdist; + short sylposition; + short clef; + short headshape; + short stemto_idx; + unsigned ho_usage : 2; + unsigned is_meas : 1; + unsigned grpsyl : 1; + unsigned tuploc : 3; + unsigned grpcont : 2; + unsigned grpvalue : 1; + unsigned grpsize : 1; + unsigned uncompressible : 1; + unsigned beamloc : 3; + unsigned stemdir : 2; + unsigned tupside : 2; + unsigned phraseside : 2; + unsigned printtup : 2; + unsigned tie : 1; + unsigned normwith : 1; + unsigned roll : 3; + unsigned rolldir : 2; + unsigned inhibitprint : 1; + unsigned beamto : 2; + unsigned stemto : 2; + unsigned breakbeam : 1; +#endif +}; + +/* + * Define the structure for a chord. + */ +struct CHORD { + /* + * Define the coords of a CHORD. For vertical, only the absolute ones + * are set. They are set the same as the FEED for this score, and they + * are used only for drawing bounding boxes with MUP_BB. As for + * horizontal, the relative coords are relative to the score's + * (x, y). Basically, west and east are set out just far enough to + * hold the biggest GRPSYL in the CHORD. However, for both groups and + * syllables there is special code that allows parts of them to stick + * out, when the overlap would be harmless even if the CHORDs end up + * being packed tightly together. + */ + float c[NUMCTYPE]; /* coordinates */ + float width; /* c[RE] - c[RW], which equals c[AE] - c[AW] */ + float fullwidth; /* dist from c[RX] of this chord to c[RX] of */ + /* next (or to bar line if last in measure) */ + + RATIONAL starttime; /* starting time of chord within its measure */ + RATIONAL duration; /* duration of the chord */ + float pseudodur; /* a function of duration; proportional to */ + /* width this chord will "deserve" */ + + struct CHORD *ch_p; /* point at next chord in list */ + struct GRPSYL *gs_p; /* point at first group or syllable in chord */ +}; + +/* + * Define the structure that contains info concerning chord grids that are + * going to be printed at the end of the song. Only one instance of this + * structure exists. + */ +struct ATEND_INFO { + /* number of different grids actually used in the song */ + int grids_used; + + /* + * Must grid dictionary be put on a separate page, following the last + * page of music (because it doesn't fit with the music)? YES or NO. + */ + int separate_page; + + /* + * This is a malloc'ed array of pointers to the grids to be printed. + * Placement sets it up and sorts it. + */ + struct GRID **grid_p; + + int grids_per_row; /* no. of grids to print per row */ + int rows_per_page; /* no. of rows of grids allowed on one page */ + float firstgrid_x; /* X coord of grids in the first column */ + float firstgrid_y; /* Y coord of grids in the first row */ + float horz_sep; /* dist between X of neighboring grids */ + float vert_sep; /* dist between Y of neighboring grids */ +}; + +/* + * Define a symbol for each structure type that can be inside a union, so + * that we can record which member of the union is being used. + */ +#define S_SSV (0) +#define S_FEED (1) +#define S_CLEFSIG (2) +#define S_PRHEAD (3) +#define S_CHHEAD (4) +#define S_STAFF (5) +#define S_LINE (6) +#define S_CURVE (7) +#define S_BAR (8) +#define S_BLOCKHEAD (9) + +/* + * The following contains a union of all the structures that can occur in the + * main linked list, set up by yyparse(). + */ +struct MAINLL { + short str; /* which structure in the union is now being used? */ + short inputlineno; /* which input line this structure came from */ + char *inputfile; /* which file this came from (malloc'ed) */ + union { /* malloc'ed structures to be pointed at */ + struct SSV *ssv_p; /* score/staff/voice context info */ + struct FEED *feed_p; /* score and/or page feed */ + struct CLEFSIG *clefsig_p; /* print clef and/or sigs? */ + struct PRHEAD *prhead_p;/* head of list to print things */ + struct CHHEAD *chhead_p;/* head of chord list for a measure */ + struct STAFF *staff_p; /* staff info from data context */ + struct LINE *line_p; /* line info */ + struct CURVE *curve_p; /* curve info */ + struct BAR *bar_p; /* bar line info from data context */ + struct BLOCKHEAD *blockhead_p; /* info for a "block" context */ + } u; + struct MAINLL *prev; /* previous structure in linked list */ + struct MAINLL *next; /* next structure in linked list */ +}; +/* + * The structures in the main linked list must occur in the order as shown + * below, by the end of the placement phase. There are optional initial SSVs, + * then two alternative sets of structures that repeat, then some optional + * final structures. The list shows [in brackets] which phase of Mup inserts + * the structure: parse or placement. (The third phase, print, doesn't insert + * any structures; nor does the midi phase, which can replace the print phase.) + * + * 0 or more SSVs [parse] + * LOOP 1 or more times: + * EITHER a measure: + * 0 or 1 FEED; 1 is required in 1st measure & after block[parse or place] + * 0 or 1 CLEFSIG (at start of a score); 1 iff a FEED precedes [place] + * 1 CHHEAD [place] + * 1 or more STAFFs. They are ordered by staff number. [parse] + * 0 or more LINEs and/or CURVEs and/or PRHEADs, any order[parse or place] + * 1 BAR [parse] + * 0 or more SSVs [parse or place] + * 0 or 1 CLEFSIG (after a bar line, not at start of a score) [place] + * OR a block: + * 1 FEED [parse] + * 1 BLOCKHEAD [parse] + * 0 or more SSVs [parse] + * END_EITHER + * END_LOOP + * 0 or more LINEs and/or CURVEs and/or PRHEADs and 1 optional FEED; the FEED + * is required if a block preceeds [parse] + */ +#endif diff --git a/mup/mup/stuff.c b/mup/mup/stuff.c new file mode 100644 index 0000000..08a2259 --- /dev/null +++ b/mup/mup/stuff.c @@ -0,0 +1,2255 @@ +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2005 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: stuff.c + * + * Description: This file contains functions for handling "stuff". + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* for STUFF, apply appropriate staffscale, based on "all" */ +#define STUFFSTEP(stuff_p) ((stuff_p)->all == YES ? \ + Score.staffscale * STEPSIZE : stepsize); + +static void normalizestuff P((void)); +static void movestuff P((struct STAFF *staff1_p, struct STAFF *staff2_p, + struct STUFF *stuff_p)); +static void setphrases P((void)); +static void phrasestuff P((struct MAINLL *msbeg_p, struct STUFF *stuff_p)); +static void set1phrase P((struct MAINLL *msbeg_p, struct STUFF *stuff_p, + int v)); +static void rmstuff P((struct STAFF *staff_p, struct STUFF *stuff_p)); +static void breakstuff P((void)); +static struct STUFF *prevstuff P((struct MAINLL *mainll_p, + struct STUFF *stuff_p)); +static void breakone P((struct MAINLL *m2_p, struct STUFF *stuff_p, + int timenum, char *origstr_p, int depth)); +static void contpedal P((void)); +static void setstuff P((void)); +static double count2coord P((double count, struct BAR *bar_p, + struct CHHEAD *chhead_p, int timeden)); +static int geteast P((struct STUFF *stuff_p, struct MAINLL *m2_p, + short *timeden2_p, struct CHHEAD **chhead2_p_p, + struct BAR **bar2_p_p)); +static int setmrferm P((struct STAFF *staff_p, struct STUFF *stuff_p)); +static int trygrid P((struct MAINLL *mainll_p, struct STUFF *stuff_p)); +static void tieslurstuff P((void)); +static void mktieslurstuff P((struct MAINLL *mllstaff_p, struct GRPSYL *gs_p, + int n, int s)); +static void mkextrastuff P((struct MAINLL *mll_p, struct STUFF *origstuff_p, + struct GRPSYL *gs_p, int n, int s, int stufftype)); + +/* + * 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(); +} + +/* + * 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--; + } + } + } + } +} + +/* + * 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; +} + +/* + * 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); + } +} + +/* + * 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; + } +} + +/* + * 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; + } +} + +/* + * 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); +} + +/* + * 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); + } + } + } +} + +/* + * 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); +} + +/* + * 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); + } +} + +/* + * 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; + } + } +} + +/* + * 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); + } + } + } +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * 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); +} + +/* + * 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 */ +} + +/* + * 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); + } + } + } + } + } +} + +/* + * 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); + } + } +} + +/* + * Name: mkextrastuff() + * + * Abstract: Create STUFF extra structure(s) for one tie/slur/bend. + * + * Returns: void + * + * Description: This function puts ST_TIESLUR, ST_TABSLUR, or ST_BEND STUFF + * structure(s) in the linked list for the ending piece of a tie, + * slur, or bend that is broken across a scorefeed or into a + * second or later ending. + */ + +static void +mkextrastuff(mll_p, origstuff_p, gs_p, n, s, stufftype) + +struct MAINLL *mll_p; /* starts before first staff in measure */ +struct STUFF *origstuff_p; /* original STUFF for this curve */ +struct GRPSYL *gs_p; /* GRPSYL where curve started */ +int n; /* index to note in notelist where it starts */ +int s; /* index into slurtolist, or -1 for tie */ +int stufftype; /* which of the stuff types is it? */ + +{ + struct STUFF *stuff_p; /* new stuff */ + struct GRPSYL *endgs_p; /* group where tie/slur/bend ends */ + int k; /* loop variable */ + + + /* find first staff */ + for ( ; mll_p != 0 && mll_p->str != S_STAFF; + mll_p = mll_p->next) + ; + + /* find matching staff */ + for ( ; mll_p != 0 && mll_p->str == S_STAFF && + mll_p->u.staff_p->staffno != + gs_p->staffno; mll_p = mll_p->next) + ; + if (mll_p == 0) + pfatal("last bar missing in main linked list [mkextrastuff]"); + if (mll_p->str != S_STAFF) /* number of staffs changed? */ + return; + + + /* allocate a STUFF structure second half of tie/slur/bend */ + stuff_p = newSTUFF((char *)0, 0, SD_NONE, (double)0, (double)0, 0, 0, + (double)0, stufftype, NO, PL_UNKNOWN, (char *)0, 0); + + stuff_p->carryin = YES; + stuff_p->costuff_p = origstuff_p; + + /* fill in additional items needed for tie/slur */ + stuff_p->vno = gs_p->vno; + endgs_p = mll_p->u.staff_p->groups_p[gs_p->vno - 1]; + stuff_p->beggrp_p = endgs_p; /* "beg" is really set to the end here*/ + + /* begnote_p must be pointed at the note where tie/slur ends; find it */ + for (k = 0; k < endgs_p->nnotes; k++) { + if (s == -1) { + /* tie; check for matching note */ + if (endgs_p->notelist[k].letter == + gs_p->notelist[n].letter + && endgs_p->notelist[k].octave == + gs_p->notelist[n].octave) + break; + } else { + /* slur/bend; check for note we're slurring/bending to*/ + if (endgs_p->notelist[k].letter == + gs_p->notelist[n].slurtolist[s].letter + && endgs_p->notelist[k].octave == + gs_p->notelist[n].slurtolist[s].octave) + break; + } + } + if (k == endgs_p->nnotes) { + l_warning(endgs_p->inputfile, endgs_p->inputlineno, + "can't find note being tied, slurred, or bent to"); + FREE(stuff_p); + return; + } + + stuff_p->begnote_p = &endgs_p->notelist[k]; /* end of tie/slur */ + stuff_p->curveno = (short)s; /* same as for the carryout stuff */ + + /* put the new STUFF into this staff's stuff list, at start of list */ + stuff_p->next = mll_p->u.staff_p->stuff_p; + mll_p->u.staff_p->stuff_p = stuff_p; +} diff --git a/mup/mup/symtbl.c b/mup/mup/symtbl.c new file mode 100644 index 0000000..ed03155 --- /dev/null +++ b/mup/mup/symtbl.c @@ -0,0 +1,1332 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* This file contains functions for dealing with symbol tables. + * There is a symbol table that maps the names of location variables + * to the addresses of their array of coordinate info, + * a symbol table to map headshape names to the list of shapes, + * a table to map time signatures to beamstyle and/or timeunit values, + * and a symbol table to map grid names to definitions of the grids. + * Symbol names are hashed for fast lookup. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + +/* shapes for quarter and shorter, half, whole, double whole */ +#define MAX_SHAPE_DURS (4) +/* UP and DOWN */ +#define MAX_STEM_DIRS (2) + +/* First index of headchar and headfont is based on stem direction; + * also index of ystem_off. */ +#define STEMINDEX(stemdir) ( (stemdir) == UP ? 0 : 1 ) +/* Second index of headchar and headfont is based on basictime */ +#define HCDUR(basictime) ( (basictime) > 2 ? 0 : 3 - (basictime) ) +/* First index of Nhead_map */ +#define FONTINDEX(font) (font - FONT_MUSIC) +/* Second index of Nhead_map */ +#define CHARINDEX(ch) (ch - FIRST_CHAR) + +struct HDSHAPEINFO { + /* We give each headshape instance a unique index number, + * as a compact way to refer to it. */ + short index; + + /* This says what notehead characters to use for this shape. + * The first dimension is for stem direction, the second for + * duration (quarter and shorter, half, whole, double whole). + */ + char headchar[MAX_STEM_DIRS][MAX_SHAPE_DURS]; + /* This array parallels the notehead array, saying which music + * font the character is in. */ + char headfont[MAX_STEM_DIRS][MAX_SHAPE_DURS]; +}; + +/* How many "headshape" entries we allow. This must be small enough to + * fit in the number of bits allowed for shape indexes in GRPSYL and NOTE. + * Entry 0 isn't used since we need an "unknown" value. + */ +#define MAX_SHAPE_ENTRIES (32) + +/* These are the predefined headshape entries. Users can define more. + * We define them here using the same syntax as user would, so we can + * use the same code to add to our internal table. */ +struct SHAPENAMES { + char *clan_name; /* name for the set of shapes */ + char *member_names; /* The names of the 4 shapes in the set */ +} Predef_shape_names[] = { + { "norm", "4n 2n 1n dblwhole" }, + { "x", "xnote diamond diamond dwhdiamond" }, + { "allx", "xnote xnote xnote xnote" }, + { "diam", "filldiamond diamond diamond dwhdiamond" }, + { "blank", "blankhead blankhead blankhead blankhead" }, + { "righttri", "u?fillrighttriangle u?righttriangle u?righttriangle u?dwhrighttriangle" }, + { "isostri", "fillisostriangle isostriangle isostriangle dwhisostriangle" }, + { "rect", "fillrectangle rectangle rectangle dwhrectangle" }, + { "pie", "fillpiewedge piewedge piewedge dwhpiewedge" }, + { "semicirc", "fillsemicircle semicircle semicircle dwhsemicircle" }, + { "allslash", "fillslashhead fillslashhead fillslashhead fillslashhead" }, + { "slash", "fillslashhead slashhead slashhead dwhslashhead" }, + { 0, 0 } +}; + +/* Information about characters that are allowed to be noteheads */ +struct HEADINFO { + char ch; /* code number 32-127 */ + char font; /* FONT_MUSIC* */ + float ystem_off[MAX_STEM_DIRS]; /* stepsizes from y to end stem */ +}; + +/* Predefined note head music characters and their attributes. */ +struct HEADDATA { + char *name; + struct HEADINFO info; +} Predef_headinfo[] = { + { "dblwhole", { C_DBLWHOLE, FONT_MUSIC, { 0.0, 0.0 } } }, + { "1n", { C_1N, FONT_MUSIC, { 0.0, 0.0 } } }, + { "2n", { C_2N, FONT_MUSIC, { 0.25, -0.25 } } }, + { "4n", { C_4N, FONT_MUSIC, { 0.25, -0.25 } } }, + { "xnote", { C_XNOTE, FONT_MUSIC, { 1.0, -1.0 } } }, + { "dwhdiamond", { C_DWHDIAMOND, FONT_MUSIC, { 0.0, 0.0 } } }, + { "diamond", { C_DIAMOND, FONT_MUSIC, { 0.0, 0.0 } } }, + { "filldiamond", { C_FILLDIAMOND, FONT_MUSIC, { 0.0, 0.0 } } }, + { "dwhrighttriangle", { C_DWHRIGHTTRIANGLE, FONT_MUSIC2, { 0.0, 0.0 } } }, + { "righttriangle", { C_RIGHTTRIANGLE, FONT_MUSIC2, { 0.0, 0.9 } } }, + { "fillrighttriangle",{ C_FILLRIGHTTRIANGLE, FONT_MUSIC2, { 0.0, 0.9 } } }, + { "udwhrighttriangle",{ C_UDWHRIGHTTRIANGLE, FONT_MUSIC2, { 0.0, 0.9 } } }, + { "urighttriangle", { C_URIGHTTRIANGLE, FONT_MUSIC2, { -0.9, 0.0 } } }, + { "ufillrighttriangle",{ C_UFILLRIGHTTRIANGLE,FONT_MUSIC2, { -0.9, 0.0 } } }, + { "dwhrectangle", { C_DWHRECTANGLE, FONT_MUSIC2, { -0.9, 0.0 } } }, + { "rectangle", { C_RECTANGLE, FONT_MUSIC2, { 0.0, 0.0 } } }, + { "fillrectangle", { C_FILLRECTANGLE, FONT_MUSIC2, { 0.0, 0.0 } } }, + { "dwhisostriangle", { C_DWHISOSTRIANGLE, FONT_MUSIC2, { -0.8, -0.8 } } }, + { "isostriangle", { C_ISOSTRIANGLE, FONT_MUSIC2, { -0.8, -0.8 } } }, + { "fillisostriangle", { C_FILLISOSTRIANGLE, FONT_MUSIC2, { -0.8, -0.8 } } }, + { "dwhpiewedge", { C_DWHPIEWEDGE, FONT_MUSIC2, { 0.1, 0.2 } } }, + { "piewedge", { C_PIEWEDGE, FONT_MUSIC2, { 0.1, 0.2 } } }, + { "fillpiewedge", { C_FILLPIEWEDGE, FONT_MUSIC2, { 0.1, 0.2 } } }, + { "dwhsemicircle", { C_DWHSEMICIRCLE, FONT_MUSIC2, { 0.8, 0.8 } } }, + { "semicircle", { C_SEMICIRCLE, FONT_MUSIC2, { 0.8, 0.8 } } }, + { "fillsemicircle", { C_FILLSEMICIRCLE, FONT_MUSIC2, { 0.8, 0.8 } } }, + { "blankhead", { C_BLANKHEAD, FONT_MUSIC2, { 0.0, 0.0 } } }, + { "slashhead", { C_SLASHHEAD, FONT_MUSIC2, { 1.8, -1.8 } } }, + { "fillslashhead", { C_FILLSLASHHEAD, FONT_MUSIC2, { 1.8, -1.8 } } }, + { "dwhslashhead", { C_DWHSLASHHEAD, FONT_MUSIC2, { 1.8, -1.8 } } }, + { 0, { 0, 0, { 0.0, 0.0 } } } +}; + +/* + * This struct provides a mapping from a time signature to all the + * beamstyle and timeunit values to be associated with that time signature. + * + * The [0][0] entry is used for the C_SCORE value. + * The entries [0][1] through [0][MAXVOICES+1] are unused. + * The [s][0] entries are used for C_STAFF values where 1 <= s <= MAXSTAFFS + * The [s][v] entries are used for C_VOICE values where 1 <= s <= MAXSTAFFS + * and 1 <= v <= MAXVOICES + * There will be one of these allocated for each time signature used in the + * input, if and only if the user also specified at least one beamstyle + * or timeunit while that time signature was in effect. + */ +struct SSVTABLES { + struct SSV *beamstyle_table[MAXSTAFFS+1][MAXVOICES+1]; + struct SSV *timeunit_table[MAXSTAFFS+1][MAXVOICES+1]; +}; + + +/* information about a symbol: its name and current value. + * This is used for location tags, chord grids, headshapes, and time signatures. + * Note that in the case of location tags, + * if the same name is used in a later measure, just the coordlist_p will + * change, and when the symbol table is queried for the value of a symbol, + * it will get the current value for that symbol */ +struct Sym { + char *symname; + union { + float *coordlist_p; /* when used for location tags, this is + * where its AX, RX, etc values are */ + struct GRID *grid_p; /* when used for grids */ + struct HDSHAPEINFO *shapeinfo_p;/* when used for headshapes */ + struct HEADINFO *noteinfo_p; /* when used for note head info */ + /* Info about beamstyles and/or timeunits associated with + * the time signature given by the symname. */ + struct SSVTABLES *ssvtables_p; + } val; + struct Sym *next; /* for collision chain off hash table */ +}; + +/* symbol hash table size-- if this changes, hash() has to change accordingly */ +#define SYMTBLSIZE (128) + +/* this is the symbol table for location tags */ +static struct Sym *Tag_table[SYMTBLSIZE]; + +/* this is the symbol table for guitar grids. It is malloc-ed at runtime + * only if needed */ +static struct Sym **Grid_table; + +/* This is the symbol table for headshapes */ +static struct Sym *Shape_table[SYMTBLSIZE]; + +/* This maps headshape indexes to the corresponding info. + * Element 0 is unused, since index 0 means "unknown" shape. + */ +static struct Sym *Shape_map[MAX_SHAPE_ENTRIES]; +/* How many Shape_map entries are actually used */ +static short Shape_entries = 0; + +/* This is the symbol table for noteheads, to get stem offsets */ +static struct Sym *Nhead_table[SYMTBLSIZE]; + +/* This maps notehead character codes to the stem offset info */ +static struct HEADINFO *Nhead_map[NUM_MFONTS][CHARS_IN_FONT]; + +/* This is used to remember what beamstyle and/or timeunit values were + * associated with time signatures. This is really only needed during parse, + * and then only if user specifies beamstyle or timeunit somewhere. + */ +static struct Sym *Time_map[SYMTBLSIZE]; + +/* Internal name for tag used to store the virtual _win coords for blocks */ +char Blockwin[] = "~blockwin"; +/* This points to where in the symbol table + * to save the pointer to the coord array for blocks. + * Having this pointer is a speed optimization, + * to save us from having to look it up every time. */ +float **Blockcoord_p_p; + + +/* static functions */ +static struct GRID *parse_grid P((char *griddef)); +static struct Sym *add2tbl P((char *symname, struct Sym **table)); +static struct Sym *findSym P((char *symname, struct Sym **table)); +static int hash P((char *string)); +static int coordhash P((float *key)); +static void rep_ref P((float **old_ref_p_p, float **new_ref_p_p)); +static void delete_coord P((float *coord_p)); +static int is_valid_notehead P((int ch, int font)); +static void add_head P((char *name, struct HEADINFO *info_p)); + + +/* size of Coordinfo hash table. Should be prime */ +#define COORDTBLSIZE (271) + +static struct COORD_INFO *Coord_table[COORDTBLSIZE]; + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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)); +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); + } +} + + +/* 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]); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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)]); +} + + +/* This should be called when an SSV has been collected by the user. + * If the user set beamstyle and/or timeunit in the SSV, + * create a mapping between the current time signature and that beamstyle + * and/or timeunit, so that if the user later sets the same time signature, + * they don't have to set the other things too. + * If they set time signature, see if we have a mapping + * for that time signature. If so, set the beamstyles and timeunits + * from that mapping. + */ + +void +remember_tsig_params(mll_p) + +struct MAINLL *mll_p; /* contains SSV */ + +{ + struct SSV *ssv_p; /* the SSV to process */ + char *timesig; /* current time signature representation */ + struct Sym *entry; /* entry in time sig info mapping table */ + + + if (mll_p->str != S_SSV) { + pfatal("remember_tsig_params got bad str value %d", mll_p->str); + } + ssv_p = mll_p->u.ssv_p; + + if (ssv_p->used[TIME] == NO && ssv_p->used[BEAMSTLIST] == NO && + ssv_p->used[TIMEUNIT] == NO) { + /* nothing of interest in this SSV */ + return; + } + + /* If user set time signature in this SSV, that's the time sig + * of interest, otherwise use the current time signature */ + timesig = (ssv_p->used[TIME] == YES ? ssv_p->timerep : Score.timerep); + if ((entry = findSym(timesig, Time_map)) == 0) { + entry = add2tbl(timesig, Time_map); + /* We'll only allocate the actual table if user gives a + * beamstyle or timeunit somewhere. If they never do, + * this will avoid wasting memory. + */ + entry->val.ssvtables_p = 0; + } + + /* If beamstyle or timeunit are set in this SSV, associate them + * with the current time signature. */ + if (ssv_p->used[BEAMSTLIST] == YES) { + if (entry->val.ssvtables_p == 0) { + CALLOC(SSVTABLES, entry->val.ssvtables_p, 1); + } + /* Note that when staffno and voiceno are zero, + * that's actually a score entry, and when voiceno is zero, + * but staffno is non-zero, that is actually a staff entry. */ + entry->val.ssvtables_p->beamstyle_table[ssv_p->staffno][ssv_p->voiceno] = ssv_p; + } + if (ssv_p->used[TIMEUNIT] == YES) { + if (entry->val.ssvtables_p == 0) { + CALLOC(SSVTABLES, entry->val.ssvtables_p, 1); + } + entry->val.ssvtables_p->timeunit_table[ssv_p->staffno][ssv_p->voiceno] = ssv_p; + } + + /* If time signature is set in this SSV, see if we have any + * beamstyles or timeunits associated with that time signature. + * If so, restore their values. */ + if (ssv_p->used[TIME] == YES && entry->val.ssvtables_p != 0) { + /* Make new SSVs and copy the relevant fields for any + * remembered beamstyles and/or timesunits associated + * with this time signature. */ + struct SSV *beamstyle_ssv_p; /* SSV having beamstyle info */ + struct SSV *timeunit_ssv_p; /* SSV having timeunit info */ + struct MAINLL *mll_ssv_p; /* new SSV to add to list */ + struct SSV *nssv_p; /* new SSV to add to list */ + int s; /* staff */ + int v; /* voice */ + + /* Check all SSV contexts. The [0][0] entry is for Scoreo * The rest of row [0] is unused. + * The [0] column is for staffs, for s > 0. + */ + for (s = 0; s <= MAXSTAFFS; s++) { + for (v = 0; v <= MAXVOICES; v++) { + + /* Check if we need to create an SSV for + * this staff/voice */ + beamstyle_ssv_p = entry->val.ssvtables_p->beamstyle_table[s][v]; + timeunit_ssv_p = entry->val.ssvtables_p->timeunit_table[s][v]; + if (beamstyle_ssv_p == 0 && + timeunit_ssv_p == 0) { + /* nothing to do for this one */ + continue; + } + + /* If both saved SSVs are either zero or + * the same SSV as where the time was just + * set, no need to make another SSV */ + if ( (beamstyle_ssv_p == 0 || + beamstyle_ssv_p == ssv_p) && + (timeunit_ssv_p == 0 || + timeunit_ssv_p == ssv_p) ) { + continue; + } + + /* need to create an SSV */ + mll_ssv_p = newMAINLLstruct(S_SSV, -1); + insertMAINLL(mll_ssv_p, mll_p); + mll_p = mll_ssv_p; + + /* populate the new SSV */ + nssv_p = mll_ssv_p->u.ssv_p; + if (beamstyle_ssv_p != 0) { + nssv_p->nbeam = beamstyle_ssv_p->nbeam; + nssv_p->beamstlist = beamstyle_ssv_p->beamstlist; + nssv_p->beamrests = beamstyle_ssv_p->beamrests; + nssv_p->beamspaces = beamstyle_ssv_p->beamspaces; + nssv_p->nsubbeam = beamstyle_ssv_p->nsubbeam; + nssv_p->subbeamstlist = beamstyle_ssv_p->subbeamstlist; + nssv_p->used[BEAMSTLIST] = YES; + } + if (timeunit_ssv_p != 0) { + nssv_p->timeunit = timeunit_ssv_p->timeunit; + nssv_p->used[TIMEUNIT] = YES; + } + + /* fill in the SSV header */ + if (v != 0) { + nssv_p->context = C_VOICE; + } + else if (s != 0) { + /* The [s][0] entry is for staff s + * when s > 0 */ + nssv_p->context = C_STAFF; + } + else { + /* The [0][0] entry is actually score */ + nssv_p->context = C_SCORE; + } + nssv_p->staffno = s; + nssv_p->voiceno = v; + asgnssv(nssv_p); + } + } + } +} diff --git a/mup/mup/tie.c b/mup/mup/tie.c new file mode 100644 index 0000000..41849e0 --- /dev/null +++ b/mup/mup/tie.c @@ -0,0 +1,1109 @@ + +/* Copyright (c) 1995, 1997, 1998, 1999, 2001, 2002 by Arkkra Enterprises */ +/* All rights reserved */ + +/* This file contains functions for handling ties and slurs. + * This includes doing error checking to make sure + * there is a note to tie/slur to. + * There is also code to add padding to make space for ties/slurs + * that are carried into second endings. */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + + + +/* lengths of line segments of carried in tie marks */ +#define HALFTIEPAD (3 * STEPSIZE) + +/* infomation about a tied or slurred note that gets carried into an ending */ +struct TIECARRY { + short letter; /* pitch to be tied or slurred to */ + short octave; /* octave of the pitch */ + short curveno; /* slurto index or -1 for tie */ + short is_bend; /* if slurto is actually a bend */ + struct MAINLL *mll_p; /* points to first group */ + struct GRPSYL *gs_p; /* group of first note */ + struct TIECARRY *next; /* linked list */ +}; + +/* linked list of tie carry info for each staff/voice */ +struct TIECARRY *Tiecarryinfolist_p [MAXSTAFFS + 1] [MAXVOICES]; + +/* flag to mark if there are any carry ins */ +static short Have_carry_ins = NO; + + +/* static functions */ +static void do_tie P((struct MAINLL *mll_p)); +static void do_group_ties P((struct GRPSYL *gs_p, struct MAINLL *mll_p)); +static void chk_slides P((struct NOTE *note_p, struct GRPSYL *gs_p, + struct MAINLL *mll_p)); +static void chk_following4slide P((struct NOTE *note_p, struct GRPSYL *gs_p, + struct MAINLL *mll_p)); +static struct MAINLL *do_carry_ties P((struct MAINLL *staff_mll_p, + struct MAINLL *bar_mll_p)); +static void savetieinfo P((struct MAINLL *mll_p, struct GRPSYL *gs_p)); +static void do_save_tieinfo P((int staffno, int vno, int letter, int octave, + int is_tie, struct MAINLL *mainll_p, struct GRPSYL *gs_p, + int is_bend)); +static void carryin_ties P((struct MAINLL *mll_p)); +static void add_carryin P((struct STAFF *staff_p)); +static void free_carryin_info P((void)); +static void free_cinfo P((struct TIECARRY *carryinfo_p)); +static void chk4xpose P((struct MAINLL *mll_p)); +static void chkxpstaff P((struct MAINLL *mll_p, int s)); +static void chkxpgrp P((struct GRPSYL *gs_p, char *inputfile, int lineno)); +static void set_inhibitprint_if_appropriate P((struct GRPSYL *gs_p, + struct MAINLL *mll_p)); + + + +/* 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); + } + } +} + + +/* 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); + } + } + } +} + + +/* 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"); + + } +} + + +/* 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
or <\\n>"); + break; + default: + break; + } + } + } + } +} + + +/* 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 ); +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* 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; +} + + +/* 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; + } + } +} + + +/* 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); + } + } + } +} + + +/* 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); +} + + +/* 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); + } + } + } + } +} + + +/* 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; + } + } + } +} + + +/* 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; + } + } + } + } +} + + +/* On tablature staffs, if two consecutive groups are tied together, + * normally the frets are not printed for the second group, so we need + * to set the inhibitprint flag on the group. However if there is any + * reason why inhibiting printing on a given group isn't a good idea, + * we won't set the inhibitprint flag. So this function checks all the + * possible reasons for not setting inhibitprint, and if none of them + * apply, then it is set. + */ + +static void +set_inhibitprint_if_appropriate(gs_p, mll_p) + +struct GRPSYL *gs_p; +struct MAINLL *mll_p; + +{ + struct GRPSYL *nextgs_p; /* the group after gs_p */ + struct GRPSYL *following_p; /* the group after next_gs_p */ + int n; /* index through notelist */ + + + + if ((nextgs_p = nextgrpsyl(gs_p, &mll_p)) == (struct GRPSYL *) 0) { + /* no next group, so nothing to set */ + return; + } + + /* if this group and next group don't have same number of notes, + * then there won't be an inhibitprint on the next group */ + if (gs_p->nnotes == 0 || gs_p->nnotes != nextgs_p->nnotes) { + return; + } + + /* if next group has a "with" list, no inhibitprint */ + if (nextgs_p->nwith != 0) { + return; + } + + for (n = 0; n < gs_p->nnotes; n++) { + /* if any notes in this group are not tied, then there won't be + * an inhibitprint on the next group */ + if (gs_p->notelist[n].tie == NO) { + return; + } + + /* if next group has any slides to/from nowhere, or slurs + * to the next group, it won't get inhibitprint set */ + if (nextgs_p->notelist[n].nslurto != 0) { + return; + } + } + + /* next group has a bend of any sort, it doesn't get inhibitprint */ + for (n = 0; n < nextgs_p->nnotes; n++) { + if (HASBEND(nextgs_p->notelist[n]) == YES) { + return; + } + } + + /* if group following next group has a non-prebend bend, then the + * next group does not get inhibitprint */ + if ((following_p = nextgrpsyl(nextgs_p, &mll_p)) != (struct GRPSYL *) 0) { + for (n = 0; n < following_p->nnotes; n++) { + if (HASBEND(following_p->notelist[n]) == YES && + following_p->notelist[n].FRETNO == NOFRET) { + return; + } + } + } + + /* Whew! If we got here, the group passed all the tests to have its + * inhibitprint flag set, so set it */ + nextgs_p->inhibitprint = YES; +} diff --git a/mup/mup/trantab.c b/mup/mup/trantab.c new file mode 100644 index 0000000..f04e9bb --- /dev/null +++ b/mup/mup/trantab.c @@ -0,0 +1,1662 @@ +/* Copyright (c) 1997, 1998, 2000, 2001, 2002, 2004 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: trantab.c + * + * Description: This file contains functions for translating tablature staffs + * to their corresponding tabnote staffs. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +/* + * Define a temp structure for holding info about the note generated from a + * NOTE on a tablature staff. + */ +struct TABNOTENOTE { + char letter; /* 'a' to 'g' */ + char accidental; /* '\0', 'x', '#', 'n', '&', 'B'(double flat)*/ + int octave; /* 0 to 9 */ + int hs; /* half steps above c0 */ + int strno; /* the string this note is played on */ + struct NOTE *note_p; /* point to the NOTE this is derived from */ +}; + +static void tabv2tabnotev P((struct MAINLL *mainll_p, int vidx)); +static void fixprevmeas P((struct GRPSYL *ngs_p, struct MAINLL *mll_p)); +static int hasprebend P((struct GRPSYL *gs_p)); +static int cancombine P((struct MAINLL *mll_p, struct GRPSYL *tgs_p, + RATIONAL *comp_p)); +static RATIONAL calctime P((struct GRPSYL *gs_p)); +static void translate_group P((struct GRPSYL *tgs_p, struct GRPSYL *pregs_p, + struct GRPSYL *ngs_p, struct MAINLL *mll_p, int combine)); +static void calcnote P((struct STRINGINFO *sinfo_p, int fretno, RATIONAL bend, + int sharps, struct TABNOTENOTE *note_p, struct GRPSYL *tgs_p)); +static int findfret P((struct GRPSYL *tgs_p, struct MAINLL *mll_p, int strno)); +static void popnotes P((struct GRPSYL *gs_p, struct TABNOTENOTE tnn[], + int ntnn, struct GRPSYL *tgs_p, struct MAINLL *mll_p, + int is_prebend, int combine, int sharps)); +static int neighbor P((struct TABNOTENOTE *high_p, struct TABNOTENOTE *low_p)); +static int inkeysig P((struct TABNOTENOTE *note_p, int sharps)); +static int upletter P((struct TABNOTENOTE *note_p)); +static int downletter P((struct TABNOTENOTE *note_p)); +static void cleanaccs P((struct GRPSYL *gs_p, struct MAINLL *mll_p)); + +/* + * 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); + } + } +} + +/* + * 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); + } + } + } +} + +/* + * 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; + } + } + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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)))); +} + +/* + * 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); +} + +/* + * 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"); + } +} + +/* + * 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); + } +} + +/* + * 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; + } + } + } + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * Name: cleanaccs() + * + * Abstract: Remove unnecessary accidentals from a tabnote staff measure. + * + * Returns: void + * + * Description: This function removes all the unnecessary accidentals from one + * measure of a tabnote staff. It takes into consideration the + * key signature and the fact that accidentals last for the + * duration of the measure unless changed by another accidental. + * Also, if a note in the first group was tied from the previous + * measure, any accidental is carried over to this note and + * any series of notes it ties into, but if the note occurs again + * in this measure it reverts to the key signature; so the bottom + * line is we can ignore this and pretend that the tied note is in + * the key signature. + */ + +static void +cleanaccs(gs_p, mll_p) + +struct GRPSYL *gs_p; /* starts at first tabnote GRPSYL */ +struct MAINLL *mll_p; /* main LL struct that tabnote staff hangs off*/ + +{ + /* current accidental for letter and octave */ + char curacc[7][MAXOCTAVE + 1]; /* assumes MINOCTAVE == 0 */ + + int oct; /* octave number */ + char let; /* note letter */ + int sharps; /* number of sharps in tabnote staff's keysig*/ + int cidx; /* index into circle of fifths */ + struct GRPSYL *prevgs_p;/* pointer to preceding GRPSYL */ + struct NOTE *note_p; /* pointer to a NOTE structure */ + int n, k; /* loop variables */ + + + + /* + * Initialize the table to say that for all octaves of all letters, + * the accidental is a natural. + */ + for (oct = 0; oct <= MAXOCTAVE; oct++) { + for (let = 'a'; let <= 'g'; let++) { + curacc[let - 'a'] [oct] = 'n'; + } + } + + /* find the key signature; flats count negative */ + sharps = svpath(gs_p->staffno, SHARPS)->sharps; + + /* + * Load the key signature's accidentals into the array for every + * octave. + */ + for (oct = 0; oct <= 9; oct++) { + for (cidx = 0; cidx < sharps; cidx++) { + curacc[ Circle[cidx] - 'a' ] [oct] = '#'; + } + for (cidx = 0; cidx > sharps; cidx--) { + curacc[ Circle[6 + cidx] - 'a' ] [oct] = '&'; + } + } + + /* + * Loop through every note group and every note in them, clearing + * accidentals when that accidental is already in force, and updating + * the table when not. + */ + for ( ; gs_p != 0; gs_p = gs_p->next) { + if (gs_p->grpcont != GC_NOTES) + continue; + + /* find previous group; could be in previous measure if any */ + prevgs_p = prevgrpsyl(gs_p, &mll_p); + + for (n = 0; n < gs_p->nnotes; n++) { + note_p = &gs_p->notelist[n]; + + /* + * If the note is the destination of a tie, blow away + * its accidental. This wouldn't have to be a special + * check if it weren't for ties across bar lines. + */ + if (prevgs_p != 0 && prevgs_p->grpcont == GC_NOTES) { + for (k = 0; k < prevgs_p->nnotes; k++) { + if (prevgs_p->notelist[k].tie == YES && + prevgs_p->notelist[k].letter == + note_p->letter && prevgs_p->notelist + [k].octave == note_p->octave) { + note_p->accidental = '\0'; + break; + } + } + /* if we found it was tied, continue to next */ + if (k < prevgs_p->nnotes) + continue; + } + /* + * If this note's accidental agrees with the accidental + * already in force for this letter and octave, wipe it + * out. If it doesn't, leave it alone, and update the + * table to show the new accidental that is in force. + */ + if (note_p->accidental == curacc[ note_p->letter - 'a' ] + [ note_p->octave ]) { + note_p->accidental = '\0'; + } else { + curacc[ note_p->letter - 'a' ] [ note_p-> + octave ] = note_p->accidental; + } + } + } +} diff --git a/mup/mup/trnspose.c b/mup/mup/trnspose.c new file mode 100644 index 0000000..6dd5dab --- /dev/null +++ b/mup/mup/trnspose.c @@ -0,0 +1,819 @@ +/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2002, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ +/* + * Name: trnspose.c + * + * Description: This file contains functions for transposing to different keys. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +#define BAD (99) /* a bad interval */ + +/* + * For each possible transposition, this table shows the change in the number + * of sharps in whatever key we are in. Invalid intervals are marked as BAD. + */ +static short Delshtab[5][8] = { + /* 1 2 3 4 5 6 7 */ + + { 0, -7, -12, -10, -8, -6, -11, -9 }, /* d */ + { 0, BAD, -5, -3, BAD, BAD, -4, -2 }, /* m */ + { 0, 0, BAD, BAD, -1, 1, BAD, BAD }, /* P */ + { 0, BAD, 2, 4, BAD, BAD, 3, 5 }, /* M */ + { 0, 7, 9, 11, 6, 8, 10, 12 }, /* A */ +}; + +/* index this by an interval type to get a string naming it */ +static char *Inttab[] = + { "diminished", "minor", "perfect", "major", "augmented" }; + +/* + * The following hold the transposition information for the score and all the + * staffs. After every bar line it is updated if the transposition changed. + * The score's info is stored in inttype[0], intnum[0], and octint[0]. + */ +static int inttype[MAXSTAFFS+1]; /* interval type of simple interval */ +static int intnum[MAXSTAFFS+1]; /* simple interval (>0, octs removed)*/ +static int octint[MAXSTAFFS+1]; /* number of octaves in interval */ + + +static void transnote P((struct GRPSYL *g_p, struct NOTE *n_p, int inttype, + int intnum, int octint)); +static void translurto P((struct GRPSYL *g_p, struct NOTE *n_p, int tnum, + int toct)); +static void simptrans P((int origtype, int orignum, int *inttype_p, + int *intnum_p, int *octint_p)); +static void fixslurto P((int s, struct MAINLL *mainll_p, int nintnum, + int noctint)); + +/* + * 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; + } + } +} + +/* + * 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); +} + +/* + * 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; + } +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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; + } + } +} + +/* + * 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); + } + } +} + +/* + * Name: totaltrans() + * + * Abstract: Find the current total transposition of a staff or the score. + * + * Returns: void + * + * Description: This function is given a staff number, or zero for the score. + * It assumes that the SSVs are up to date. It gets the two + * tranposition parameters, and adds them to get the current + * total transpostion. If it's invalid, it does a ufatal. + */ + +void +totaltrans(s, type_p, num_p) + +int s; /* staff number, or 0 for score */ +int *type_p; /* return type of resulting transposition */ +int *num_p; /* return number of resulting transposition */ + +{ + /* + * inths is to be indexed by interval type and number (1 through 7). + * It gives the number of half steps in the interval. + */ + static short inths[5][8] = { + /* 1 2 3 4 5 6 7 */ + + { 0, -1, 0, 2, 4, 6, 7, 9 }, /* d */ + { 0, BAD, 1, 3, BAD, BAD, 8, 10 }, /* m */ + { 0, 0, BAD, BAD, 5, 7, BAD, BAD }, /* P */ + { 0, BAD, 2, 4, BAD, BAD, 9, 11 }, /* M */ + { 0, 1, 3, 5, 6, 8, 10, 12 }, /* A */ + }; + + struct SSV *ssv_p; /* point at the SSV hold a transposition */ + int type[2]; /* interval types (DIMINISHED, MINOR, . . .) */ + int num[2]; /* interval numbers (down is negative) */ + int totalhs; /* total half steps in resulting interval */ + char place[15]; /* temp storage for error message use */ + int offset; /* like interval no. but counting from 0 */ + int n; /* loop variable */ + + + /* get the type and num of each transpostion interval */ + ssv_p = svpath(s, TRANSPOSITION); + type[0] = ssv_p->inttype; + num[0] = ssv_p->intnum; + ssv_p = svpath(s, ADDTRANSPOSITION); + type[1] = ssv_p->addinttype; + num[1] = ssv_p->addintnum; + + /* + * To get the interval number of the num of the transpostions, we + * basically add the two. But musicians unfortunately start counting + * intervals from 1 instead of 0, so we have to play some games. + */ + offset = (num[0] > 0 ? num[0] - 1 : num[0] + 1) + /* add true offsets*/ + (num[1] > 0 ? num[1] - 1 : num[1] + 1); + if (offset >= 0) { /* get interval number from offset */ + *num_p = offset + 1; + } else { + *num_p = offset - 1; + } + + /* accumulate total half steps in both transpositions */ + totalhs = 0; + for (n = 0; n < NUMELEM(num); n++) { + if (num[n] > 0) { /* interval is up */ + while (num[n] > 7) { + num[n] -= 7; /* subtract an octave */ + totalhs += 12; /* add 12 half steps */ + } + /* account for this simple interval */ + totalhs += inths[type[n]][num[n]]; + } else { /* interval is down */ + while (num[n] < -7) { + num[n] += 7; /* add an octave */ + totalhs -= 12; /* subtract 12 half steps */ + } + /* account for this simple interval */ + totalhs -= inths[type[n]][abs(num[n])]; + } + } + + /* if interval is down, find the up version of offset and halfsteps */ + if (offset < 0) { + offset = -offset; + totalhs = -totalhs; + } + /* bring it into the range of a simple interval */ + totalhs -= (offset / 7) * 12; + offset %= 7; + + /* make sure this simple interval is valid */ + if (totalhs < inths[DIMINISHED][offset + 1] || + totalhs > inths[AUGMENTED ][offset + 1]) { + + if (s == 0) { + (void)sprintf(place, "score"); + } else { + (void)sprintf(place, "staff %d", s); + } + ufatal("on %s, 'transpose' %s %s %d and 'addtranspose' %s %s %d add up to an invalid interval", + place, + num[0] > 0 ? "up" : "down", Inttab[type[0]], abs(num[0]), + num[1] > 0 ? "up" : "down", Inttab[type[1]], abs(num[1])); + } + + /* search table for the type of interval this is; it will be found */ + for (n = DIMINISHED; n <= AUGMENTED; n++) { + if (totalhs == inths[n][offset + 1]) { + break; + } + } + + *type_p = n; +} diff --git a/mup/mup/undrscre.c b/mup/mup/undrscre.c new file mode 100644 index 0000000..e45213c --- /dev/null +++ b/mup/mup/undrscre.c @@ -0,0 +1,1542 @@ +/* Copyright (c) 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003 by Arkkra Enterprises */ +/* All rights reserved */ + +/* This file contains functions that deal with + * extending underscores and dashes on lyric syllables. + */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +static double end_dashes P((struct MAINLL *mll_p, struct GRPSYL *syl_p, + int verse, int place, int *carryover_p)); +static double end_underscore P((struct MAINLL *mll_p, struct GRPSYL *syl_p, + int verse, int place, int *carryover_p)); +static double endx P((struct GRPSYL *last_grp_p, double end)); +static int has_above_lyr P((struct MAINLL *mll_p, RATIONAL begin_time, + struct GRPSYL *group_p, int verse)); +static int voice_is_above P((int v1, int v2)); +static struct GRPSYL *find_verse_place P((struct STAFF *staff_p, + int verse, int place)); +static RATIONAL default_end P((struct MAINLL *mll_p, struct GRPSYL *syl_p, + RATIONAL start_time, double *end_p)); +static int bar_ends_extender P((struct BAR *bar_p, struct MAINLL *mll_p, + int staffno, int verse, int place, + struct GRPSYL **nextsyl_p_p)); +static void pr_extender P((int ch, double start, double end, double y, + int font, int size)); +static void insert_carryover_syllable P((struct MAINLL *mll_p, int staffno, + int sylplace, int verseno, char *dash_or_underscore, + int font, int size)); +static void add_syllable P((struct STAFF *staff_p, int sylplace, int verseno, + char *dash_or_underscore, int font, int size, + double begin_x, struct CHORD *chord_p)); +static void stitch_syl_into_chord P((struct CHORD *chord_p, + struct GRPSYL *syl_gs_p)); + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* + * 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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]); +} + + +/* Given a syllable and chord to attach it to, attach it */ +/* Strictly speaking, this function probably isn't necessary, since I think + * all use of the CHORD struct has already been done before this function is + * called, but it's probably good to do anyway on general principles, in case + * some day the CHORDs are looked at later */ + +static void +stitch_syl_into_chord(chord_p, syl_gs_p) + +struct CHORD *chord_p; /* add to this chord */ +struct GRPSYL *syl_gs_p; /* add this syllable */ + +{ + struct GRPSYL *gs_p; /* walk through chord */ + + + /* go down chord list */ + for (gs_p = chord_p->gs_p; gs_p->gs_p != (struct GRPSYL *) 0; + gs_p = gs_p->gs_p) { + + /* if next grpsyl in chord has staffno < staffno of syl to add, + * keep going */ + if (gs_p->gs_p->staffno < syl_gs_p->staffno) { + continue; + } + + /* if next grpsyl in chord had staffno > staffno of syl to add, + * put it here */ + if (gs_p->gs_p->staffno > syl_gs_p->staffno) { + /* found where to insert */ + break; + } + + /* If here, must be same staffno. + * Keep going until find syllable with larger vno. */ + if (gs_p->gs_p->grpsyl == GS_GROUP) { + continue; + } + + if (gs_p->gs_p->vno > syl_gs_p->vno) { + /* found where to insert */ + break; + } + } + + /* insert syllable */ + syl_gs_p->gs_p = gs_p->gs_p; + gs_p->gs_p = syl_gs_p; +} diff --git a/mup/mup/utils.c b/mup/mup/utils.c new file mode 100644 index 0000000..3b70edc --- /dev/null +++ b/mup/mup/utils.c @@ -0,0 +1,2024 @@ + +/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* miscellaneous utility functions for music publication program, mostly + * for the print phase */ + +#include "defines.h" +#include "structs.h" +#include "globals.h" + +static void grp_octave_adjust P((struct GRPSYL *gs_p, int adj, struct MAINLL *mll_p)); +static void set_height_blockhead P((struct BLOCKHEAD *blockhead_p, int context, + struct MAINLL *mll_p)); +static double coord_staffscale P((float *coord_array)); + + + +/* 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; +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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); + } +} + + +/* 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))); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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)); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); +} + +/* + * 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 ]); +} + +/* + * 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); +} + + +/* 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; + } +} + + +/* 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; + } + } + } +} + + +/* 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); +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } +} + + +/* 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + +/* + * 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); +} + + +/* Return the width of the widest note head in the given GRPSYL. */ + +double +widest_head(gs_p) + +struct GRPSYL *gs_p; + +{ + double widest; /* widest note head in the group */ + double thiswidth; /* width of current note */ + int n; /* note index */ + + widest = 0.0; + for (n = 0; n < gs_p->nnotes; n++) { + thiswidth = width(gs_p->notelist[n].headfont, + (gs_p->notelist[n].notesize == GS_NORMAL ? + DFLT_SIZE : SMALLSIZE), + gs_p->notelist[n].headchar); + if (thiswidth > widest) { + widest = thiswidth; + } + } + return(widest); +} diff --git a/mup/mup/ytab.c b/mup/mup/ytab.c new file mode 100644 index 0000000..e3536b0 --- /dev/null +++ b/mup/mup/ytab.c @@ -0,0 +1,8414 @@ +/* A Bison parser, made from gram.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* Written by Richard Stallman by simplifying the original so called + ``semantic'' parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Pure parsers. */ +#define YYPURE 0 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_SCORE = 258, + T_STAFF = 259, + T_VOICE = 260, + T_GRIDS = 261, + T_BLOCKHEAD = 262, + T_NUMBER = 263, + T_EQUAL = 264, + T_SEMICOLON = 265, + T_NEWLINE = 266, + T_COLON = 267, + T_COMMA = 268, + T_LBRACKET = 269, + T_RBRACKET = 270, + T_LBRACE = 271, + T_RBRACE = 272, + T_VARIABLE = 273, + T_DASH = 274, + T_PLUS = 275, + T_PLACE = 276, + T_ALL = 277, + T_WITH = 278, + T_CUE = 279, + T_GRACE = 280, + T_XNOTE = 281, + T_DIAM = 282, + T_DOT = 283, + T_MULTIWHOLE = 284, + T_LET_M = 285, + T_LET_R = 286, + T_LET_S = 287, + T_LET_U = 288, + T_PITCH = 289, + T_SHARP = 290, + T_AMPERSAND = 291, + T_LET_N = 292, + T_LET_X = 293, + T_DBLFLAT = 294, + T_LETTER = 295, + T_LYRICS = 296, + T_PAD = 297, + T_LPAREN = 298, + T_RPAREN = 299, + T_LVAR = 300, + T_MUSIC = 301, + T_HEADSHAPES = 302, + T_HS = 303, + T_SWINGUNIT = 304, + T_POSTSCRIPT = 305, + T_SCOREFEED = 306, + T_BARTYPE = 307, + T_HAT = 308, + T_TILDE = 309, + T_QUESTION = 310, + T_LINETYPE = 311, + T_LINE = 312, + T_TO = 313, + T_STAR = 314, + T_BULGE = 315, + T_CURVE = 316, + T_TIE = 317, + T_PRINTTYPE = 318, + T_NL = 319, + T_STAFFLINES = 320, + T_FFAMILY = 321, + T_PARAGRAPH = 322, + T_PARATYPE = 323, + T_NUMVAR = 324, + T_FNUMVAR = 325, + T_2FNUMVAR = 326, + T_RATNUMLISTVAR = 327, + T_RANGELISTVAR = 328, + T_TIMEUNIT = 329, + T_FONTVAR = 330, + T_STRVAR = 331, + T_CLEFVAR = 332, + T_VVAR = 333, + T_BARSTLISTVAR = 334, + T_SCORESEP = 335, + T_FONT = 336, + T_SLASH = 337, + T_KEY = 338, + T_TIME = 339, + T_CUT = 340, + T_COMMON = 341, + T_CLEF = 342, + T_MULTIREST = 343, + T_YESNOVAR = 344, + T_BM = 345, + T_ESBM = 346, + T_EBM = 347, + T_INVISBAR = 348, + T_OCTAVE = 349, + T_ROLL = 350, + T_VISVAR = 351, + T_WHEREUSED = 352, + T_UNSET = 353, + T_VCOMBINE = 354, + T_VCOMBVAL = 355, + T_SCOREPAD = 356, + T_WORD = 357, + T_UP = 358, + T_DOWN = 359, + T_ENDING = 360, + T_ENDENDING = 361, + T_FAMILY = 362, + T_ENDSTYLE = 363, + T_ENDTYPE = 364, + T_SLASHMARK = 365, + T_ALT = 366, + T_TITLE = 367, + T_REHEARSAL = 368, + T_NUM = 369, + T_LET = 370, + T_MNUM = 371, + T_TRANSPOSE = 372, + T_XPOS_INT = 373, + T_PEDAL = 374, + T_PHRASE = 375, + T_MUSSYM = 376, + T_L_ANGLE = 377, + T_MODIFIER = 378, + T_R_ANGLE = 379, + T_TIL = 380, + T_MIDI = 381, + T_PEDSTYLE = 382, + T_PEDSTAR = 383, + T_HIDECHANGES = 384, + T_SLUR = 385, + T_UNITS = 386, + T_CENTIMETERS = 387, + T_UNITTYPE = 388, + T_TAB = 389, + T_TICKS = 390, + T_NOWHERE_SLIDE = 391, + T_LEN = 392, + T_EXCLAM = 393, + T_OTHERTEXT = 394, + T_ORDER = 395, + T_GRIDPLACE = 396, + T_GRPLVALUE = 397, + T_DRUM = 398, + T_RPT = 399, + T_STRING = 400, + T_HO = 401, + T_REH_STYLE = 402, + T_REHTYPE = 403, + T_L_DBLANGLE = 404, + T_R_DBLANGLE = 405, + T_SLOPE = 406, + T_PSVAR = 407, + T_PAGESIZE = 408, + T_ORIENTATION = 409 + }; +#endif +#define T_SCORE 258 +#define T_STAFF 259 +#define T_VOICE 260 +#define T_GRIDS 261 +#define T_BLOCKHEAD 262 +#define T_NUMBER 263 +#define T_EQUAL 264 +#define T_SEMICOLON 265 +#define T_NEWLINE 266 +#define T_COLON 267 +#define T_COMMA 268 +#define T_LBRACKET 269 +#define T_RBRACKET 270 +#define T_LBRACE 271 +#define T_RBRACE 272 +#define T_VARIABLE 273 +#define T_DASH 274 +#define T_PLUS 275 +#define T_PLACE 276 +#define T_ALL 277 +#define T_WITH 278 +#define T_CUE 279 +#define T_GRACE 280 +#define T_XNOTE 281 +#define T_DIAM 282 +#define T_DOT 283 +#define T_MULTIWHOLE 284 +#define T_LET_M 285 +#define T_LET_R 286 +#define T_LET_S 287 +#define T_LET_U 288 +#define T_PITCH 289 +#define T_SHARP 290 +#define T_AMPERSAND 291 +#define T_LET_N 292 +#define T_LET_X 293 +#define T_DBLFLAT 294 +#define T_LETTER 295 +#define T_LYRICS 296 +#define T_PAD 297 +#define T_LPAREN 298 +#define T_RPAREN 299 +#define T_LVAR 300 +#define T_MUSIC 301 +#define T_HEADSHAPES 302 +#define T_HS 303 +#define T_SWINGUNIT 304 +#define T_POSTSCRIPT 305 +#define T_SCOREFEED 306 +#define T_BARTYPE 307 +#define T_HAT 308 +#define T_TILDE 309 +#define T_QUESTION 310 +#define T_LINETYPE 311 +#define T_LINE 312 +#define T_TO 313 +#define T_STAR 314 +#define T_BULGE 315 +#define T_CURVE 316 +#define T_TIE 317 +#define T_PRINTTYPE 318 +#define T_NL 319 +#define T_STAFFLINES 320 +#define T_FFAMILY 321 +#define T_PARAGRAPH 322 +#define T_PARATYPE 323 +#define T_NUMVAR 324 +#define T_FNUMVAR 325 +#define T_2FNUMVAR 326 +#define T_RATNUMLISTVAR 327 +#define T_RANGELISTVAR 328 +#define T_TIMEUNIT 329 +#define T_FONTVAR 330 +#define T_STRVAR 331 +#define T_CLEFVAR 332 +#define T_VVAR 333 +#define T_BARSTLISTVAR 334 +#define T_SCORESEP 335 +#define T_FONT 336 +#define T_SLASH 337 +#define T_KEY 338 +#define T_TIME 339 +#define T_CUT 340 +#define T_COMMON 341 +#define T_CLEF 342 +#define T_MULTIREST 343 +#define T_YESNOVAR 344 +#define T_BM 345 +#define T_ESBM 346 +#define T_EBM 347 +#define T_INVISBAR 348 +#define T_OCTAVE 349 +#define T_ROLL 350 +#define T_VISVAR 351 +#define T_WHEREUSED 352 +#define T_UNSET 353 +#define T_VCOMBINE 354 +#define T_VCOMBVAL 355 +#define T_SCOREPAD 356 +#define T_WORD 357 +#define T_UP 358 +#define T_DOWN 359 +#define T_ENDING 360 +#define T_ENDENDING 361 +#define T_FAMILY 362 +#define T_ENDSTYLE 363 +#define T_ENDTYPE 364 +#define T_SLASHMARK 365 +#define T_ALT 366 +#define T_TITLE 367 +#define T_REHEARSAL 368 +#define T_NUM 369 +#define T_LET 370 +#define T_MNUM 371 +#define T_TRANSPOSE 372 +#define T_XPOS_INT 373 +#define T_PEDAL 374 +#define T_PHRASE 375 +#define T_MUSSYM 376 +#define T_L_ANGLE 377 +#define T_MODIFIER 378 +#define T_R_ANGLE 379 +#define T_TIL 380 +#define T_MIDI 381 +#define T_PEDSTYLE 382 +#define T_PEDSTAR 383 +#define T_HIDECHANGES 384 +#define T_SLUR 385 +#define T_UNITS 386 +#define T_CENTIMETERS 387 +#define T_UNITTYPE 388 +#define T_TAB 389 +#define T_TICKS 390 +#define T_NOWHERE_SLIDE 391 +#define T_LEN 392 +#define T_EXCLAM 393 +#define T_OTHERTEXT 394 +#define T_ORDER 395 +#define T_GRIDPLACE 396 +#define T_GRPLVALUE 397 +#define T_DRUM 398 +#define T_RPT 399 +#define T_STRING 400 +#define T_HO 401 +#define T_REH_STYLE 402 +#define T_REHTYPE 403 +#define T_L_DBLANGLE 404 +#define T_R_DBLANGLE 405 +#define T_SLOPE 406 +#define T_PSVAR 407 +#define T_PAGESIZE 408 +#define T_ORIENTATION 409 + + + + +/* Copy the first part of user declarations. */ +#line 2 "gram.y" + + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, + * 2005, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* parser for music publication program. Uses lex to get tokens. */ + + +#include "rational.h" +#include "globals.h" +#include "defines.h" +#include "structs.h" + +#define YYDEBUG 1 + + +/* how many items to allocate at a time for + * "with" list, and location lists, etc */ +#define ITEMS (4) + + +static struct MAINLL *Currstruct_p; /* main list struct being filled in */ +static struct BLOCKHEAD *Currblock_p; /* current block, if non-zero */ + +static struct INPCOORD *Curr_loc_info_p; /* location info being collected */ + + +static short Gotheader, Gotfooter; /* boolean: to make sure each is defined only once */ +static short Gothead2, Gotfoot2; +static short Getting_tup_dur; /* YES if currently collection tuplet + * duration rather than GRPSYL dur */ + +static struct GRPSYL *Curr_grpsyl_p; /* current GRPSYL struct being filled in */ +static struct GRPSYL *Last_grpsyl_p; /* previous GRPSYL struct filled in (contains + * defaults for the current one */ +static struct TIMELIST *Extra_time_p; /* If user enters times to be added + * together, like 2.+16 this points to + * a linked list of the extra times */ +static struct TIMELIST *Curr_timelist_p;/* current additive time, used to know + * where to link items to the list */ +static struct TIMELIST *Last_alloced_timelist_p; /* Most recently allocated + * list. Keeping track of this lets us + * avoid trying to free the list + * when Extra_time_p is pointing + * to a list from an SSV. */ +static struct GRPSYL *Prev_grpsyl_p; /* Like Last_grpsyl_p except in the + * case of additive times, + * in which case it points to the + * first group. This is needed in case + * the following group is to get its + * time value by defaulting to that + * of its previous group. */ +static int Extra_basictime; /* for saving basictime, when doing + * additive times */ +static int Doing_timeunit = NO; /* YES if gathering timeunit param */ +static struct GRPSYL *Lyrics_p; /* pointer to current list of lyrics */ +static char **Curr_marklist; /* current "with" list */ +static struct PRINTDATA **Next_print_link_p_p; /* points to where to attach next + * print command that we get */ +static int Item_count; /* items in current list */ +static int Max_items; /* current amount of space in lists + * "with" list, curve locations, etc) */ + +static int Plus_minus; /* if 1 add, if -1 subtract offset */ +static int Defining_multiple = NO; /* if defining multiple voices at once */ +static int Chord_at_a_time = NO; /* YES for chord-at-a-time, + * NO for voice-at-a-time */ +static short Endingloc; /* if current bar starts or ends an + * ending, etc (STARTITEM, ENDITEM, etc) */ +static short Got_ending; /* YES if got ending on this bar */ + +static int Til_bars; /* number of bars in "til" clause */ +static int Dist; /* dist for a specific STUFF */ +static int Dist_usage; /* meaning of Dist field */ +static short User_meas_time; /* YES if user specified a time for + * an 'm' item. Only valid on mr */ +static int Order_place; /* PL_* for markorder in SSV */ +static int Order_prio; /* value in markorder in SSV */ +static int Gracebackup; /* how many grace notes to back up + * before starting a "stuff" */ +static float Til_offset; /* beat count in "til" clause */ +static int Slurstyle; /* L_DOTTED, L_DASHED, or L_NORMAL */ + +static char *String1, *String2; /* to temporarily keep track + * of labels and other temporary + * strings */ +static char Tmpbuff[20]; /* temporary buffer for converting + * float numbers */ +static char Stringbuff[100]; /* temporary string storage */ +static int Titlefont, Titlesize; /* font/size for title command */ +static double Extra; /* extra vertical space for prints */ +static short Good_till_canceled = NO; /* if [] things should be continued + * until turned off */ +static short Curr_paratype = J_JUSTPARA; /* current paragraph type */ +static struct TIMEDSSV *Curr_tssv_p; /* current mid-measure param change */ +static char Timerep[MAXTSLEN]; /* Internal representation of time + * signature being collected */ +static int Tsig_offset; /* Current place in Timerep while + * collecting a time signature */ +static char *Alt_timesig_list; /* If user specified alternating + * time signatures, this points to + * the beginning of the list, for + * when we need to wrap around */ +static char *Next_alt_timesig; /* If user specified alternating + * time signatures, this points to + * the one for the next measure */ +static short Tsig_visibility; /* If EACHMEAS, alternating + * time signatures will be done + * by explicitly printing + * the appropriate time signature at + * the beginning of every measure, + * rather than printing them all just + * once at the beginning of the run + * of measures that alternate. */ + +/* Row index values must match the PS_* value definitions in defines.h. + * Column [0] is height in portrait mode, and column [1] is height. */ +double pagesztbl[7][2] = { + { 8.5, 11.0 }, /* PS_LETTER */ + { 8.5, 14.0 }, /* PS_LEGAL */ + { 8.5, 13.0 }, /* PS_FLSA */ + { 5.5, 8.5 }, /* PS_HALFLETTER */ + { 8.26, 11.69 }, /* PS_A4 */ + { 5.84, 8.26 }, /* PS_A5 */ + { 4.12, 5.84 } /* PS_A6 */ +}; + + + +/* static functions */ +static char *stripquotes P((char *string)); /* rmv double quotes + * from string */ +static void chkdup_headfoot P((int flag, char *which)); +static void end_prev_context P((void)); +static void var_valid P((void)); /* check if okay to set location var */ +static void proc_printcmd P((int justifytype, struct INPCOORD *inpc_p, + char *str, int font, int size, int got_nl, + int isPostScript, double extra)); +static double extra_needed P((int font, int size, char *string)); +static void keyword_notes P((char *str)); +static void free_extra_time P((void)); +static void tsig_item P((int item)); + + + + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +#ifndef YYSTYPE +#line 152 "gram.y" +typedef union { +int intval; /* for tokens/nonterminals that return int values */ +char *stringval; /* for tokens/nonterminals that return strings */ +float floatval; /* for nonterminals that return floats */ +RATIONAL ratval; /* for nonterminals that return rational numbers */ +struct INPCOORD *inpcoord_p; /* for nonterminals that return coord info */ +} yystype; +/* Line 193 of /usr/share/bison/yacc.c. */ +#line 536 "y.tab.c" +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif + +#ifndef YYLTYPE +typedef struct yyltype +{ + int first_line; + int first_column; + int last_line; + int last_column; +} yyltype; +# define YYLTYPE yyltype +# define YYLTYPE_IS_TRIVIAL 1 +#endif + +/* Copy the second part of user declarations. */ + + +/* Line 213 of /usr/share/bison/yacc.c. */ +#line 557 "y.tab.c" + +#if ! defined (yyoverflow) || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* 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 /* 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 /* 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 + + + +#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 */ + + + +#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; + } +} + + + +/* 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" + + 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 + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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"); + } +} + + +/* 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; +} + + +/* 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); + } +} + + +/* 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); + } + } +} + + +/* 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; +} + + +/* Add an item to the internal representation of the time signature + * currently being collected */ + +static void +tsig_item(item) + +int item; /* the byte to add to timerep */ + +{ + if (Tsig_offset >= MAXTSLEN - 1) { + l_ufatal(Curr_filename, yylineno, + "time signature is too complicated"); + } + Timerep[Tsig_offset++] = (char) item; +} + diff --git a/mup/mup/ytab.h b/mup/mup/ytab.h new file mode 100644 index 0000000..ce5234a --- /dev/null +++ b/mup/mup/ytab.h @@ -0,0 +1,363 @@ +/* A Bison parser, made from gram.y, by GNU bison 1.75. */ + +/* Skeleton parser for Yacc-like parsing with Bison, + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +#ifndef BISON_Y_TAB_H +# define BISON_Y_TAB_H + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + T_SCORE = 258, + T_STAFF = 259, + T_VOICE = 260, + T_GRIDS = 261, + T_BLOCKHEAD = 262, + T_NUMBER = 263, + T_EQUAL = 264, + T_SEMICOLON = 265, + T_NEWLINE = 266, + T_COLON = 267, + T_COMMA = 268, + T_LBRACKET = 269, + T_RBRACKET = 270, + T_LBRACE = 271, + T_RBRACE = 272, + T_VARIABLE = 273, + T_DASH = 274, + T_PLUS = 275, + T_PLACE = 276, + T_ALL = 277, + T_WITH = 278, + T_CUE = 279, + T_GRACE = 280, + T_XNOTE = 281, + T_DIAM = 282, + T_DOT = 283, + T_MULTIWHOLE = 284, + T_LET_M = 285, + T_LET_R = 286, + T_LET_S = 287, + T_LET_U = 288, + T_PITCH = 289, + T_SHARP = 290, + T_AMPERSAND = 291, + T_LET_N = 292, + T_LET_X = 293, + T_DBLFLAT = 294, + T_LETTER = 295, + T_LYRICS = 296, + T_PAD = 297, + T_LPAREN = 298, + T_RPAREN = 299, + T_LVAR = 300, + T_MUSIC = 301, + T_HEADSHAPES = 302, + T_HS = 303, + T_SWINGUNIT = 304, + T_POSTSCRIPT = 305, + T_SCOREFEED = 306, + T_BARTYPE = 307, + T_HAT = 308, + T_TILDE = 309, + T_QUESTION = 310, + T_LINETYPE = 311, + T_LINE = 312, + T_TO = 313, + T_STAR = 314, + T_BULGE = 315, + T_CURVE = 316, + T_TIE = 317, + T_PRINTTYPE = 318, + T_NL = 319, + T_STAFFLINES = 320, + T_FFAMILY = 321, + T_PARAGRAPH = 322, + T_PARATYPE = 323, + T_NUMVAR = 324, + T_FNUMVAR = 325, + T_2FNUMVAR = 326, + T_RATNUMLISTVAR = 327, + T_RANGELISTVAR = 328, + T_TIMEUNIT = 329, + T_FONTVAR = 330, + T_STRVAR = 331, + T_CLEFVAR = 332, + T_VVAR = 333, + T_BARSTLISTVAR = 334, + T_SCORESEP = 335, + T_FONT = 336, + T_SLASH = 337, + T_KEY = 338, + T_TIME = 339, + T_CUT = 340, + T_COMMON = 341, + T_CLEF = 342, + T_MULTIREST = 343, + T_YESNOVAR = 344, + T_BM = 345, + T_ESBM = 346, + T_EBM = 347, + T_INVISBAR = 348, + T_OCTAVE = 349, + T_ROLL = 350, + T_VISVAR = 351, + T_WHEREUSED = 352, + T_UNSET = 353, + T_VCOMBINE = 354, + T_VCOMBVAL = 355, + T_SCOREPAD = 356, + T_WORD = 357, + T_UP = 358, + T_DOWN = 359, + T_ENDING = 360, + T_ENDENDING = 361, + T_FAMILY = 362, + T_ENDSTYLE = 363, + T_ENDTYPE = 364, + T_SLASHMARK = 365, + T_ALT = 366, + T_TITLE = 367, + T_REHEARSAL = 368, + T_NUM = 369, + T_LET = 370, + T_MNUM = 371, + T_TRANSPOSE = 372, + T_XPOS_INT = 373, + T_PEDAL = 374, + T_PHRASE = 375, + T_MUSSYM = 376, + T_L_ANGLE = 377, + T_MODIFIER = 378, + T_R_ANGLE = 379, + T_TIL = 380, + T_MIDI = 381, + T_PEDSTYLE = 382, + T_PEDSTAR = 383, + T_HIDECHANGES = 384, + T_SLUR = 385, + T_UNITS = 386, + T_CENTIMETERS = 387, + T_UNITTYPE = 388, + T_TAB = 389, + T_TICKS = 390, + T_NOWHERE_SLIDE = 391, + T_LEN = 392, + T_EXCLAM = 393, + T_OTHERTEXT = 394, + T_ORDER = 395, + T_GRIDPLACE = 396, + T_GRPLVALUE = 397, + T_DRUM = 398, + T_RPT = 399, + T_STRING = 400, + T_HO = 401, + T_REH_STYLE = 402, + T_REHTYPE = 403, + T_L_DBLANGLE = 404, + T_R_DBLANGLE = 405, + T_SLOPE = 406, + T_PSVAR = 407, + T_PAGESIZE = 408, + T_ORIENTATION = 409 + }; +#endif +#define T_SCORE 258 +#define T_STAFF 259 +#define T_VOICE 260 +#define T_GRIDS 261 +#define T_BLOCKHEAD 262 +#define T_NUMBER 263 +#define T_EQUAL 264 +#define T_SEMICOLON 265 +#define T_NEWLINE 266 +#define T_COLON 267 +#define T_COMMA 268 +#define T_LBRACKET 269 +#define T_RBRACKET 270 +#define T_LBRACE 271 +#define T_RBRACE 272 +#define T_VARIABLE 273 +#define T_DASH 274 +#define T_PLUS 275 +#define T_PLACE 276 +#define T_ALL 277 +#define T_WITH 278 +#define T_CUE 279 +#define T_GRACE 280 +#define T_XNOTE 281 +#define T_DIAM 282 +#define T_DOT 283 +#define T_MULTIWHOLE 284 +#define T_LET_M 285 +#define T_LET_R 286 +#define T_LET_S 287 +#define T_LET_U 288 +#define T_PITCH 289 +#define T_SHARP 290 +#define T_AMPERSAND 291 +#define T_LET_N 292 +#define T_LET_X 293 +#define T_DBLFLAT 294 +#define T_LETTER 295 +#define T_LYRICS 296 +#define T_PAD 297 +#define T_LPAREN 298 +#define T_RPAREN 299 +#define T_LVAR 300 +#define T_MUSIC 301 +#define T_HEADSHAPES 302 +#define T_HS 303 +#define T_SWINGUNIT 304 +#define T_POSTSCRIPT 305 +#define T_SCOREFEED 306 +#define T_BARTYPE 307 +#define T_HAT 308 +#define T_TILDE 309 +#define T_QUESTION 310 +#define T_LINETYPE 311 +#define T_LINE 312 +#define T_TO 313 +#define T_STAR 314 +#define T_BULGE 315 +#define T_CURVE 316 +#define T_TIE 317 +#define T_PRINTTYPE 318 +#define T_NL 319 +#define T_STAFFLINES 320 +#define T_FFAMILY 321 +#define T_PARAGRAPH 322 +#define T_PARATYPE 323 +#define T_NUMVAR 324 +#define T_FNUMVAR 325 +#define T_2FNUMVAR 326 +#define T_RATNUMLISTVAR 327 +#define T_RANGELISTVAR 328 +#define T_TIMEUNIT 329 +#define T_FONTVAR 330 +#define T_STRVAR 331 +#define T_CLEFVAR 332 +#define T_VVAR 333 +#define T_BARSTLISTVAR 334 +#define T_SCORESEP 335 +#define T_FONT 336 +#define T_SLASH 337 +#define T_KEY 338 +#define T_TIME 339 +#define T_CUT 340 +#define T_COMMON 341 +#define T_CLEF 342 +#define T_MULTIREST 343 +#define T_YESNOVAR 344 +#define T_BM 345 +#define T_ESBM 346 +#define T_EBM 347 +#define T_INVISBAR 348 +#define T_OCTAVE 349 +#define T_ROLL 350 +#define T_VISVAR 351 +#define T_WHEREUSED 352 +#define T_UNSET 353 +#define T_VCOMBINE 354 +#define T_VCOMBVAL 355 +#define T_SCOREPAD 356 +#define T_WORD 357 +#define T_UP 358 +#define T_DOWN 359 +#define T_ENDING 360 +#define T_ENDENDING 361 +#define T_FAMILY 362 +#define T_ENDSTYLE 363 +#define T_ENDTYPE 364 +#define T_SLASHMARK 365 +#define T_ALT 366 +#define T_TITLE 367 +#define T_REHEARSAL 368 +#define T_NUM 369 +#define T_LET 370 +#define T_MNUM 371 +#define T_TRANSPOSE 372 +#define T_XPOS_INT 373 +#define T_PEDAL 374 +#define T_PHRASE 375 +#define T_MUSSYM 376 +#define T_L_ANGLE 377 +#define T_MODIFIER 378 +#define T_R_ANGLE 379 +#define T_TIL 380 +#define T_MIDI 381 +#define T_PEDSTYLE 382 +#define T_PEDSTAR 383 +#define T_HIDECHANGES 384 +#define T_SLUR 385 +#define T_UNITS 386 +#define T_CENTIMETERS 387 +#define T_UNITTYPE 388 +#define T_TAB 389 +#define T_TICKS 390 +#define T_NOWHERE_SLIDE 391 +#define T_LEN 392 +#define T_EXCLAM 393 +#define T_OTHERTEXT 394 +#define T_ORDER 395 +#define T_GRIDPLACE 396 +#define T_GRPLVALUE 397 +#define T_DRUM 398 +#define T_RPT 399 +#define T_STRING 400 +#define T_HO 401 +#define T_REH_STYLE 402 +#define T_REHTYPE 403 +#define T_L_DBLANGLE 404 +#define T_R_DBLANGLE 405 +#define T_SLOPE 406 +#define T_PSVAR 407 +#define T_PAGESIZE 408 +#define T_ORIENTATION 409 + + + + +#ifndef YYSTYPE +#line 152 "gram.y" +typedef union { +int intval; /* for tokens/nonterminals that return int values */ +char *stringval; /* for tokens/nonterminals that return strings */ +float floatval; /* for nonterminals that return floats */ +RATIONAL ratval; /* for nonterminals that return rational numbers */ +struct INPCOORD *inpcoord_p; /* for nonterminals that return coord info */ +} yystype; +/* Line 1281 of /usr/share/bison/yacc.c. */ +#line 356 "y.tab.h" +# define YYSTYPE yystype +#endif + +extern YYSTYPE yylval; + + +#endif /* not BISON_Y_TAB_H */ + diff --git a/mup/mupdisp/at386.c b/mup/mupdisp/at386.c new file mode 100644 index 0000000..abe96d8 --- /dev/null +++ b/mup/mupdisp/at386.c @@ -0,0 +1,262 @@ + +/* Copyright (c) 1995, 1996, 1998, 2000 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions to support displaying multipage bitmap + * (as from Ghostscript -sDEVICE=bit) to AT386 console. + */ + +#include "mupdisp.h" + +#if defined(AT386) && ! defined(linux) && ! defined(__DOS__) + +#include +#include + +#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)); + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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]; + } + } +} + + +/* 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); + } +} + + +#else + +/* some compilers complain about files that are effectively empty, + * so put in something even when entire file is effectively ifdef-ed out */ +static short dummy; + +#endif diff --git a/mup/mupdisp/dispttyp.h b/mup/mupdisp/dispttyp.h new file mode 100644 index 0000000..1ede728 --- /dev/null +++ b/mup/mupdisp/dispttyp.h @@ -0,0 +1,20 @@ + +/* Copyright (c) 1995, 1996, 1998 by Arkkra Enterprises */ +/* All rights reserved */ + +/* to compile Mup/Ghostscript display program + * to allow working on AT386 terminal type, make sure AT386 is + * defined. To compile to work on X-windows, make sure XWINDOW is defined. + * To work with either, define both. + * Support for other terminal types could be added in the future. */ + +#ifdef i386 +#if !defined(linux) && !defined(__EMX__) +#define AT386 1 +#endif +#endif + +#ifdef unix +#define XWINDOW 1 +#endif + diff --git a/mup/mupdisp/do_cmd.c b/mup/mupdisp/do_cmd.c new file mode 100644 index 0000000..deca4c6 --- /dev/null +++ b/mup/mupdisp/do_cmd.c @@ -0,0 +1,222 @@ + +/* Copyright (c) 1995 by Arkkra Enterprises */ +/* All rights reserved */ + +/* command processing function for Mup/Ghostscript display program. + * Given a input input character, does the appropriate command */ + + +/* The user interface commands are: + * + or or ^e or ^f scroll forwards 1/8" + * - or or ^y or ^b scroll backwards 1/8" + * f or 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" + + +/* command processing function for Mup/Ghostscript display program. + * Given a input input character, does the appropriate command */ + +void +do_cmd(c) + +int c; /* character read from user */ + +{ + static int line = 0; /* current line on page that + * is at top of screen */ + static int got1z = 0; /* if got one Z for vi-like ZZ exit */ + static int pgnum = -1; /* page number */ + static int count = 0; /* how many times called */ + static int lasterr = 0; /* value of count for last error */ + static int goofs = 0; /* how many consecutive user errors */ + + + /* count of times called, to implement auto-help if user goofs too + * many times in a row */ + count++; + + c = tolower(c); + + switch(c) { + + case '0': case '1': + case '2': case '3': + case '4': case '5': + case '6': case '7': + case '8': case '9': + /* gathering page number for specific page */ + if (pgnum < 0) { + /* first digit, so initialize page number */ + pgnum = 0; + } + pgnum = (pgnum * 10) + c - '0'; + break; + + case '+': + case ' ': + case '\5': /* control-E for vi users */ + case '\6': /* control-F for emacs users */ + /* scroll forward a little bit */ + if (Fullpgmode) { + ( *(Conf_info_p->error) ) ("command invalid in full page mode"); + } + else { + line = scroll(line, 9); + } + break; + + case '-': + case '\b': + case '\31': /* control-Y for vi users */ + case '\2': /* control-B for emacs users */ + /* backward a little bit */ + if (Fullpgmode) { + ( *(Conf_info_p->error) ) ("command invalid in full page mode"); + } + else { + line = scroll(line, -9); + } + break; + + case '\n': + case '\r': + if (pgnum >= 0) { + /* ending page number command */ + if (getpginfo(pgnum) == YES) { + ( *(Conf_info_p->draw) ) (0, Fullpgmode); + line = 0; + } + else { + ( *(Conf_info_p->error) ) ("invalid page number"); + } + pgnum = -1; + break; + } + /* else fall through to moving forward on page*/ + /*FALLTHRU*/ + + case 'f': + case '\4': /* control-D */ + case '\16': /* control-N */ + /* forward an inch */ + if (Fullpgmode) { + ( *(Conf_info_p->error) ) ("command invalid in full page mode"); + } + else { + line = scroll(line, 72); + } + break; + + case 'b': + case '\25': /* control-U */ + case '\20': /* control-P */ + /* back an inch */ + if (Fullpgmode) { + ( *(Conf_info_p->error) ) ("command invalid in full page mode"); + } + else { + line = scroll(line, -72); + } + break; + + case 'h': + case '?': + /* display help screen */ + ( *(Conf_info_p->bitmap) ) (Help_bitmap, Help_width, Help_height); + break; + + case 'n': + /* go to next page */ + if (Currpage_p->next != (struct Pginfo *) 0) { + Currpage_p = Currpage_p->next; + line = 0; + ( *(Conf_info_p->draw) ) (line, Fullpgmode); + } + else { + ( *(Conf_info_p->error) ) ("already at last page"); + } + break; + + case 'p': + /* go to previous page */ + if (Currpage_p->prev != (struct Pginfo *) 0) { + Currpage_p = Currpage_p->prev; + line = 0; + ( *(Conf_info_p->draw) ) (line, Fullpgmode); + } + else { + ( *(Conf_info_p->error) ) ("already at first page"); + } + break; + + case 'q': + /* quit */ + ( *(Conf_info_p->cleanup) ) (0); + break; + + case 'r': + /* repaint current screen */ + /* if redraw is because window was resized, make sure we don't + * run off the bottom */ + if (line + Conf_info_p->vlines > LINES_PER_PAGE * Conf_info_p->adjust) { + line = LINES_PER_PAGE * Conf_info_p->adjust - Conf_info_p->vlines; + } + ( *(Conf_info_p->draw) ) (line, Fullpgmode); + break; + + case 'z': + /* 2 Z's is symonym for quit, to match with common + * way to exit vi */ + if (got1z) { + ( *(Conf_info_p->cleanup) ) (0); + } + break; + + case 'm': + /* switch between full page and scrolled modes */ + Fullpgmode = (Fullpgmode == YES ? NO : YES); + line = 0; + ( *(Conf_info_p->draw) ) (line, Fullpgmode); + break; + + default: + ( *(Conf_info_p->error) ) ("unknown command"); + /* auto-help feature: + * if user puts in something illegal too many times in a row, + * figure they're confused and desperate, so give them the + * help screen */ + if (lasterr == count - 1) { + goofs++; + if (goofs > 9) { + ( *(Conf_info_p->bitmap) ) (Help_bitmap, + Help_width, Help_height); + goofs = 0; + } + } + else { + goofs = 1; + } + lasterr = count; + break; + } + + /* set flag if got Z, so can check for Z consecutive Z's for + * vi-style exit */ + got1z = (c == 'Z' || c == 'z'); +} diff --git a/mup/mupdisp/dos.c b/mup/mupdisp/dos.c new file mode 100644 index 0000000..b609df6 --- /dev/null +++ b/mup/mupdisp/dos.c @@ -0,0 +1,295 @@ + +/* Copyright (c) 1995, 1998 by Arkkra Enterprises */ +/* All rights reserved */ + +/* Functions for displaying Mup/Ghostscript output on screen using + * Watcom C */ + +#ifdef __WATCOMC__ +#include "mupdisp.h" +#include +#include +#include +#include +#include +#include +#include + +/* 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)); + + +/* 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); +} + + +/* before exiting, clean up graphics, then call the general cleanup routine */ + +void +dos_cleanup(int status) +{ + _setvideomode(_DEFAULTMODE); + generalcleanup(status); +} + + +/* 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); +} + + +/* for now we just beep on errors */ +/*ARGSUSED*/ +void +dos_error(msg) + +char *msg; + +{ + putc('\7', stderr); +} + + +/* 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; + } +} + + +/* 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); +} + +/* zero out a block of memory that may be bigger than 32K */ + +#define BLOCKSIZE 0x3fff + +static void +zapblock(area, size) + +char *area; +long size; + +{ + long k; + + /* + * memset's third parm is "unsigned int", so we can't do the whole + * area at once. + */ + for (k = 0; k < size; k += BLOCKSIZE) { + if (size - k >= BLOCKSIZE) + (void)memset(&area[k], 0, BLOCKSIZE); + else + (void)memset(&area[k], 0, size - k); + } +} + +#else + +/* some compilers don't like empty files, so if __WATCOMC__ isn't defined, + * put something here to keep those compilers happy */ +static short dummy; + +#endif diff --git a/mup/mupdisp/genfile.c b/mup/mupdisp/genfile.c new file mode 100644 index 0000000..e45669e --- /dev/null +++ b/mup/mupdisp/genfile.c @@ -0,0 +1,422 @@ + +/* Copyright (c) 1995, 1998, 1999, 2000, 2001 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions to generate the bitmap output file from the Mup input. + * Includes functions for running Mup to produce PostScript, and to run + * Ghostscript on the output of Mup */ + + +#ifdef __WATCOMC__ +#include +#include +#endif +#include +#include +#include "mupdisp.h" + +#ifdef unix +#include +#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)); + + +/* 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); + } +} + + +/* 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 +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); + } + } +} + + +/* execute Mup, putting output in Psfile */ + +void +run_mup(argv) + +char **argv; /* arguments to pass to Mup */ + +{ + int ret; + int child; + + +#ifdef unix + switch(child = fork()) { + case 0: + /* arrange to put output in Psfile */ + close(1); + dup(Psfile); + + /* execute Mup */ + execvp("mup", argv); + fprintf(stderr, "failed to execute Mup\n"); + exit(1); + case -1: + fprintf(stderr, "failed to fork Mup\n"); + generalcleanup(1); + /*NOTREACHED*/ + break; + default: + /* wait for Mup to complete */ + while (wait(&ret) != child) + ; + if (ret != 0) { + unlink(Mupfile); + generalcleanup(ret); + } + break; + } +#else +#ifdef __WATCOMC__ + /* arrange to put output in Psfile */ + close(1); + dup(Psfile); + + /* execute Mup */ + if ((ret = spawnvp(P_WAIT, "mup", argv)) != 0) { + if (errno != 0) { + perror("Mup failed"); + } + unlink(Mupfile); + exit(ret); + } +#else + fprintf(stderr, "unsupported platform\n"); +#endif +#endif +} diff --git a/mup/mupdisp/help.bm b/mup/mupdisp/help.bm new file mode 100644 index 0000000..0fc2e18 --- /dev/null +++ b/mup/mupdisp/help.bm @@ -0,0 +1,327 @@ +/* Copyright (c) 1995 by Arkkra Enterprises */ +/* All rights reserved */ + +int Help_width = 64; +int Help_height = 319; +unsigned char Help_bitmap[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc3, 0xe1, 0xff, 0xfe, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3e, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xe3, 0xf3, 0xff, 0xff, 0x9f, 0x1f, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xe1, 0xf7, 0xff, 0xff, 0x9f, 0x9f, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xe9, 0xf7, 0xff, 0xff, 0x9f, 0x9f, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x9f, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xec, 0xf7, 0xff, 0xf3, 0x9d, 0xf8, 0xff, 0x07, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xf0, 0x7f, 0xff, 0x8f, 0xff, 0xff, 0xe3, 0xff, 0xfe, 0xcf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xec, 0xe7, 0xff, 0xc7, 0x98, 0xf0, 0x07, 0x9f, 0x86, 0x31, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0x0f, 0xf9, 0xf8, 0x7f, 0x00, 0xf0, 0x3c, 0x03, 0x87, 0xfe, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcc, 0x6f, 0xfe, 0x1f, 0x80, 0xfc, 0x67, 0x9e, 0x73, 0x89, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9e, 0x4f, 0xf9, 0xf2, 0x7f, 0xc6, 0x67, 0x39, 0xce, 0x73, 0xfc, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x6f, 0xf8, 0x7f, 0x9c, 0xfc, 0xe7, 0x9e, 0x73, 0x9f, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xe7, 0xf9, 0xe7, 0x3f, 0xcf, 0x27, 0x39, 0xce, 0x73, 0xfc, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xde, 0x0f, 0xf9, 0xff, 0x9c, 0xdc, 0xe7, 0x9e, 0x01, 0x9f, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xe7, 0xf9, 0xe7, 0x3f, 0xcf, 0x38, 0x39, 0xce, 0x01, 0xfd, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xdf, 0x1f, 0xfc, 0x7f, 0x9f, 0xdc, 0xe7, 0x9c, 0x7f, 0x9f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3c, 0xe7, 0xf9, 0xe7, 0x3f, 0xcf, 0x33, 0x3c, 0x1c, 0x7f, 0xfd, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9f, 0x1f, 0xff, 0x1f, 0x9f, 0x9c, 0xe7, 0x9a, 0x7f, 0x9f, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xfc, 0xe7, 0xf9, 0xa7, 0x3f, 0xcf, 0x27, 0x38, 0xfe, 0x7f, 0xf9, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9f, 0x9f, 0xff, 0xc3, 0x9f, 0x1c, 0xe7, 0x92, 0x3b, 0x9f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x4f, 0xf9, 0x32, 0x7f, 0xc6, 0x67, 0x3b, 0xfe, 0x3b, 0xf9, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xfe, 0x0f, 0x9f, 0xff, 0xf2, 0x00, 0x10, 0x41, 0x87, 0x06, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0x1f, 0xf8, 0x78, 0xff, 0xc0, 0xf0, 0x88, 0x07, 0x07, 0xe0, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf9, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf1, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xfe, 0x00, 0xc1, 0xfc, 0x7f, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0f, 0x87, 0x18, 0xe7, 0xf8, 0x07, 0x81, 0xe0, 0x1c, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc6, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xce, 0x73, 0x9b, 0xe7, 0xfe, 0x33, 0x39, 0xce, 0x73, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xc7, 0xe7, 0xfe, 0x79, 0x39, 0xce, 0x73, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x01, 0xc7, 0xe7, 0xfe, 0x79, 0xc1, 0xce, 0x70, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xcc, 0x7f, 0xc7, 0xe7, 0xfe, 0x79, 0x99, 0xe0, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x7f, 0xd3, 0xe6, 0xfe, 0x79, 0x39, 0xc7, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x3b, 0xb9, 0xe4, 0xfe, 0x33, 0x39, 0xdf, 0xf1, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x04, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x83, 0x06, 0x10, 0xe1, 0xfe, 0x07, 0x84, 0x40, 0x38, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0x9f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0x8e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xfe, 0x08, 0x5f, 0xff, 0x1d, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x1c, 0x63, 0x87, 0x1c, 0x0f, 0x86, 0x18, 0xf0, 0x3e, 0x01, 0xf0, 0x3c, 0x03, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc6, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xcf, 0x12, 0x73, 0x9d, 0xcf, 0x27, 0x9c, 0xef, 0x3f, 0x8c, 0xe7, 0x39, 0xcc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x3e, 0x73, 0x9d, 0xce, 0x73, 0x9c, 0xe3, 0x3f, 0x9e, 0x67, 0x39, 0xcc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x3e, 0x01, 0x9b, 0xce, 0x73, 0x9c, 0xf0, 0x7f, 0x9e, 0x78, 0x39, 0xcc, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x3c, 0x7f, 0xcb, 0xce, 0x73, 0x9c, 0xf8, 0x3f, 0x9e, 0x73, 0x3c, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x3e, 0x7f, 0xc7, 0xce, 0x73, 0x9c, 0xef, 0xbf, 0x9e, 0x67, 0x38, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc6, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xcf, 0x3e, 0x3b, 0xe7, 0xcf, 0x27, 0x98, 0xe7, 0xbf, 0x8c, 0xe7, 0x3b, 0xfc, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1c, 0x1f, 0x07, 0xef, 0x07, 0x8f, 0xc4, 0x20, 0x7f, 0x81, 0xf0, 0x88, 0x06, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf9, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf1, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xdf, 0xff, 0xff, 0xff, 0x1f, 0xe0, 0xfe, 0x3f, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x1c, 0x3e, 0x06, 0x31, 0x81, 0x08, 0x43, 0xfc, 0x01, 0x8c, 0x60, 0x63, 0x86, 0x00, 0xf3, 0xfc, 0x03, 0xe0, 0x78, 0x06, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x93, 0x9d, 0xc7, 0x89, 0x39, 0xcc, 0xef, 0xf9, 0x19, 0xcf, 0x13, 0x12, 0x73, 0x8c, 0xf3, 0xff, 0x19, 0xce, 0x73, 0x99, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf3, 0x99, 0xc7, 0x9f, 0x39, 0xcc, 0x6f, 0xf3, 0xb9, 0xcf, 0x3f, 0x3e, 0x73, 0x9c, 0xf3, 0xff, 0x3c, 0xce, 0x73, 0x99, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf0, 0x09, 0xc7, 0x9f, 0xc1, 0xcc, 0x6f, 0xf3, 0xf9, 0xcf, 0x3f, 0x3e, 0x01, 0x9c, 0xf3, 0xff, 0x3c, 0xf0, 0x73, 0x98, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe3, 0xf9, 0xc7, 0x9f, 0x99, 0xe3, 0x1f, 0xf3, 0xf9, 0xcf, 0x3f, 0x3c, 0x7f, 0x9c, 0xf3, 0xff, 0x3c, 0xe6, 0x78, 0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf3, 0xf9, 0xc7, 0x9f, 0x39, 0xe3, 0x1f, 0xf3, 0xd9, 0xcf, 0x3f, 0x3e, 0x7f, 0x9c, 0xf3, 0x7f, 0x3c, 0xce, 0x71, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf1, 0xdc, 0xc7, 0x9f, 0x39, 0xf3, 0x3f, 0xf9, 0xb9, 0x8f, 0x3f, 0x3e, 0x3b, 0x9c, 0xf2, 0x7f, 0x19, 0xce, 0x77, 0xf8, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf8, 0x3e, 0x22, 0x0f, 0x84, 0x77, 0xbf, 0xf8, 0x7c, 0x40, 0x1c, 0x1f, 0x06, 0x08, 0x30, 0xff, 0x03, 0xe1, 0x10, 0x0c, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xe7, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xe3, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x87, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0x84, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xff, 0xe7, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xcd, 0xff, 0xe7, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xe7, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xc7, 0xf1, 0x9f, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xe7, 0xf0, 0x3f, 0xff, 0xfb, 0xff, 0xff, 0x02, 0x3b, 0xe7, 0x3f, 0xc7, 0xff, 0xff, 0xf1, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x00, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf8, 0x78, 0x06, 0x01, 0x9e, 0x1f, 0xf3, 0xf0, 0xff, 0x81, 0x80, 0x3e, 0x07, 0xfc, 0xc6, 0x38, 0x60, 0x10, 0x7f, 0xcc, 0x31, 0xe7, 0x3f, 0x80, 0x78, 0x1e, 0x01, 0xc3, 0xf8, 0x04, 0x1f, 0x0f, 0x81, 0xe1, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc6, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf2, 0x73, 0x9c, 0xe7, 0x99, 0xcf, 0xf3, 0xe4, 0xff, 0x39, 0xe3, 0x3d, 0xc7, 0xfc, 0xf1, 0x32, 0x78, 0xc6, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe3, 0x33, 0x9c, 0xe7, 0x39, 0xfe, 0x31, 0x9e, 0x4f, 0x71, 0x9c, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x33, 0x9c, 0xe7, 0x99, 0xcf, 0xf3, 0xce, 0x7f, 0x39, 0xe7, 0x39, 0xc7, 0xfc, 0xf3, 0xe7, 0x39, 0xce, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe7, 0x93, 0x9c, 0xe7, 0x39, 0xfe, 0x73, 0x9c, 0xe6, 0x71, 0x9c, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x33, 0x9c, 0xe7, 0x98, 0x07, 0xf3, 0xce, 0x7f, 0xc1, 0xe7, 0x39, 0xc7, 0xfc, 0xf3, 0xe7, 0x39, 0xce, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe7, 0x9c, 0x1c, 0xe7, 0x00, 0xfe, 0x73, 0x9c, 0xe6, 0x71, 0x80, 0x7f, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe7, 0x38, 0x3e, 0x0f, 0x91, 0xff, 0xf3, 0xce, 0x7f, 0x99, 0xe7, 0x39, 0xc7, 0xfc, 0xf3, 0xe7, 0x39, 0xce, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe7, 0x99, 0x9e, 0x0e, 0x3f, 0xfe, 0x73, 0x9c, 0xe6, 0x71, 0x1f, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xa7, 0x31, 0xfc, 0x7f, 0x99, 0xff, 0xf3, 0x4e, 0x7f, 0x39, 0xe7, 0x39, 0xc7, 0xfc, 0xf3, 0xe7, 0x39, 0xce, 0x7f, 0xcf, 0x39, 0xe7, 0x3f, 0xe7, 0x93, 0x9c, 0x7f, 0x3f, 0xfe, 0x73, 0x9c, 0xe6, 0x71, 0x9f, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x32, 0x77, 0xfd, 0xff, 0x98, 0xef, 0xf2, 0x64, 0xff, 0x39, 0xe7, 0x3c, 0xc7, 0xfc, 0xf3, 0xf2, 0x79, 0xce, 0x7f, 0xcf, 0x31, 0xe7, 0x3f, 0xe3, 0x33, 0x9d, 0xff, 0x1d, 0xfe, 0x73, 0x9e, 0x4f, 0x31, 0x8e, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x78, 0xf0, 0x0c, 0x02, 0x0c, 0x1f, 0xf0, 0xf1, 0xff, 0x84, 0x02, 0x0e, 0x23, 0xf0, 0x41, 0xf8, 0xe0, 0x84, 0x1f, 0x07, 0x88, 0x00, 0x1f, 0xe0, 0x78, 0x44, 0x03, 0x83, 0xf8, 0x21, 0x07, 0x1f, 0x88, 0xc1, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xfc, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc9, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xf9, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x88, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xf8, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xfc, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x7c, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0x71, 0xff, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff, 0x8f, 0xff, 0xcf, 0xff, 0xf1, 0xc7, 0xff, 0xff, 0xfc, 0x1d, 0xff, 0xfc, 0xfe, 0x3f, 0xff, 0xff, 0xc7, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xfc, 0x7f, 0xc8, 0x21, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x70, 0x0c, 0x70, 0xf3, 0xcc, 0x20, 0x0f, 0x00, 0xff, 0x07, 0x0c, 0x02, 0x0c, 0x02, 0x0f, 0x03, 0x00, 0x7c, 0x0e, 0x07, 0xf3, 0x80, 0x78, 0x18, 0xc6, 0x70, 0xf0, 0x3c, 0xfc, 0x03, 0xe0, 0x78, 0x06, 0x1f, 0xc0, 0x20, 0xf8, 0x7c, 0x0f, 0x87, 0xfe, 0x18, 0x03, 0xcc, 0x63, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0x64, 0x62, 0x64, 0xf3, 0xcf, 0x38, 0xce, 0x73, 0xfe, 0x46, 0x4f, 0x18, 0xcf, 0x18, 0xce, 0x73, 0xc6, 0x7b, 0x8d, 0xe7, 0xf3, 0xe3, 0x33, 0x9e, 0x26, 0x7c, 0xe7, 0x3c, 0xff, 0x19, 0xce, 0x73, 0x99, 0xcf, 0xf1, 0x8c, 0xf2, 0x7b, 0x8e, 0x73, 0xfc, 0x9e, 0x33, 0xce, 0x77, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc6, 0x4e, 0xe7, 0xce, 0x73, 0xcf, 0x39, 0xce, 0x73, 0xfc, 0xec, 0xe7, 0x39, 0xcf, 0x39, 0xce, 0x73, 0xce, 0x73, 0x8c, 0x67, 0xf3, 0xe7, 0x93, 0x9e, 0x7e, 0x7c, 0xe7, 0x3c, 0xff, 0x3c, 0xce, 0x73, 0x99, 0xcf, 0xf3, 0x9c, 0xe7, 0x33, 0x8e, 0x73, 0xf9, 0xce, 0x73, 0xce, 0x77, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xcf, 0xe7, 0xce, 0x73, 0xcf, 0x39, 0xce, 0x73, 0xfc, 0xfc, 0xe7, 0x39, 0xcf, 0x39, 0xcf, 0x83, 0xce, 0x73, 0x8e, 0x0f, 0xf3, 0xe7, 0x9c, 0x1e, 0x7e, 0x7c, 0xf8, 0x3c, 0xff, 0x3c, 0xf0, 0x73, 0x98, 0x07, 0xf3, 0x9c, 0xe7, 0x33, 0x8e, 0x01, 0xf9, 0xce, 0x73, 0xcf, 0x2f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x4f, 0xe7, 0xce, 0x73, 0xcf, 0x39, 0xcf, 0x07, 0xfc, 0xfc, 0xe7, 0x39, 0xcf, 0x39, 0xcf, 0x33, 0xce, 0x73, 0x8f, 0x07, 0xf3, 0xe7, 0x99, 0x9e, 0x7e, 0x7c, 0xf3, 0x3c, 0xff, 0x3c, 0xe6, 0x78, 0x31, 0xff, 0xf3, 0x9c, 0xe7, 0x33, 0x8c, 0x7f, 0xf9, 0xce, 0x73, 0xcf, 0x2f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0x4f, 0x67, 0xce, 0x73, 0xcf, 0x39, 0xce, 0x3f, 0xfc, 0xf4, 0xe7, 0x39, 0xcf, 0x39, 0xce, 0x73, 0xce, 0x73, 0x8d, 0xf7, 0xf3, 0xe7, 0x93, 0x9e, 0x7e, 0x6c, 0xe7, 0x3c, 0xff, 0x3c, 0xce, 0x71, 0xf9, 0xff, 0xf3, 0x9c, 0xe7, 0x33, 0x8e, 0x7f, 0xf9, 0xce, 0x73, 0xcf, 0x0f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x66, 0xe7, 0xe4, 0xf3, 0xcf, 0x39, 0xce, 0xff, 0xfe, 0x6e, 0x4f, 0x39, 0xcf, 0x39, 0xce, 0x73, 0xce, 0x79, 0x8c, 0xf7, 0xf9, 0xe3, 0x33, 0x9e, 0x7e, 0x4c, 0xe7, 0x3c, 0xff, 0x19, 0xce, 0x77, 0xf8, 0xef, 0xf3, 0x9c, 0xf2, 0x79, 0x8e, 0x3b, 0xfc, 0x9e, 0x73, 0xcf, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xe1, 0x83, 0xf1, 0xc1, 0x04, 0x00, 0x82, 0x01, 0xfe, 0x1f, 0x1c, 0x10, 0x80, 0x10, 0x83, 0x08, 0x04, 0x1c, 0x44, 0x0f, 0xf9, 0xe0, 0x78, 0x40, 0x3e, 0x10, 0x70, 0x80, 0x7f, 0x03, 0xe1, 0x10, 0x0c, 0x1f, 0xc1, 0x08, 0x38, 0xfc, 0x47, 0x07, 0xfe, 0x38, 0x20, 0x07, 0x9f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xe7, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xbf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x71, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xe3, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xef, 0xff, 0xf9, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x1f, 0xee, 0x0f, 0xf9, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x1f, 0xc9, 0xc7, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xd9, 0xe7, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xfe, 0x3b, 0xc1, 0xff, 0x9f, 0xd8, 0xe7, 0xfb, 0xc7, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf3, 0xff, 0xe1, 0x8c, 0x7f, 0xf1, 0xe0, 0x00, 0x78, 0x1f, 0x07, 0x0f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf0, 0xc6, 0x02, 0x10, 0xc0, 0xc6, 0x38, 0x1f, 0xe0, 0x70, 0x1f, 0x0c, 0x31, 0xe7, 0xff, 0x9f, 0x9c, 0x0f, 0xe1, 0x80, 0x3e, 0x0c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf3, 0xff, 0xc9, 0xe2, 0x7f, 0x87, 0xde, 0x63, 0x33, 0x9e, 0x44, 0xe7, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe4, 0xf1, 0x33, 0x3b, 0x9c, 0xf1, 0x37, 0x1f, 0xce, 0x71, 0x8e, 0x4f, 0x39, 0xe7, 0xff, 0x9f, 0xbe, 0x0f, 0xf9, 0xe3, 0x3c, 0x8c, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf3, 0xff, 0x9c, 0xe7, 0xfe, 0x1f, 0xc6, 0x67, 0x93, 0x9c, 0xec, 0xe7, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf3, 0x1b, 0x9c, 0xf3, 0xe7, 0x1f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x3c, 0x07, 0xf9, 0xe7, 0x39, 0xdc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x80, 0x3f, 0x9c, 0xe7, 0xfe, 0x7f, 0xe0, 0xe7, 0x9c, 0x1c, 0xfc, 0x03, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf3, 0x1b, 0xe0, 0xf3, 0xe7, 0x1f, 0xf0, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x79, 0xe3, 0xf9, 0xe7, 0x39, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf3, 0xff, 0x9c, 0xe7, 0xff, 0x1f, 0xf0, 0x67, 0x99, 0x9c, 0xf8, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf8, 0xc7, 0xcc, 0xf3, 0xe7, 0x1f, 0xe6, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x73, 0xf3, 0xf9, 0xe7, 0x39, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf3, 0xff, 0x9c, 0xe7, 0xff, 0xc7, 0xdf, 0x67, 0x93, 0x9c, 0xf4, 0xff, 0x87, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf8, 0xc7, 0x9c, 0xf3, 0xe7, 0x1f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe6, 0xff, 0x9e, 0x73, 0xf3, 0xf9, 0xe7, 0x39, 0xec, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf3, 0xff, 0xc9, 0xe7, 0xff, 0xf0, 0xcf, 0x63, 0x33, 0x9e, 0x6c, 0x76, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe4, 0xf3, 0xfc, 0xcf, 0x9c, 0xf3, 0xf3, 0x1f, 0xce, 0x71, 0x9e, 0x4f, 0x31, 0xe4, 0xff, 0x9e, 0xf9, 0xe7, 0xf9, 0xe7, 0x3c, 0xdc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf3, 0xff, 0xe3, 0x83, 0xff, 0xfc, 0xc0, 0xe0, 0x78, 0x46, 0x1e, 0x0e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf1, 0xc1, 0xfd, 0xef, 0xc2, 0x01, 0xf8, 0x8f, 0xe1, 0x14, 0x3f, 0x1f, 0x88, 0x61, 0xfe, 0x02, 0xfc, 0x0f, 0xe0, 0x82, 0x0c, 0x30, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xef, 0xff, 0xf9, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x1f, 0xee, 0x0f, 0xf9, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x1f, 0xc9, 0xc7, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xd9, 0xe7, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xfe, 0x3b, 0xc1, 0xff, 0x9f, 0xd8, 0xe7, 0xfb, 0x8f, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x18, 0xff, 0xe3, 0x80, 0xf0, 0x3e, 0x0c, 0x87, 0x02, 0x01, 0xe0, 0x7c, 0x1c, 0x3c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1e, 0x07, 0xc1, 0x90, 0xc2, 0x10, 0x81, 0x8c, 0x70, 0x3f, 0xe0, 0x70, 0x1f, 0x0c, 0x31, 0xe7, 0xff, 0x9f, 0x9c, 0x0f, 0xe1, 0x00, 0x7c, 0x18, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x93, 0xc4, 0xff, 0x0f, 0x8c, 0x67, 0x3c, 0x8c, 0xde, 0xf3, 0x8c, 0xce, 0x79, 0x13, 0x9f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8c, 0xe7, 0x91, 0x9b, 0xf3, 0x3b, 0x39, 0xe2, 0x6e, 0x3f, 0xce, 0x71, 0x8e, 0x4f, 0x39, 0xe7, 0xff, 0x9f, 0xbe, 0x0f, 0xf9, 0xc6, 0x79, 0x18, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xcf, 0xfc, 0x3f, 0x9e, 0x67, 0x39, 0xdc, 0xbe, 0x33, 0x9e, 0x4e, 0x73, 0xb3, 0x9f, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xe7, 0x3b, 0x97, 0xf3, 0x1b, 0x39, 0xe7, 0xce, 0x3f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x3c, 0x07, 0xf9, 0xce, 0x73, 0xb9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x00, 0x00, 0x3f, 0x39, 0xcf, 0xfc, 0xff, 0x9e, 0x78, 0x39, 0xfc, 0x1f, 0x07, 0x9e, 0x70, 0x73, 0xf0, 0x0f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0x07, 0x3f, 0x83, 0xf3, 0x1b, 0xc1, 0xe7, 0xce, 0x3f, 0xf0, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x79, 0xe3, 0xf9, 0xce, 0x73, 0xf9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xcf, 0xfe, 0x3f, 0x9e, 0x73, 0x39, 0xfc, 0x9f, 0x83, 0x9e, 0x66, 0x73, 0xe3, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x67, 0x3f, 0x93, 0xf8, 0xc7, 0x99, 0xe7, 0xce, 0x3f, 0xe6, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0x73, 0xf3, 0xf9, 0xce, 0x73, 0xf9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xcf, 0xff, 0x8f, 0x9e, 0x67, 0x39, 0xec, 0xce, 0xfb, 0x9e, 0x4e, 0x73, 0xd3, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xe7, 0x3d, 0x99, 0xf8, 0xc7, 0x39, 0xe7, 0xce, 0x3f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe6, 0xff, 0x9e, 0x73, 0xf3, 0xf9, 0xce, 0x73, 0xd9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x93, 0xcf, 0xff, 0xe1, 0x8c, 0xe7, 0x3c, 0xdc, 0xe6, 0x7b, 0x8c, 0xce, 0x79, 0xb1, 0xd8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x9c, 0xe7, 0x9b, 0x9c, 0xfc, 0xcf, 0x39, 0xe7, 0xe6, 0x3f, 0xce, 0x71, 0x9e, 0x4f, 0x31, 0xe4, 0xff, 0x9e, 0xf9, 0xe7, 0xf9, 0xce, 0x79, 0xb9, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x07, 0xff, 0xf9, 0xa1, 0xf0, 0x8c, 0x30, 0x42, 0x07, 0x81, 0xe1, 0x18, 0x78, 0x39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3e, 0x11, 0x86, 0x08, 0x7d, 0xef, 0x84, 0x03, 0xf1, 0x1f, 0xe1, 0x14, 0x3f, 0x1f, 0x88, 0x61, 0xfe, 0x02, 0xfc, 0x0f, 0xe0, 0x04, 0x18, 0x60, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcc, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf8, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x1f, 0xfc, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcd, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfc, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xff, 0x9c, 0xef, 0xc7, 0xf8, 0x3f, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xf3, 0xff, 0xfe, 0x3b, 0xc1, 0xff, 0x9f, 0xfd, 0xe3, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xfc, 0x31, 0x8f, 0xfe, 0x3c, 0xc7, 0x80, 0x3c, 0xfc, 0x31, 0x8c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf0, 0xc6, 0x02, 0x10, 0xc0, 0xc6, 0x38, 0x1f, 0xe0, 0x70, 0x1f, 0x0c, 0x31, 0xe7, 0xff, 0x9f, 0xf0, 0xc0, 0x1f, 0x06, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xf9, 0x3c, 0x4f, 0xf0, 0xfc, 0x07, 0xe3, 0x3c, 0xf3, 0x9c, 0x4f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe4, 0xf1, 0x33, 0x3b, 0x9c, 0xf1, 0x37, 0x1f, 0xce, 0x71, 0x8e, 0x4f, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xf1, 0x9e, 0x46, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xf3, 0x9c, 0xff, 0xc3, 0xfc, 0xe7, 0xe7, 0x3c, 0xf3, 0x9c, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf3, 0x1b, 0x9c, 0xf3, 0xe7, 0x1f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xf3, 0x9c, 0xee, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xf3, 0x9c, 0xff, 0xcf, 0xfc, 0xe6, 0xe7, 0x3c, 0xf0, 0x0c, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf3, 0x1b, 0xe0, 0xf3, 0xe7, 0x1f, 0xf0, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xf3, 0x9c, 0xfe, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xf3, 0x9c, 0xff, 0xe3, 0xfc, 0xfe, 0xe7, 0x3c, 0xe3, 0xfc, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf8, 0xc7, 0xcc, 0xf3, 0xe7, 0x1f, 0xe6, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xf3, 0x9c, 0xfe, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xf3, 0x9c, 0xff, 0xf8, 0xfc, 0xfc, 0xe7, 0x3c, 0xd3, 0xfc, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0xf8, 0xc7, 0x9c, 0xf3, 0xe7, 0x1f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe6, 0xff, 0x9f, 0xfc, 0xf3, 0x9c, 0xf6, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xf9, 0x3c, 0xff, 0xfe, 0x1c, 0xf8, 0xe7, 0x3c, 0x91, 0xdc, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xe4, 0xf3, 0xfc, 0xcf, 0x9c, 0xf3, 0xf3, 0x1f, 0xce, 0x71, 0x9e, 0x4f, 0x31, 0xe4, 0xff, 0x9f, 0xfc, 0xf3, 0x9e, 0x6e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x07, 0xfc, 0x70, 0x7f, 0xff, 0x90, 0x00, 0x82, 0x0c, 0x38, 0x30, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xf1, 0xc1, 0xfd, 0xef, 0xc2, 0x01, 0xf8, 0x8f, 0xe1, 0x14, 0x3f, 0x1f, 0x88, 0x61, 0xfe, 0x03, 0xf0, 0x41, 0x06, 0x18, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xfc, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xf7, 0xfe, 0x1f, 0xfc, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xe7, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf3, 0xff, 0xfe, 0x3b, 0xc1, 0xff, 0x9f, 0xfd, 0xc7, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1e, 0x07, 0xc1, 0x90, 0xc2, 0x10, 0x81, 0x8c, 0x70, 0x3f, 0xe0, 0x70, 0x1f, 0x0c, 0x31, 0xe7, 0xff, 0x9f, 0xf0, 0x80, 0x3e, 0x0c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x8c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8c, 0xe7, 0x91, 0x9b, 0xf3, 0x3b, 0x39, 0xe2, 0x6e, 0x3f, 0xce, 0x71, 0x8e, 0x4f, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xe3, 0x3c, 0x8c, 0x67, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xe7, 0x3b, 0x97, 0xf3, 0x1b, 0x39, 0xe7, 0xce, 0x3f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xe7, 0x39, 0xdc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcf, 0x07, 0x3f, 0x83, 0xf3, 0x1b, 0xc1, 0xe7, 0xce, 0x3f, 0xf0, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xe7, 0x39, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x67, 0x3f, 0x93, 0xf8, 0xc7, 0x99, 0xe7, 0xce, 0x3f, 0xe6, 0x73, 0xcc, 0xe7, 0x39, 0xe7, 0xff, 0x9f, 0xfc, 0xe7, 0x39, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9e, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xcc, 0xe7, 0x3d, 0x99, 0xf8, 0xc7, 0x39, 0xe7, 0xce, 0x3f, 0xce, 0x73, 0xcc, 0xe7, 0x39, 0xe6, 0xff, 0x9f, 0xfc, 0xe7, 0x39, 0xec, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x9c, 0xe7, 0x9b, 0x9c, 0xfc, 0xcf, 0x39, 0xe7, 0xe6, 0x3f, 0xce, 0x71, 0x9e, 0x4f, 0x31, 0xe4, 0xff, 0x9f, 0xfc, 0xe7, 0x3c, 0xdc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xa1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x3e, 0x11, 0x86, 0x08, 0x7d, 0xef, 0x84, 0x03, 0xf1, 0x1f, 0xe1, 0x14, 0x3f, 0x1f, 0x88, 0x61, 0xfe, 0x03, 0xf0, 0x02, 0x0c, 0x30, 0x41, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf1, 0x9e, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xf3, 0xbe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xe3, 0xbc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x77, 0xde, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xe0, 0x7f, 0xc3, 0x18, 0xff, 0xcf, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x08, 0x63, 0x0f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcc, 0x7f, 0x93, 0xc4, 0xff, 0x8f, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x8e, 0x73, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9e, 0x7f, 0x39, 0xcf, 0xff, 0x1f, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x73, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9e, 0x7f, 0x39, 0xcf, 0xff, 0x3d, 0xe7, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x73, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9e, 0x7f, 0x39, 0xcf, 0xfe, 0x3c, 0xc7, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x73, 0xcf, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x9e, 0x7f, 0x39, 0xcf, 0xfe, 0x7c, 0xcf, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xce, 0x73, 0xcf, 0x37, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcc, 0x7f, 0x93, 0xcf, 0xfc, 0xf9, 0x9f, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x8e, 0x63, 0xcf, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc2, 0x7f, 0xc7, 0x07, 0xf8, 0x01, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x4f, 0x10, 0x07, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe1, 0xff, 0xfe, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfc, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xfe, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xff, 0xff, 0x9c, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc0, 0x7f, 0xe1, 0x8c, 0x7f, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0f, 0x87, 0x98, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xc6, 0x7f, 0xc9, 0xe2, 0x7f, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xce, 0x73, 0x9e, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0x9c, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x73, 0x9e, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0x9c, 0xe7, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x01, 0x9e, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0x9c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xcc, 0x7f, 0x9e, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0x9c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x7f, 0x9e, 0x79, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xce, 0x7f, 0xc9, 0xe7, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xce, 0x3b, 0x9e, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0x04, 0x1f, 0xe3, 0x83, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x83, 0x06, 0x0e, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + diff --git a/mup/mupdisp/init.c b/mup/mupdisp/init.c new file mode 100644 index 0000000..0c34321 --- /dev/null +++ b/mup/mupdisp/init.c @@ -0,0 +1,195 @@ + +/* Copyright (c) 1995, 1997, 1998, 1999, 2000, 2002 by Arkkra Enterprises */ +/* All rights reserved */ + +/* initialization table and routine for Mup/Ghostscript display program */ + +/* when adding support for additional terminal types, you will need to + * add the declarations of relevant functions and add an entry to the + * Config table */ + + +#include +#include +#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 + + + +/* 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 +}; + + +/* initialize. Make sure TERM is supported, and set up for it. */ + +void +init() + +{ + struct CONFIG *c_p; /* terminal configuration info */ + char *termname; /* $TERM */ + int numtypes; +#ifdef XWINDOW + struct CONFIG *xwindow_conf_p = 0; /* info for running under X */ +#endif + + +#ifdef __WATCOMC__ + termname = "DOS"; +#else + if ((termname = getenv("TERM")) == NULL) { + fprintf(stderr, "can't determine $TERM\n"); + generalcleanup(1); + } +#endif + + /* find appropriate functions to use based on terminal type */ + numtypes = sizeof(Config) / sizeof(struct CONFIG); + for (c_p = Config; numtypes > 0; c_p++, numtypes--) { + if (strcmp(c_p->termname, termname) == 0) { + Conf_info_p = c_p; + break; + } +#ifdef XWINDOW + /* save the xwindow config. If we don't find a + * matching terminal type here, we're try some other + * tricks later to guess if we're running under X */ + if (strcmp(c_p->termname, "xterm") == 0) { + xwindow_conf_p = c_p; + } +#endif + } + +#ifdef XWINDOW + if (Conf_info_p == (struct CONFIG *) 0) { + /* There can be several variations on xterm, so + * if $TERM at least starts with xterm, consider that + * good enough to try. And to try even harder to + * recognize if we're probably running under X, and + * thus the 'xterm' type will probably work, check if + * $DISPLAY is set. Chances are, if it is, we're probably + * in X. If it turns out we're not, we'll fail eventually, + * but we will have at least tried pretty hard + * to find something that would work... */ + if (strncmp(termname, "xterm", 5) == 0 || + getenv("DISPLAY") != (char *) 0) { + Conf_info_p = xwindow_conf_p; + } + } +#endif + + /* Make sure we managed to find a $TERM we can work with */ + if (Conf_info_p == (struct CONFIG *) 0 ) { + fprintf(stderr, "$TERM type not supported\n"); + generalcleanup(1); + } + +#ifdef XWINDOW + /* X has some extra options, so handle them */ + if (strcmp(Conf_info_p->termname, "xterm") == 0) { + parse_X_options(); + } +#endif +} diff --git a/mup/mupdisp/linvga.c b/mup/mupdisp/linvga.c new file mode 100644 index 0000000..20ac83a --- /dev/null +++ b/mup/mupdisp/linvga.c @@ -0,0 +1,357 @@ + +/* Copyright (c) 1997, 1998, 1999, 2000, 2002 by Arkkra Enterprises */ +/* All rights reserved */ + +/* Functions to support displaying multipage bitmap + * (as from Ghostscript -sDEVICE=bit) using Linux svgalib. + * This was derived from the AT386 version, so maybe some things + * would have been done a bit differently if it were written from + * scratch for Linux, but this seems to work fine and to be + * plenty fast enough (at least on a Pentium or better ;-) + * + * Note that using mupdisp in non-X-window mode on Linux requires that it + * can write to the console device. To allow this, make mupdisp setuid to root: + * chown root mupdisp + * chmod 4755 mupdisp + */ + +#if defined(linux) && ! defined(NO_VGA_LIB) + + +#include "mupdisp.h" + +#include +#include +#include +#include +#include + +#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)); + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); +} + + +/* 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); + } +} + + +/* 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); + } +} + + +#else + +/* some compilers complain about files that are effectively empty, + * so put in something even when entire file is effectively ifdef-ed out */ +static short dummy; + +#endif diff --git a/mup/mupdisp/mupdisp.c b/mup/mupdisp/mupdisp.c new file mode 100644 index 0000000..8f68d3b --- /dev/null +++ b/mup/mupdisp/mupdisp.c @@ -0,0 +1,464 @@ + +/* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + + +/* Program to display ghostscript bitmap output on screen. + * Works either on an AT386 or linux console + * or under X-windows from an xterm window or under DOS (with Watcom C). + * It could be extended to other + * TERM types by writing appropriate functions and adding to the Config + * array. Use the existing functions as models. + * Passes all arguments on to Mup. + */ + +/* for compiling under UNIX on x86, try + * cc -DSYSV -D_USHORT_H -s -O -o mupdisp *.c -lX11 -lnsl_i + * If you compile without XWINDOW, you can get by with just: + * cc -s -O -o mupdisp *.c + * + * For Watcom C under DOS, + * Put the following 4 lines in a batch script and execute it + * + * for %%f in (*.c) do wcc386 %%f -dDEBUG -on -4r + * echo NAME mup > mup.lnk + * for %%f in (*.obj) do echo FIL %%f >> mup.lnk + * wlink sys dos4g op st=32k @mup.lnk + * + * Note that all the mupdisp *.c and *.h files should be in the + * current directory, but there must be no other *.c files there, and no *.obj + * files (except that *.obj files from a previous attempt would be okay). + * + * For Linux, + * cc -L/usr/X11/lib -o mupdisp *.c -lvga -lX11 -lm + * Depending on the versions of libraries you have, + * you might not really need the -lm, but it doesn't hurt. + * If you don't have libvga on your system, and only intend to use the X11 + * mode, not the console mode, you can use + * cc -L/usr/X11/lib -o mupdisp -DNO_VGA_LIB *.c -lX11 + * + * Other environments may require different options + * + * Note that using mupdisp in non-X-window mode on Linux requires that it + * can write to the console device. To allow this, make mupdisp setuid to root: + * chown root mupdisp + * chmod 4755 mupdisp + */ + + +#include "mupdisp.h" +#ifdef __WATCOMC__ +#include +#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)); + + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* + * 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); + } +} + + +/* at the end of a PostScript page, save info about it */ + +static void +save_endpage() + +{ + struct Pginfo *new_p; /* newly allocated struct for info about page */ + static int seqnum = 0; /* sequential count of pages */ + + + /* allocate space to save info about page */ + if ((new_p = (struct Pginfo *) malloc (sizeof(struct Pginfo))) + == (struct Pginfo *) 0) { + fprintf(stderr, "malloc failed\n"); + generalcleanup(1); + } + + /* fill in info */ + new_p->pagenum = Pagenum; + new_p->seqnum = seqnum++; + new_p->begin = Begin_offset; + new_p->end = ftell(PS_file); + new_p->prev = Pagetail; + new_p->next = (struct Pginfo *) 0; + + /* link onto list */ + if (Pagehead == (struct Pginfo *) 0) { + Pagehead = new_p; + } + if (Pagetail != (struct Pginfo *) 0) { + Pagetail->next = new_p; + } + Pagetail = new_p; +} diff --git a/mup/mupdisp/mupdisp.h b/mup/mupdisp/mupdisp.h new file mode 100644 index 0000000..892d323 --- /dev/null +++ b/mup/mupdisp/mupdisp.h @@ -0,0 +1,155 @@ + +/* Copyright (c) 1995, 1996, 1998, 2000, 2001, 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* include file for Mup/Ghostscript display program */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#if !defined(linux) && !defined(__EMX__) +/* undef SIGCHLD to avoid conflict with Xos.h */ +#undef SIGCHLD +#endif +#include + +#ifdef __WATCOMC__ +#ifndef __DOS__ +#define __DOS__ 1 +#endif +#endif + +#if defined(__DOS__) || defined (__EMX__) +#include +#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 +#include +#include +/* define XK_MISCELLANY so we can use XK_Return, etc */ +#define XK_MISCELLANY 1 +#include +#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 +#else +extern long lseek(); +#endif diff --git a/mup/mupdisp/waitmsg.bm b/mup/mupdisp/waitmsg.bm new file mode 100644 index 0000000..54666ea --- /dev/null +++ b/mup/mupdisp/waitmsg.bm @@ -0,0 +1,56 @@ +/* Copyright (c) 1995 by Arkkra Enterprises */ +/* All rights reserved */ + +int Waitmsg_width = 29; +int Waitmsg_height = 48; +unsigned char Waitmsg_bitmap[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xf0, 0x1f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x33, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xc7, 0x9f, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x33, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xcf, 0xdf, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0x8f, 0xdf, 0xff, 0xff, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0x9f, 0xf9, 0x30, 0xf0, 0xc3, 0x38, 0x1e, 0x03, 0xe0, 0x38, 0x78, 0x0c, 0x38, 0x3f, 0x0e, 0x0f, 0xf0, 0x33, 0x83, 0x01, 0xce, 0x1c, 0x67, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0x9f, 0xf9, 0xae, 0x66, 0x67, 0x38, 0xcc, 0xc7, 0xe3, 0x13, 0x33, 0x1b, 0x93, 0x9f, 0x9c, 0xe7, 0xe6, 0x33, 0x39, 0x18, 0xcc, 0xcc, 0xf7, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0x9f, 0xf9, 0xe0, 0x6e, 0x67, 0x39, 0xcc, 0xe7, 0xe7, 0x97, 0x33, 0x98, 0x11, 0xff, 0x99, 0xe3, 0xcf, 0x33, 0x1f, 0x3c, 0xcd, 0xce, 0x6f, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0x9f, 0xf9, 0xcf, 0xf8, 0x67, 0x39, 0xcc, 0xe7, 0xe7, 0x9c, 0x33, 0x93, 0xf8, 0x7f, 0x99, 0xf3, 0xcf, 0x33, 0x87, 0x3c, 0xcf, 0x0e, 0x6f, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0x9f, 0xf9, 0xcf, 0xf6, 0x67, 0x39, 0xce, 0x4f, 0xe7, 0x9b, 0x39, 0x33, 0xfe, 0x3f, 0x99, 0xf3, 0xcf, 0x33, 0xe3, 0x3c, 0xce, 0xcf, 0x1f, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0x8f, 0xf9, 0xcf, 0xa6, 0x67, 0x39, 0xce, 0x1f, 0xe7, 0x93, 0x38, 0x73, 0xe7, 0x1f, 0x98, 0xf3, 0xc7, 0x33, 0x71, 0x3c, 0xcc, 0xcf, 0x1f, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xc7, 0x99, 0xe7, 0x44, 0x67, 0x39, 0xcc, 0xff, 0xe7, 0x22, 0x33, 0xf9, 0xd3, 0x9f, 0x9c, 0xe7, 0xe7, 0x33, 0x39, 0x39, 0xc8, 0x8f, 0x9e, 0xf7, 0x7b, 0xff, 0x00, +0x00, 0xff, 0xe0, 0x30, 0x70, 0xe0, 0x21, 0x18, 0x8c, 0x07, 0xe0, 0x70, 0x10, 0x1c, 0x30, 0x3f, 0x86, 0x0f, 0xf0, 0x31, 0x03, 0x03, 0x8c, 0x07, 0xbc, 0xe6, 0x73, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x83, 0xe7, 0xff, 0xf6, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xfb, 0xe7, 0xff, 0xe7, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xe7, 0xe7, 0xff, 0xe3, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0f, 0xc7, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + diff --git a/mup/mupdisp/xterm.c b/mup/mupdisp/xterm.c new file mode 100644 index 0000000..95f5698 --- /dev/null +++ b/mup/mupdisp/xterm.c @@ -0,0 +1,644 @@ + +/* Copyright (c) 1995, 1996, 1998, 1999, 2000, 2001, 2004, 2005 by Arkkra Enterprises */ +/* All rights reserved */ + +/* functions for displaying Mup/Ghostscript output under X windows. */ + +#include "mupdisp.h" + +#ifdef XWINDOW + +#include +#include + +/* 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)); + + +/* 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); +} + + +/* 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); +} + + +/* 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; +} + + +/* 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); +} + + +/* 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); +} + + +/* 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; + } + } +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + +/* 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); +} + + + +/* Error handler. For now just beep. Maybe eventually pop up an error message */ + +void +xterm_error(msg) + +char *msg; + +{ + putc('\7', stderr); +} + + +/* draw a raster bitmap, centered on the window */ + +void +xterm_raster(bitmap, width, height) + +unsigned char *bitmap; /* what to display */ +int width, height; /* of bitmap, width is in bytes */ + +{ + register int b; + int x, y; /* upper left corner of where to put bitmap, x in bytes */ + XImage *bm_image; + char *bmap; + + + /* figure out how to center on screen */ + x = (BYTES_PER_LINE - width) / 2; + y = (Conf_info_p->vlines - height) / 2; + + /* get space to image, copy, inverting to white on black. Display, + * then release the storage */ + if ((bmap = (char *) malloc(width*height)) == (char *) 0) { + Exit_errmsg = "Could not allocate memory\n"; + ( *(Conf_info_p->cleanup) ) (1); + } + for (b = width * height - 1; b >= 0; b--) { + bmap[b] = bitmap[b] ^ 0xff; + } + bm_image = XCreateImage(Display_p, DefaultVisual(Display_p, Xscreen), + 1, XYBitmap, 0, bmap, width * 8, height, + 8, width); + bm_image->bitmap_unit = 8; + bm_image->bitmap_bit_order = MSBFirst; + XPutImage(Display_p, Win, gc, bm_image, 0, 0, x * 8, y, width * 8, height); + XDestroyImage(bm_image); + XFlush(Display_p); +} + +#else + +/* some compilers complain about files that are effectively empty, + * so put in something even when entire file is effectively ifdef-ed out */ +static short dummy; + +#endif + diff --git a/mup/mupmate/Config.C b/mup/mupmate/Config.C new file mode 100644 index 0000000..446238a --- /dev/null +++ b/mup/mupmate/Config.C @@ -0,0 +1,1089 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +// Code for the Config menu item on the main toolbar + +#include "globals.H" +#include "Preferences.H" +#include "Config.H" +#include "Main.H" +#include "utils.H" +#include +#include +#include +#include +#include +#include + + +// Window to ask user where files and tools are located + +FileLocations_dialog::FileLocations_dialog(void) + : Fl_Double_Window(620, 300, "Mupmate File Locations") +{ + mup_documentation_p = new Fl_Input(200, 30, 400, 30, "Mup Documentation Folder"); + mup_documentation_p->tooltip("Set where Mup documentation\n" + "files are installed on your system.\n" + "This folder must contain the \"uguide\"\n" + "folder that contains the HTML version\n" + "of the Mup User's Guide."); + + mup_program_p = new Fl_Input(200, 65, 400, 30, "Mup Command Path"); + mup_program_p->tooltip("Set where the Mup program\n" + "is installed on your system."); + + music_files_p = new Fl_Input(200, 100, 400, 30, "Folder for Mup Files"); + music_files_p->tooltip("Set the default folder for storing\n" + "your Mup files (.mup input files,\n" + "and .ps and .mid output files)."); + + muppath_p = new Fl_Input(200, 135, 400, 30, "Folder for Mup include Files"); + static char include_tip_text[200]; + (void) sprintf(include_tip_text, + "Set the default folder (or list of folders,\n" + "separated by %c characters) for\n" + "storing your Mup \"include\" files.", + path_separator()); + muppath_p->tooltip(include_tip_text); + + viewer_p = new Fl_Input(200, 170, 400, 30, "PostScript Viewer Path"); + viewer_p->tooltip("Set which PostScript viewing program\n" + "to use for displaying Mup output.\n" +#ifdef OS_LIKE_WIN32 + "This is typically GSview32.exe\n" + "which you can obtain from\n" + "http://www.cs.wisc.edu/~ghost/gsview/" +#else + "The \"gv\" program is a common choice." +#endif + ); + + player_p = new Fl_Input(200, 205, 400, 30, "MIDI Player Path"); + player_p->tooltip("Set which MIDI player program\n" + "to use for playing Mup MIDI output.\n" +#ifdef OS_LIKE_WIN32 + "This is typically wmplayer.exe" +#else + "Common choices include xplaymidi or timidity." +#endif + ); + + apply_p = new Fl_Return_Button(50, 255, 100, 30, "Apply"); + apply_p->when(FL_WHEN_RELEASE); + apply_p->callback(Apply_cb, this); + + cancel_p = new Fl_Button(w() - 150, 255, 100, 30, "Cancel"); + cancel_p->shortcut(FL_Escape); + cancel_p->when(FL_WHEN_RELEASE); + cancel_p->callback(Cancel_cb, this); + + // Populate the fields + set_current_values(); + + // Arrange for destructor to clean up new-ed widgets + end(); + + // Arrange for window manager closes to do Cancel. + callback(Cancel_cb, this); + when(FL_WHEN_NEVER); +} + + +FileLocations_dialog::~FileLocations_dialog() +{ +} + + +//--- Callback for when user clicks "Apply" on FileLocations dialog. +// Save values in preferences file. + +CALL_BACK(FileLocations_dialog, Apply) +{ + bool changes = false; // if any changes made + bool error = false; // if any errors found + char location[FL_PATH_MAX]; + + // Documentation location + if (mup_documentation_p->size() > 0) { + (void) Preferences_p->set(Mup_documentation_location, + mup_documentation_p->value()); + changes = true; + // Documentation being wrong means User's Guide can't be + // shown, which is bad, although not fatal. + if ( ! fl_filename_isdir(mup_documentation_p->value()) ) { + fl_alert("Location for Mup documentation is not a valid folder."); + error = true; + } + else { + if (access(users_guide_index_file( + mup_documentation_p->value()), F_OK) + != 0) { + fl_alert("Folder specified for Mup documentation it not correct:\n" + "it does not contain the Mup User's Guide."); + error = true; + } + } + } + + // Location of Mup program + if (mup_program_p->size() > 0) { + if (find_executable(mup_program_p->value(), location)) { + (void) Preferences_p->set(Mup_program_location, + mup_program_p->value()); + changes = true; + } + else { + fl_alert("Location specified for Mup program is not valid."); + error = true; + } + } + + // Default folder for Mup input files + if (music_files_p->size() > 0) { + if (chdir(music_files_p->value()) != 0) { + fl_alert("Value for \"Folder for Mup Files\" is not a valid folder."); + error = true; + } + else { + (void) Preferences_p->set(Music_files_location, + music_files_p->value()); + changes = true; + } + } + + // $MUPPATH value + if (muppath_p->size() > 0) { + (void) Preferences_p->set(MUPPATH_location, muppath_p->value()); + // Set $MUPPATH + set_muppath(muppath_p->value()); + changes = true; + // Setting MUPPATH correctly is only important if user + // actually uses it, which many people won't, but if it is set + // to something invalid, we give a warning. + // Since MUPPATH can be a list, we check each component + // in the list. + char pathcopy[muppath_p->size() + 1]; + (void) strcpy(pathcopy, muppath_p->value()); + char * component_p = pathcopy; + char * sep_p; // where path separator appears in list + do { + if ((sep_p = strchr(component_p, path_separator())) != 0) { + *sep_p = '\0'; + } + if (strlen(component_p) > 0 && + ! fl_filename_isdir(component_p)) { + fl_alert("Location for Mup include files\n" + "\"%s\"\nis not a valid folder.", + component_p); + error = true; + } + component_p += strlen(component_p) + 1; + } while (sep_p != 0); + } + + // PostScript viewer program + if (viewer_p->size() > 0) { + if (find_executable(viewer_p->value(), location)) { + (void) Preferences_p->set(Viewer_location, viewer_p->value()); + changes = true; + } + else { + fl_alert("Location specified for PostScript viewer is not valid."); + error = true; + } + } + + // MIDI player + if (player_p->size() > 0) { + if (find_executable(player_p->value(), location)) { + (void) Preferences_p->set(MIDI_player_location, player_p->value()); + changes = true; + } + else { + fl_alert("Location specified for MIDI player is not valid."); + error = true; + } + } + + // If any changes, persist the data. + if (changes) { + Preferences_p->flush(); + } + + // If there were errors, leave form up so user can try to correct them. + if ( ! error ) { + hide(); + } +} + + +//--- callback for when user clicks "Cancel" on FileLocations dialog + +CALL_BACK(FileLocations_dialog, Cancel) +{ + hide(); + // Put all the original settings back on the form + set_current_values(); +} + + +// Populate form with the current default values from user's preferences. + +void +FileLocations_dialog::set_current_values(void) +{ + char * val; + (void) Preferences_p->get(Mup_documentation_location, val, + Default_Mup_documentation_location); + mup_documentation_p->value(val); + + (void) Preferences_p->get(Mup_program_location, val, + Default_Mup_program_location); + mup_program_p->value(val); + + (void) Preferences_p->get(Music_files_location, val, + Default_music_files_location); + music_files_p->value(val); + (void) Preferences_p->get(MUPPATH_location, val, + Default_MUPPATH_location); + muppath_p->value(val); + (void) Preferences_p->get(Viewer_location, val, + Default_viewer_location); + viewer_p->value(val); + (void) Preferences_p->get(MIDI_player_location, val, + Default_MIDI_player_location); + player_p->value(val); +} + + +//----------------------------------------------------------------- + +// List of standard FLTK fonts, and info to map name to menu entry. +static struct Font { + const char * name; + Fl_Font value; + int menu_offset; +} Fontlist[] = { + { "Courier", FL_COURIER }, + { "Courier Bold", FL_COURIER_BOLD }, + { "Courier Italic", FL_COURIER_ITALIC }, + { "Courier Bold Italic", FL_COURIER_BOLD_ITALIC }, + { "Helvetica", FL_HELVETICA }, + { "Helvetica Bold", FL_HELVETICA_BOLD }, + { "Helvetica Italic", FL_HELVETICA_ITALIC }, + { "Helvetica Bold Italic", FL_HELVETICA_BOLD_ITALIC }, + { "Times", FL_TIMES }, + { "Times Bold", FL_TIMES_BOLD }, + { "Times Italic", FL_TIMES_ITALIC }, + { "Times Bold Italic", FL_TIMES_BOLD_ITALIC }, +}; +static const int Fontlistlength = sizeof(Fontlist) / sizeof(Fontlist[0]); + +// Window to ask user preferences, like editor font, size, etc. + +Preferences_dialog::Preferences_dialog(void) + : Fl_Double_Window(400, 280, "Mupmate Preferences") +{ + // Make widget for user's editor font choice. + font_p = new Fl_Choice(20, 40, 210, 30, "Text Font"); + font_p->tooltip("Select the font to be used\n" + "in the editor window where you\n" + "type in Mup input. It is also used\n" + "for the Help and error report text."); + // Arrange to reset size menu if font selection changes + font_p->callback(fontchg_cb, this); + font_p->when(FL_WHEN_CHANGED); + font_p->align(FL_ALIGN_TOP_LEFT); + + // Make widget for user's editor size choice. + size_p = new Fl_Choice(270, 40, 100, 30, "Text Size"); + size_p->tooltip("Select the text size to be used\n" + "in the editor window where you\n" + "type in Mup input. It is also used\n" + "for the Help and error report text."); + size_p->align(FL_ALIGN_TOP_LEFT); + + auto_display_p = new Fl_Check_Button(20, 90, 180, 30, + "Auto-Display on Save"); + auto_display_p->tooltip("Set whether your music\n" + "is displayed automatically\n" + "whenever you save your Mup file."); + + auto_save_p = new Fl_Check_Button(w() - 170, 90, 150, 30, + "Auto-Save on Run"); + auto_save_p->tooltip("Set whether your music is saved\n" + "automatically whenever you do Display, Play,\n" + "Write PostScript or Write MIDI from the Run menu."); + + tooltips_delay_p = new Fl_Value_Input(150, 155, 100, 30, "Tool Tip Delay"); + tooltips_delay_p->minimum(0.0); + tooltips_delay_p->precision(3); + tooltips_delay_p->tooltip("Set how long to delay before showing\n" + "tool tips, in seconds.\n"); + tooltips_delay_p->align(FL_ALIGN_TOP_LEFT); + + // Create and configure widget for Apply button + apply_p = new Fl_Return_Button(60, 215, 100, 30, "Apply"); + apply_p->when(FL_WHEN_RELEASE); + apply_p->callback(Apply_cb, this); + + // Create and configure widget for Cancel button + cancel_p = new Fl_Button(w() - 160, 215, 100, 30, "Cancel"); + cancel_p->shortcut(FL_Escape); + cancel_p->when(FL_WHEN_RELEASE); + cancel_p->callback(Cancel_cb, this); + + // Populate the fields + set_current_values(); + + // Arrange for destructor to clean up new-ed widgets + end(); + + // Arrange for window manager closes to do Cancel. + callback(Cancel_cb, this); + when(FL_WHEN_NEVER); +} + +Preferences_dialog::~Preferences_dialog() +{ +} + + +//---- Callback for when user changes font selection. +// This re-creates the size menu to be what sizes are available +// for that font, since each font could have a different set of sizes. + +CALL_BACK(Preferences_dialog, fontchg) +{ + unsigned char size; + if (size_p->mvalue() != 0) { + size = atoi(size_p->mvalue()->text); + } + else { + // Shouldn't really be possible to get here, + // but better to be safe. + size = (unsigned char) atoi(Default_editor_size); + } + + set_size_list(Config::fontvalue(font_p->mvalue()->text), size); +} + + +//--- Callback for when user clicks Apply in Preferences +// Save the new values. + +CALL_BACK(Preferences_dialog, Apply) +{ + Fl_Font font; + int n; + + Preferences_p->set(Auto_display_preference, auto_display_p->value()); + Preferences_p->set(Auto_save_preference, auto_save_p->value()); + Preferences_p->set(Tooltips_delay_preference, tooltips_delay_p->value()); + Fl_Tooltip::delay(tooltips_delay_p->value()); + + // Convert font menu selection into font value. + for (n = 0; n < Fontlistlength; n++) { + if (Fontlist[n].menu_offset == font_p->value()) { + Preferences_p->set(Editor_font_preference, Fontlist[n].name); + font = Fontlist[n].value; + break; + } + } + if (n >= Fontlistlength) { + // Selection not valid. Fall back to using the default. + char * fontname; + (void) Preferences_p->get(Editor_font_preference, fontname, + Default_editor_font); + font = Config::fontvalue(fontname); + } + + // Save size value. + unsigned char size; + if (size_p->text() != 0) { + (void) Preferences_p->set(Editor_size_preference, size_p->text()); + size = (unsigned char) atoi(size_p->text()); + } + else { + size = (unsigned char) atoi(Default_editor_size); + } + + // Persist the data. + Preferences_p->flush(); + + // Actually change the font/size in all relevant windows. + // Windows that want to know about these changes register a callback, + // so we call them. + Font_change_registration::run_callbacks(font, size); + + hide(); +} + +//--- callback for when user clicks Cancel in Preferences + +CALL_BACK(Preferences_dialog, Cancel) +{ + hide(); + // Put all the original settings back on the form + set_current_values(); +} + + +// Populate form with current values from user's preferences + +void +Preferences_dialog::set_current_values(void) +{ + int auto_display; + (void) Preferences_p->get(Auto_display_preference, auto_display, + Default_auto_display); + auto_display_p->value(auto_display); + + int auto_save; + (void) Preferences_p->get(Auto_save_preference, auto_save, + Default_auto_save); + auto_save_p->value(auto_save); + + double tooltips_delay; + (void) Preferences_p->get(Tooltips_delay_preference, tooltips_delay, + Default_tooltips_delay); + tooltips_delay_p->value(tooltips_delay); + + char * fontname; + (void) Preferences_p->get(Editor_font_preference, fontname, + Default_editor_font); + Fl_Font font = Config::fontvalue(fontname); + // Populate font menu + font_p->clear(); + for (int i = 0; i < Fontlistlength; i++) { + Fontlist[i].menu_offset = + font_p->add(Fontlist[i].name, 0, 0, 0, 0); + // Set the current value + if (Fontlist[i].value == font) { + font_p->value(Fontlist[i].menu_offset); + } + } + + char * sizename; + (void) Preferences_p->get(Editor_size_preference, sizename, + Default_editor_size); + unsigned char size = (unsigned char) atoi(sizename); + // Populate the size menu + set_size_list(font, size); +} + + +// When font selection changes, re-create the size menu, +// because each font could have different sizes available. + +void +Preferences_dialog::set_size_list(Fl_Font font, uchar curr_size) +{ + // Avoid really tiny sizes, or more importantly, zero, like if an atoi + // failed, because otherwise FLTK may try to divide by zero. + // Also limit to a maximum size. + if (curr_size < Min_size || curr_size > Max_size) { + curr_size = (unsigned char) atoi(Default_editor_size); + } + + // Clean out the current menu if any + size_p->clear(); + + // Populate the menu + int * sizelist; + int numsizes = Fl::get_font_sizes(font, sizelist); + + // Set current value to ridiculous value, then find closest + int currvalue = 5000; + + int i; // index through sizelist + int menu_index; // index into menu + for (i = menu_index = 0; i < numsizes; i++) { + if (sizelist[i] == 0) { + // This means font is scaleable + continue; + } + if (sizelist[i] > Max_size) { + break; + } + char num_as_string[4]; + (void) sprintf(num_as_string, "%d", sizelist[i]); + size_p->add(num_as_string, 0, 0, 0, 0); + // If this is closest index to desired size, mark as current + if ( abs(sizelist[i] - currvalue) > abs(sizelist[i] - curr_size) ) { + currvalue = sizelist[i]; + size_p->value(menu_index); + } + menu_index++; + } + if (numsizes == 0 || (numsizes == 1 && sizelist[0] == 0)) { + // Either no available sizes at all, or only + // scaleable, with no special "good" sizes, + // so we pick some and hope for the best. + size_p->add("10", 0, 0, 0, 0); + if (curr_size <= 11) { + size_p->value(0); + } + size_p->add("12", 0, 0, 0, 0); + if (curr_size >= 12 && curr_size <= 13) { + size_p->value(1); + } + size_p->add("14", 0, 0, 0, 0); + if (curr_size >= 14 && curr_size <= 15) { + size_p->value(2); + } + size_p->add("16", 0, 0, 0, 0); + if (curr_size >= 16 && curr_size <= 17) { + size_p->value(3); + } + size_p->add("18", 0, 0, 0, 0); + if (curr_size >= 18) { + size_p->value(4); + } + } +} + +//----------dialog to let user fill in the Registration form--------------- + +#define MULTI_OS "Note that if you wish to use Mup\n" \ + "on multiple machines simultaneously,\n" \ + "you need to purchase a registration\n" \ + "for each." + + +RegistrationForm_dialog::RegistrationForm_dialog(void) + : Fl_Double_Window(500, 450, "Mup Registration") +{ + name_p = new Fl_Input(80, 20, 400, 30, "Name"); + name_p->tooltip("Enter your name."); + + address_p = new Fl_Input(80, 60, 400, 30, "Address"); + address_p->tooltip("Enter your street address."); + + city_p = new Fl_Input(80, 100, 180, 30, "City"); + city_p->tooltip("Enter the name of the city\n" + "in which you live."); + state_p = new Fl_Input(380, 100, 100, 30, "State/Province"); + state_p->tooltip("Enter the state or province (if any)\n" + "in which you live."); + + postal_code_p = new Fl_Input(110, 140, 120, 30, "Postal Code"); + postal_code_p->tooltip("Enter your zip code or postal code\n" + "as appropriate for your country."); + + country_p = new Fl_Input(320, 140, 160, 30, "Country"); + country_p->tooltip("Enter the name of the country in which\n" + "you live (optional if in USA)."); + + email_p = new Fl_Input(110, 180, 370, 30, "Email address"); + email_p->tooltip("Enter your email address. This will only be used\n" + "to send you your registration key\n" + "and announcements of future (free) Mup upgrades."); + + how_heard_p = new Fl_Input(20, 240, 460, 30, "Where did you hear about Mup?"); + how_heard_p->align(FL_ALIGN_TOP_LEFT); + how_heard_p->tooltip("Please let us know how you learned about Mup\n" + "(a particular web link, magazine, book, etc.)."); + + // Checkboxes for OS types. + // If we are compiled for a particular OS, + // automatically check that box. + Windows_p = new Fl_Check_Button(20, 280, 80, 30, "Windows"); +#ifdef __WIN32 + Windows_p->value(1); +#endif + Windows_p->tooltip("Check here if you plan to run Mup\n" + "under Microsoft Windows.\n" + MULTI_OS); + + Mac_p = new Fl_Check_Button(110, 280, 50, 30, "Mac"); + Mac_p->tooltip("Check here if you plan to run Mup\n" + "under Apple Mac OS.\n" + MULTI_OS); +#ifdef __APPLE__ + Mac_p->value(1); +#endif + + Linux_p = new Fl_Check_Button(170, 280, 60, 30, "Linux"); + Linux_p->tooltip("Check here if you plan to run Mup\n" + "under Linux. " + MULTI_OS); +#ifdef __linux + Linux_p->value(1); +#endif + + other_p = new Fl_Check_Button(240, 280, 60, 30, "Other"); + other_p->tooltip("Check here if you plan to run Mup\n" + "under an OS not listed.\n" + MULTI_OS); + other_OS_p = new Fl_Input(300, 280, 180, 30, ""); + other_OS_p->tooltip("If you checked \"Other,\"\n" + "specify the name of the Operating System.\n" + MULTI_OS); + + mailing_list_p = new Fl_Check_Button(100, 320, 350, 30, + "I would like to join the Mup user's mailing list"); + mailing_list_p->tooltip("There is a email mailing list for registered\n" + "Mup users, for sharing information about Mup.\n" + "Check here if you want to join the list.\n" + "There is no extra charge, and you can always\n" + "subscribe/unsubscribe later if you change your mind."); + + num_regs_p = new Positive_Int_Input(340, 355, 60, 30, + "Number of Registrations ($29 each)"); + num_regs_p->value("1"); + num_regs_p->tooltip("Enter the number of registrations\n" + "you wish to purchase.\n" + MULTI_OS); + + save_form_p = new Fl_Return_Button(40, h() - 50, 120, 30, "Save Form"); + save_form_p->callback(SaveForm_cb, this); + cancel_p = new Fl_Button(w() - 160, h() - 50, 120, 30, "Cancel"); + cancel_p->shortcut(FL_Escape); + cancel_p->when(FL_WHEN_RELEASE); + cancel_p->callback(Cancel_cb, this); + + // Arrange for destructor to clean up new-ed widgets + end(); + + // Arrange for window manager closes to do Cancel. + callback(Cancel_cb, this); + when(FL_WHEN_NEVER); +} + + +RegistrationForm_dialog::~RegistrationForm_dialog(void) +{ +} + + +CALL_BACK(RegistrationForm_dialog, SaveForm) +{ + generate_form(); + hide(); +} + + +CALL_BACK(RegistrationForm_dialog, Cancel) +{ + hide(); +} + + +// Generate the registration form with fields filled in. + +extern const char * const registration_text; +static const char * const checkmark = "X"; +static const char * const reg_file_name = "mup-reg.txt"; + +void +RegistrationForm_dialog::generate_form() +{ + char * text = strdup(registration_text); + + // First find all the fields in the registration form. + // Do this before filling anything is to avoid any chance + // of being confused by what we fill in. + char * name = strstr(text, "Name"); + char * address = strstr(text, "Address"); + char * city = strstr(text, "City"); + char * state = strstr(text, "State"); + char * postal_code = strstr(text, "Zip code"); + char * country = strstr(text, "Country"); + char * email = strstr(text, "Email"); + char * how_heard = strstr(text, "How did you"); + char * how_heard_line2 = strstr(how_heard, "\n\n"); + char * Linux = strstr(text, "Linux"); + char * Windows = strstr(text, "Windows/MS-DOS"); + char * Mac = strstr(text, "Mac"); + char * other = strstr(text, "Other"); + char * mailing_list = strstr(text, "Yes"); + char * regs = strstr(text, "Mup Version"); + + (void) fill_in(false, name, name_p->value()); + (void) fill_in(false, address, address_p->value()); + (void) fill_in(false, city, city_p->value()); + (void) fill_in(false, state, state_p->value()); + (void) fill_in(false, postal_code, postal_code_p->value()); + (void) fill_in(false, country, country_p->value()); + (void) fill_in(false, email, email_p->value()); + const char * remaining; + if ((remaining = fill_in(false, how_heard, how_heard_p->value())) + != 0) { + (void) fill_in(false, how_heard_line2, remaining); + } + + if (Windows_p->value()) { + (void) fill_in(true, Windows, checkmark); + } + if (Linux_p->value()) { + (void) fill_in(true, Linux, checkmark); + } + if (Mac_p->value()) { + (void) fill_in(true, Mac, checkmark); + } + if (other_p->value()) { + (void) fill_in(true, other, checkmark); + } + if (other_OS_p->size() > 0) { + (void) fill_in(false, other, other_OS_p->value()); + } + (void) fill_in(mailing_list_p->value(), mailing_list, checkmark); + + (void) fill_in(true, regs, num_regs_p->value()); + + // write to file + FILE * regfile; + if ((regfile = fopen(reg_file_name, "w")) == 0) { + fl_alert("Unable to write registration form file."); + } + else { + (void) fprintf(regfile, "%s", text); + (void) fprintf(regfile, "\n\n\t Total due: $%.2f\n", + (29.0 + sales_tax()) * atoi(num_regs_p->value())); + fclose(regfile); + char currdir[FL_PATH_MAX]; + + if (getcwd(currdir, sizeof(currdir)) == 0) { + currdir[0] = '\0'; + } + hide(); + fl_message("Your registration form has been saved in\n" + "%s%c%s.", currdir, dir_separator(), reg_file_name); + } + free(text); +} + + +// Fills in value into blank either before or after the given place. +// Center the string in the blank. +// If it can't fit the entire value, it returns a pointer to +// what was left over, otherwise returns zero. + +const char * +RegistrationForm_dialog::fill_in(bool before, char * place, const char * const value) +{ + if (place == 0 || value == 0) { + // Shouldn't happen, but better than core dump. + return(value); + } + + char * blanks_p; + // Find beginning of the blank. + if (before) { + // back up to beginning of blanks, skipping any spaces + for (blanks_p = place - 1; *blanks_p == ' '; blanks_p--) + ; + for ( ; *blanks_p == '_'; blanks_p--) + ; + blanks_p++; + } + else { + blanks_p = strchr(place, '_'); + } + + // Figure out how much leading padding to leave + int count = strspn(blanks_p, "_"); + int length = strlen(value); + + // Fill in the blank. + int padding; + if (length > count) { + // Try to split at white space. + int used_length; + for (used_length = count; used_length > 10; used_length--) { + if (value[used_length] == ' ') { + break; + } + } + padding = (count - used_length) / 2; + strncpy(blanks_p + padding, value, used_length); + return(value + used_length + 1); + } + else { + padding = (count - length) / 2; + strncpy(blanks_p + padding, value, length); + return(0); + } +} + + +// Since Arkkra is based in Illinois, Illinois residents need to pay +// sales tax. So try to deduce if the address is Illinois. +// Simple minded--may sometimes guess wrong. + +double +RegistrationForm_dialog::sales_tax(void) +{ + const char * pattern; + + if (state_p->size() > 0) { + // Skip leading white space + for (pattern = state_p->value(); *pattern == ' '; pattern++) + ; + if (*pattern == '\0') { + return(0.0); + } + // Remove any trailing white space. + // Can't remove in place, since string is const. + // So remove from copy. + char state[strlen(pattern) + 1]; + (void) strcpy(state, pattern); + char * p; + for (p = state + strlen(pattern) - 1; p > state ; p--) { + if (*p == ' ') { + *p = '\0'; + } + else { + break; + } + } + + if (strcmp(state, "IL") == 0 + || strcasecmp(state, "Illinois") == 0 + || strcasecmp(state, "Ill.") == 0) { + // Sales tax is $2.18 per registration. + return(2.18); + } + } + return(0.0); +} + + +//----------dialog to let user type in the Registration Key--------------- + +RegistrationKey_dialog::RegistrationKey_dialog(void) + : Fl_Double_Window(250, 100, "Registration Key") +{ + key_p = new Fl_Secret_Input(60, 20, 150, 30, "Key:"); + key_p->tooltip("Enter the registration key\n" + "you received from Arkkra Enterprises\n" + "after you have paid your registration fee."); + + OK_p = new Fl_Return_Button(25, 60, 80, 30, "OK:"); + OK_p->when(FL_WHEN_RELEASE); + OK_p->callback(OK_cb, this); + + cancel_p = new Fl_Button(120, 60, 90, 30, "Cancel"); + cancel_p->shortcut(FL_Escape); + cancel_p->when(FL_WHEN_RELEASE); + cancel_p->callback(Cancel_cb, this); + + // Arrange for destructor to clean up new-ed widgets + end(); + + // Arrange for window manager closes to do Cancel. + callback(Cancel_cb, this); + when(FL_WHEN_NEVER); +} + + +RegistrationKey_dialog::~RegistrationKey_dialog() +{ +} + +CALL_BACK(RegistrationKey_dialog, OK) +{ + hide(); + FILE * keyfile; + if ((keyfile = fopen(magic_file(), "w")) == 0) { + fl_alert("Unable to open registration key file %s.", + magic_file()); + } + else { + if (fprintf(keyfile, "%s", key_p->value()) != key_p->size()) { + fl_alert("Unable to save registration key in %s.", + magic_file()); + } + fclose(keyfile); + } + + // Blank out the field, for if it gets displayed again later. + key_p->value(""); +} + + +// If user cancels entering registration key, we just hide the window + +CALL_BACK(RegistrationKey_dialog, Cancel) +{ + hide(); +} + + +//-------the Config menu item on main toolbar------------------------------- + +Config::Config() +{ + locations_p = 0; + preferences_p = 0; + registrationform_p = 0; + registrationkey_p = 0; +} + +Config::~Config() +{ + if (locations_p != 0) { + delete locations_p; + locations_p = 0; + } + if (preferences_p != 0) { + delete preferences_p; + preferences_p = 0; + } + if (registrationform_p != 0) { + delete registrationform_p; + registrationform_p = 0; + } + if (registrationkey_p != 0) { + delete registrationkey_p; + registrationkey_p = 0; + } +} + + +// Bring up the dialog for "File Locations" menu item + +CALL_BACK(Config, FileLocations) +{ + if (locations_p == 0) { + // first time, create widget + locations_p = new FileLocations_dialog(); + } + locations_p->show(); +} + + +// Bring up the dialog for "Preferences" menu item + +CALL_BACK(Config, Preferences) +{ + if (preferences_p == 0) { + // first time, create widget + preferences_p = new Preferences_dialog(); + } + preferences_p->show(); +} + + +// Bring up dialog for filling in Registration Form + +CALL_BACK(Config, RegistrationForm) +{ + if (registrationform_p == 0) { + // first time, create widget + registrationform_p = new RegistrationForm_dialog(); + } + registrationform_p->show(); + fl_message("Note: For fastest service, you can register via\n" + "credit card at http://www.arkkra.com/doc/credtcrd.html\n" + "rather than filling out and mailing in a paper form."); +} + + +// Bring up dialog to let user enter their registration key after paying + +CALL_BACK(Config, RegistrationKey) +{ + if (registrationkey_p == 0) { + // first time, create widget + registrationkey_p = new RegistrationKey_dialog(); + } + registrationkey_p->show(); +} + + +// Translate font name to FL_Font value. + +Fl_Font +Config::fontvalue(const char * fontname) +{ + int n; + // Linear search of the list (it is short). + for (n = 0; n < Fontlistlength; n++) { + if (strcmp(Fontlist[n].name, fontname) == 0) { + return(Fontlist[n].value); + } + } + // Hmmm. Not found. Should not happen. Hunt for default + for (n = 0; n < Fontlistlength; n++) { + if (strcmp(Fontlist[n].name, Default_editor_font) == 0) { + return(Fontlist[n].value); + } + } + // Wow. Can't find default either. Punt. + return(FL_COURIER); +} + + +//--------------------- class that lets other classes register a callback +// to be called for changes in font/size + + +// List of callbacks for when font/size change +Font_change_registration * Font_change_registration::list_p = 0; + +Font_change_registration::Font_change_registration(Font_change_callback func, void * arg) +{ + // Save callback information. + callback = func; + callback_arg = arg; + + // Add to list of callbacks. + next = list_p; + list_p = this; + + // Set the font and size on this newly registered widget. + // Look up the current values and call the newly registered callback. + char * fontstr; + (void) Preferences_p->get(Editor_font_preference, fontstr, + Default_editor_font); + Fl_Font font = Config::fontvalue(fontstr); + + char * sizestr; + (void) Preferences_p->get(Editor_size_preference, sizestr, + Default_editor_size); + unsigned char size = (unsigned char) atoi(sizestr); + if (size < Min_size) { + size = (unsigned char) atoi(Default_editor_size); + } + (*func)(arg, font, size); +} + +Font_change_registration::~Font_change_registration(void) +{ + // Remove callback from linked list + if (list_p == this) { + list_p = next; + } + else { + Font_change_registration * fcr_p; + for (fcr_p = list_p; fcr_p != 0; fcr_p = fcr_p->next) { + if (fcr_p->next == this) { + fcr_p->next = next; + return; + } + } + } +} + + +// Notify all classes that want to know about font/size changes, +// by calling the callback function they registered. + +void +Font_change_registration::run_callbacks(Fl_Font font, unsigned char size) +{ + // Avoid unreadably small sizes and division by zero if + // earlier atoi() of size failed due to bad data + // (e.g., user hand-editing the preference file) + if (size < Min_size || size > Max_size) { + size = (unsigned char) atoi(Default_editor_size); + } + + // Walk through list of registered callbacks, calling each. + Font_change_registration * fcr_p; + for (fcr_p = list_p; fcr_p != 0; fcr_p = fcr_p->next) { + (*(fcr_p->callback))(fcr_p->callback_arg, font, size); + } +} diff --git a/mup/mupmate/Config.H b/mup/mupmate/Config.H new file mode 100644 index 0000000..e127a7f --- /dev/null +++ b/mup/mupmate/Config.H @@ -0,0 +1,220 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +// Classes for Config menu item off of main toolbar + +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.H" + + +// Class for window that asks user for file locations + +class FileLocations_dialog : Fl_Double_Window { + +friend class Config; + +public: + FileLocations_dialog(void); + ~FileLocations_dialog(); + + // Callbacks + static void Apply_cb(Fl_Widget *, void *); + static void Cancel_cb(Fl_Widget *, void *); + +private: + // Callbacks + void Apply(void); + void Cancel(void); + + // Populuate fields with current values + void set_current_values(void); + + // Widgets + Fl_Input * mup_program_p; + Fl_Input * mup_documentation_p; + Fl_Input * music_files_p; + Fl_Input * muppath_p; + Fl_Input * viewer_p; + Fl_Input * player_p; + Fl_Return_Button * apply_p; + Fl_Button * cancel_p; +}; + + +// Class for window that asks user for preferences, like editor font, size, etc. + +class Preferences_dialog : Fl_Double_Window { + +friend class Config; + +public: + Preferences_dialog(void); + ~Preferences_dialog(); + + // Callbacks + static void Apply_cb(Fl_Widget *, void * data); + static void Cancel_cb(Fl_Widget *, void * data); + static void fontchg_cb(Fl_Widget *, void * data); + +private: + // Callbacks + void fontchg(void); + void Apply(void); + void Cancel(void); + + // Populate fields with current values + void set_current_values(void); + + // Populate size menu as appropriate for the given font + void set_size_list(Fl_Font font, uchar curr_size); + + // Widgets + Fl_Choice * font_p; + Fl_Choice * size_p; + Fl_Check_Button * auto_display_p; + Fl_Check_Button * auto_save_p; + Fl_Value_Input * tooltips_delay_p; + Fl_Return_Button * apply_p; + Fl_Button * cancel_p; +}; + + +// Class for user to fill out registration form + +class RegistrationForm_dialog : public Fl_Double_Window +{ +public: + RegistrationForm_dialog(void); + ~RegistrationForm_dialog(void); + + // Callbacks + static void SaveForm_cb(Fl_Widget *, void * data); + static void Cancel_cb(Fl_Widget *, void * data); + +private: + // Callbacks + void SaveForm(void); + void Cancel(void); + + // Fill in the form and write it out for user to mail with payment. + void generate_form(void); + // Fill in the value in the blank before or after the given place. + // If can't fit entire value, returns pointer to how far it got, + // otherwise returns zero. + const char * fill_in(bool before, char *place, const char * const value); + // Calculate sales tax due. + double sales_tax(void); + + // Widgets + Fl_Input * name_p; + Fl_Input * address_p; + Fl_Input * city_p; + Fl_Input * state_p; + Fl_Input * postal_code_p; + Fl_Input * country_p; + Fl_Input * email_p; + Fl_Input * how_heard_p; + Fl_Check_Button * Windows_p; + Fl_Check_Button * Mac_p; + Fl_Check_Button * Linux_p; + Fl_Check_Button * other_p; + Fl_Input * other_OS_p; + Fl_Check_Button * mailing_list_p; + Positive_Int_Input * num_regs_p; + + Fl_Return_Button * save_form_p; + Fl_Button * cancel_p; +}; + + +// Class for user to enter registration key after paying. + +class RegistrationKey_dialog : public Fl_Double_Window { +public: + RegistrationKey_dialog(void); + ~RegistrationKey_dialog(); + + // Callbacks + static void OK_cb(Fl_Widget *, void *); + static void Cancel_cb(Fl_Widget *, void *); + +private: + // Callbacks + void OK(void); + void Cancel(void); + + // Widgets + Fl_Secret_Input * key_p; + Fl_Return_Button * OK_p; + Fl_Button * cancel_p; +}; + +// Class for the Config menu item on main toolbar + +class Config { +public: + Config(); + ~Config(); + + // Callbacks + static void FileLocations_cb(Fl_Widget *, void *); + static void Preferences_cb(Fl_Widget *, void *); + static void RegistrationForm_cb(Fl_Widget *, void *); + static void RegistrationKey_cb(Fl_Widget *, void *); + + // Convert font name to Fl_Font value + static Fl_Font fontvalue(const char *); + +private: + // Callbacks + void FileLocations(void); + void Preferences(void); + void RegistrationForm(void); + void RegistrationKey(void); + + // Widgets + FileLocations_dialog * locations_p; + Preferences_dialog * preferences_p; + RegistrationForm_dialog * registrationform_p; + RegistrationKey_dialog * registrationkey_p; +}; + + +// Any class that wants to be notified of changes in user preference +// for font and size should register a callback function of this type +// using the Font_change_registration class. The first arg will be user +// data the registrant wants to have passed to it. The second argument +// is the new font, and the third argument is the new size. +typedef void (*Font_change_callback)(void *, Fl_Font, unsigned char); + +// Any class that wants to be notified of changes in user preference +// in font/size should instantiate an instance of this class. +class Font_change_registration { +public: + Font_change_registration(Font_change_callback func, void * arg); + ~Font_change_registration(void); + + // This runs all the registered callbacks + static void run_callbacks(Fl_Font font, unsigned char size); + +private: + // Linked list of callbacks + static Font_change_registration * list_p; + Font_change_registration * next; + + // What function to call back, and what to pass it. + Font_change_callback callback; + void * callback_arg; +}; + +#endif diff --git a/mup/mupmate/Edit.C b/mup/mupmate/Edit.C new file mode 100644 index 0000000..f85e632 --- /dev/null +++ b/mup/mupmate/Edit.C @@ -0,0 +1,640 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +// Code for Edit menu on main toolbar + + +#include "globals.H" +#include "Edit.H" +#include "utils.H" +#include +#include +#include +#include +#include + + +//-------------------Find_dialog class-------------------------------- +// This class is for the window that pops up when user does a "Find" + +// Constructor creates the window and all the widgets inside it + +Find_dialog::Find_dialog(void) + : Fl_Double_Window(430, 170, "Find") +{ + pattern_p = new Fl_Input(90, 20, 175, 20, "Find what:"); + // We have ungray the "Find Next" when user enters a pattern, + // so set up callback for that + pattern_p->callback(Pattern_cb, this); + pattern_p->when(FL_WHEN_CHANGED); + pattern_p->tooltip("Enter the pattern you want to\n" + "search for in your Mup input."); + + replace_with_p = new Fl_Input(90, 60, 175, 20, "Replace with"); + replace_with_p->tooltip("Enter the replacement text."); + replace_with_p->hide(); + + casematch_p = new Fl_Check_Button(10, 85, 100, 20, "Match case"); + casematch_p->tooltip("If checked, upper/lower case must match.\n" + "If not checked, case is ignored."); + + direction_p = new Fl_Box(FL_ENGRAVED_BOX, 120, 55, 125, 35, ""); + up_p = new Fl_Round_Button(130, 60, 40, 20, "Up"); + up_p->type(FL_RADIO_BUTTON); + up_p->value(0); + up_p->tooltip("Search upward from current place."); + up_p->callback(change_cb, this); + down_p = new Fl_Round_Button(175, 60, 60, 20, "Down"); + down_p->type(FL_RADIO_BUTTON); + down_p->value(1); + down_p->tooltip("Search downward from current place."); + down_p->callback(change_cb, this); + + next_p = new Fl_Return_Button(285, 10, 125, 30, "Find Next"); + next_p->when(FL_WHEN_RELEASE); + next_p->callback(FindNext_cb, this); + next_p->deactivate(); + + replace_p = new Fl_Button(285, 45, 125, 30, "Replace"); + replace_p->tooltip("Replace the current instance of the pattern\n" + "with the replacement text."); + replace_p->callback(Replace_cb, this); + replace_p->when(FL_WHEN_RELEASE); + replace_p->deactivate(); + replace_p->hide(); + + replace_all_p = new Fl_Button(285, 80, 125, 30, "Replace All"); + replace_all_p->tooltip("Replace all instances of the pattern\n" + "with the replacement text."); + replace_all_p->callback(ReplaceAll_cb, this); + replace_all_p->when(FL_WHEN_RELEASE); + replace_all_p->deactivate(); + replace_all_p->hide(); + + cancel_p = new Fl_Button(285, 115, 125, 30, "Cancel"); + cancel_p->shortcut(FL_Escape); + cancel_p->when(FL_WHEN_RELEASE); + cancel_p->callback(Cancel_cb, this); + + // Arrange for destructor to clean up new-ed widgets + end(); + + // Arrange for window manager closes to do Cancel. + callback(Cancel_cb, this); + when(FL_WHEN_NEVER); +} + +Find_dialog::~Find_dialog() +{ +} + + +// The class can be used for either Find or Replace. +// These next two methods set which of those two personalities +// the window has. + +void +Find_dialog::as_Find() +{ + label("Find"); + cancel_p->resize(cancel_p->x(), 55, cancel_p->w(), cancel_p->h()); + casematch_p->resize(casematch_p->x(), 65, casematch_p->w(), casematch_p->h()); + resize(x(), y(), w(), 120); + direction_p->show(); + up_p->show(); + down_p->show(); + replace_with_p->hide(); + replace_p->hide(); + replace_all_p->hide(); + is_replace = false; +} + +void +Find_dialog::as_Replace() +{ + label("Replace"); + cancel_p->resize(cancel_p->x(), 115, cancel_p->w(), cancel_p->h()); + casematch_p->resize(casematch_p->x(), 115, casematch_p->w(), casematch_p->h()); + resize(x(), y(), w(), 155); + direction_p->hide(); + up_p->hide(); + down_p->hide(); + replace_with_p->show(); + replace_p->show(); + replace_all_p->show(); + is_replace = true; +} + + +// Callback for when user clicks "Find Next" button after filling in +// the dialog. + +CALL_BACK(Find_dialog, FindNext) +{ + int start = editor_p->insert_position(); + bool found; + int where; + if (down_p->value() == 1 || is_replace) { + found = editor_p->buffer()->search_forward( + start + 1, pattern_p->value(), + &where, casematch_p->value()); + } + else { + found = editor_p->buffer()->search_backward( + start - 1, pattern_p->value(), + &where, casematch_p->value()); + } + + if ( ! found ) { + // It seems fltk does not find a pattern if it is exactly + // at the beginning for an upward search or exactly + // at the end for a downward search. That surely can't + // be right, so add special checks for that. If fltk + // fixes that some day, we'll never hit this case, + // so this should still be compatible. + int patlength = pattern_p->size(); + int bufflength = editor_p->buffer()->length(); + where = (down_p->value() ? bufflength - patlength : 0); + // If pattern is longer than buffer, then no match possible. + // If already at pattern, + // we already found the end one last time. + if (patlength <= bufflength && + where != editor_p->insert_position() - patlength) { + if (casematch_p->value()) { + if (strncmp(pattern_p->value(), + editor_p->buffer()->text() + + where, patlength) == 0) { + found = 1; + } + } + else { + if (strncasecmp(pattern_p->value(), + editor_p->buffer()->text() + + where, patlength) == 0) { + found = 1; + } + } + } + + if ( ! found ) { + fl_alert("Cannot find \"%s\"", pattern_p->value()); + gray_out(); + + // The main editor window should now + // be made active, rather than the Find window. + editor_p->take_focus(); + } + } + if (found) { + editor_p->buffer()->highlight(where, where + pattern_p->size()); + editor_p->insert_position(where + pattern_p->size()); + editor_p->show_insert_position(); + } +} + + +// Callback for when user clicks "Replace" + +CALL_BACK(Find_dialog, Replace) +{ + // See if we are already at the pattern to replace due to + // a previous Replace/Find Next + int start, end, isRect, rectStart, rectEnd; + bool at_pattern = false; + if (editor_p->buffer()->highlight_position(&start, &end, &isRect, + &rectStart, &rectEnd)) { + int place = editor_p->insert_position(); + if (place == end && (end - start == pattern_p->size())) { + if (casematch_p->value()) { + + at_pattern = (strncmp(pattern_p->value(), + editor_p->buffer()->text() + start, + pattern_p->size()) == 0); + } + else { + at_pattern = (strncasecmp(pattern_p->value(), + editor_p->buffer()->text() + start, + pattern_p->size()) == 0); + } + } + } + + if (at_pattern) { + editor_p->buffer()->unhighlight(); + editor_p->buffer()->replace(start, end, replace_with_p->value()); + } + + FindNext(); +} + + +// Callback for when use clicks "Replace All" + +CALL_BACK(Find_dialog, ReplaceAll) +{ + // We want to be able to "undo" the entire "Replace All" + // so we make a copy of the buffer, make all the changes in the + // copy and then replace the original with the altered copy. + Fl_Text_Buffer altered_buff; + altered_buff.copy(editor_p->buffer(), 0, editor_p->buffer()->length(), 0); + int start; // where to begin each search + bool found = true; // if matching pattern found on current search + int where; // offset into buffer where match occurred + int new_cursor_pos; + bool replaced_something = false; // if any matches found at all + + new_cursor_pos = editor_p->insert_position(); + for (start = 0; found; start = where + replace_with_p->size()) { + if ((found = altered_buff.search_forward( + start, pattern_p->value(), + &where, casematch_p->value())) + != 0) { + altered_buff.replace(where, where + pattern_p->size(), + replace_with_p->value()); + new_cursor_pos = where + replace_with_p->size(); + replaced_something = true; + } + } + // Kludge because pattern at very end is not found. + // See more complete explanation in FindNext(). + where = altered_buff.length() - pattern_p->size(); + if (where >= 0) { + found = false; + if (casematch_p->value()) { + if (strcmp(pattern_p->value(), + altered_buff.text() + where) == 0) { + found = true; + } + } + else { + if (strcasecmp(pattern_p->value(), + altered_buff.text() + where) == 0) { + found = true; + } + } + if (found) { + altered_buff.replace(where, where + pattern_p->size(), + replace_with_p->value()); + new_cursor_pos = where + replace_with_p->size(); + replaced_something = true; + } + } + + if (replaced_something) { + editor_p->buffer()->replace(0, editor_p->buffer()->length(), + altered_buff.text()); + editor_p->insert_position(new_cursor_pos); + } + else { + fl_alert("No instances of pattern to replace."); + } + replace_all_p->deactivate(); +} + + +// Callback for when user clicks "Cancel" in the "Find" window. +// Hides the window. + +CALL_BACK(Find_dialog, Cancel) +{ + editor_p->buffer()->unhighlight(); + hide(); +} + + +// If user did Find Next until no more instances found, +// the Find Next and Replace buttons will get grayed out, +// But if they then change search direction, we need to reactivate them +// since the pattern might be found in that direction. +// They must also be ungrayed if the contents of the editor buffer change, +// since the new text might contain the pattern. + +CALL_BACK(Find_dialog, change) +{ + next_p->activate(); + replace_p->activate(); + replace_all_p->activate(); +} + + +// Callback for when user changes pattern, to know whether to gray or ungray +// Find Next button or not. + +CALL_BACK(Find_dialog, Pattern) +{ + if (pattern_p->size() > 0) { + next_p->activate(); + replace_p->activate(); + replace_all_p->activate(); + } + else { + gray_out(); + } +} + +// Horrible kludge. If the "Find" or "Replace" is grayed out because there +// are no more instances of the pattern in the current direction, +// and then user moves the cursor somewhere else, it's possible the pattern +// may then be findable. But modify_callback does not get called for +// a change in cursor position. So we poll to see if the cursor position +// changed since the last check, and if so, ungray. +// Fortunately, we can limit this to only when the button are grayed, +// which shouldn't be too often. + +void +Find_dialog::gray_out(void) +{ + next_p->deactivate(); + replace_p->deactivate(); + replace_all_p->deactivate(); + // Remember where we are and set up to poll for changes + last_cursor_position = editor_p->insert_position(); + Fl::add_timeout(0.5, cursor_change_check, this); +} + +void +Find_dialog::cursor_change_check(void * data) +{ + Find_dialog * obj_p = (Find_dialog *) data; + if (obj_p->editor_p->insert_position() != obj_p->last_cursor_position + && obj_p->pattern_p->size() > 0) { + obj_p->change(); + } + else { + Fl::repeat_timeout(0.5, cursor_change_check, data); + } +} + + +// Class needs access to the editor; this lets it know which editor +// instance to use, and which main window it is associated with. + +void +Find_dialog::set_editor(Fl_Text_Editor * ed) +{ + editor_p = ed; +} + + +// Returns the current "Find" pattern entered by user, +// or "" if they have not yet entered any such pattern + +const char * +Find_dialog::get_pattern() +{ + if (pattern_p->value() == 0) { + return(""); + } + else { + return(pattern_p->value()); + } +} + + +//---------------- GoTo class--------------------------------------------- + +GoTo_dialog::GoTo_dialog(void) + : Fl_Double_Window(225, 95, "Goto line") +{ + linenum_p = new Positive_Int_Input(115, 10, 60, 30, "Line Number:"); + linenum_p->tooltip("Enter the line number of the line\n" + "you want to make the current line."); + + ok_p = new Fl_Return_Button(25, 50, 75, 30, "OK"); + ok_p->when(FL_WHEN_RELEASE); + ok_p->callback(OK_cb, this); + + cancel_p = new Fl_Button(125, 50, 75, 30, "Cancel"); + cancel_p->shortcut(FL_Escape); + cancel_p->when(FL_WHEN_RELEASE); + cancel_p->callback(Cancel_cb, this); + + // Arrange for destructor to clean up new-ed widgets + end(); + + // Arrange for window manager closes to do Cancel. + callback(Cancel_cb, this); + when(FL_WHEN_NEVER); +} + +GoTo_dialog::~GoTo_dialog() +{ +} + + +// Callback for when user clicks "OK" in GoTo dialog + +CALL_BACK(GoTo_dialog, OK) +{ + // Find end of valid range + int last_line = editor_p->buffer()->count_lines(0, + editor_p->buffer()->length()); + // FLTK line numbers start at 0, so we have to subtract 1 from + // number supplied by user. + int desired_line = (int) strtol(linenum_p->value(), 0, 0) - 1; + if (desired_line < 0 || desired_line > last_line) { + fl_alert("Line number out of range"); + return; + } + + // Find appropriate new cursor position and move cursor there + int newposition = editor_p->buffer()->skip_lines(0, desired_line); + editor_p->insert_position(newposition); + editor_p->show_insert_position(); + hide(); +} + + +// Callback if user cancel Go To + +CALL_BACK(GoTo_dialog, Cancel) +{ + hide(); +} + + +// Code that calls constructor should then call this to tell +// us which editor instance to act upon. + +void +GoTo_dialog::set_editor(Fl_Text_Editor * ed) +{ + editor_p = ed; +} + + +// Initialize contents on GoTo field to the current line number + +void +GoTo_dialog::set_current_line() +{ + char num_as_string[16]; + // fltk numbers lines from 0, so add 1 to get what user expects + (void) sprintf(num_as_string, "%d", + editor_p->buffer()->count_lines(0, editor_p->insert_position()) + 1); + linenum_p->value(num_as_string); +} + + +//------------------Edit class----------------------------------------------- +// Implements the items in the Edit menu on the main toolbar + + +Edit::Edit() +{ + find_p = 0; + goto_p = 0; + wrote_to_clipboard = false; +} + + +Edit::~Edit() +{ + if (find_p != 0) { + delete find_p; + find_p = 0; + } + if (goto_p != 0) { + delete goto_p; + goto_p = 0; + } +} + + +//---Undo menu item--------------- + +CALL_BACK(Edit, Undo) +{ + buffer_p->undo(); +} + + +//---Cut menu item--------------- + +CALL_BACK(Edit, Cut) +{ + Fl_Text_Editor::kf_cut('x', editor_p); + set_can_paste(); +} + + +//---Copy menu item--------------- + +CALL_BACK(Edit, Copy) +{ + Fl_Text_Editor::kf_copy('c', editor_p); + set_can_paste(); +} + + +//---Paste menu item--------------- + +CALL_BACK(Edit, Paste) +{ + Fl_Text_Editor::kf_paste('v', editor_p); +} + + +//---Delete menu item--------------- + +CALL_BACK(Edit, Delete) +{ + buffer_p->remove_selection(); + buffer_p->unselect(); +} + + +//---Find menu item--------------- + +CALL_BACK(Edit, Find) +{ + if (find_p == 0) { + // First time, create widget + find_p = new Find_dialog(); + find_p->set_editor(editor_p); + } + find_p->as_Find(); + find_p->show(); +} + + +//---Find Next menu item--------------- + +CALL_BACK(Edit, FindNext) +{ + if (find_p == 0 || strlen(find_p->get_pattern()) == 0) { + // No pattern specified yet; turn into Find + Find(); + return; + } + find_p->FindNext(); +} + + +//---Replace menu item--------------- + +CALL_BACK(Edit, Replace) +{ + if (find_p == 0) { + // First time, create widget + find_p = new Find_dialog(); + find_p->set_editor(editor_p); + } + find_p->as_Replace(); + find_p->show(); +} + + +//---Go To menu item--------------- + +CALL_BACK(Edit, GoTo) +{ + if (goto_p == 0) { + // First time, create widget + goto_p = new GoTo_dialog(); + goto_p->set_editor(editor_p); + } + goto_p->set_current_line(); + goto_p->show(); +} + + +//---Select All menu item--------------- + +CALL_BACK(Edit, SelectAll) +{ + buffer_p->select(0, buffer_p->length()); +} + + +//---- Callback for when editor window is modified. +// Grayed out find/replace should be ungrayed, because the modified +// text might now match. + +void +Edit::modify_cb(int, int, int, int, const char *, void * data) +{ + if ( ((Edit *)data)->find_p != 0) { + ((Edit *)data)->find_p->change(); + } +} + + +// Class needs access to the editor; this lets it know which editor +// instance to use. + +void +Edit::set_editor(Fl_Text_Editor * ed) +{ + editor_p = ed; + buffer_p = editor_p->buffer(); +} + +// Ungray Paste button + +void +Edit::set_can_paste(void) +{ + wrote_to_clipboard = true; + editor_p->buffer()->call_modify_callbacks(); +} diff --git a/mup/mupmate/Edit.H b/mup/mupmate/Edit.H new file mode 100644 index 0000000..8ab39fe --- /dev/null +++ b/mup/mupmate/Edit.H @@ -0,0 +1,171 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _EDIT_H_ +#define _EDIT_H_ + +// Classes for Edit menu item off of main toolbar + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +// Class for window that pops up for "Find" or "Replace" + +class Find_dialog : public Fl_Double_Window { + +friend class Edit; // so it can call FindNext() + +public: + Find_dialog(void); + ~Find_dialog(); + + // Callbacks + static void FindNext_cb(Fl_Widget *, void * data); + static void Replace_cb(Fl_Widget *, void * data); + static void ReplaceAll_cb(Fl_Widget *, void * data); + static void Cancel_cb(Fl_Widget *, void * data); + static void Pattern_cb(Fl_Widget *, void * data); + static void change_cb(Fl_Widget *, void * data); + static void cursor_change_check(void * data); + + // Returns current search pattern + const char * get_pattern(void); + + // Tells class which edit buffer to search in + void set_editor(Fl_Text_Editor *); + + // Class instance can be either a Find or a Replace. + // These change the personality. + void as_Find(void); + void as_Replace(void); + + // when not allowed to search/replace + void gray_out(void); + +private: + // Callbacks + void FindNext(void); + void Replace(void); + void ReplaceAll(void); + void Cancel(void); + void Pattern(void); + void change(void); + + // Widgets + Fl_Input * pattern_p; + Fl_Input * replace_with_p; + Fl_Button * replace_p; + Fl_Button * replace_all_p; + Fl_Check_Button * casematch_p; + Fl_Box * direction_p; + Fl_Round_Button * up_p; + Fl_Round_Button * down_p; + Fl_Return_Button * next_p; + Fl_Button * cancel_p; + + // The text editor widget we are editing + Fl_Text_Editor * editor_p; + + // true if current personality is "Replace," false if "Find." + bool is_replace; + + // Where cursor was at last check + int last_cursor_position; +}; + + +// Class for window that pops up for Go To + +class GoTo_dialog : Fl_Double_Window { + +friend class Edit; + +public: + GoTo_dialog(void); + ~GoTo_dialog(); + + // Callbacks + static void OK_cb(Fl_Widget *, void * data); + static void Cancel_cb(Fl_Widget *, void * data); + + // Tells us which editor instance to use + void set_editor(Fl_Text_Editor * ed); + + // Initialize contents on GoTo field to the current line number + void set_current_line(); + +private: + // Callbacks + void OK(void); + void Cancel(void); + + // Widgets + Fl_Int_Input * linenum_p; + Fl_Return_Button * ok_p; + Fl_Button * cancel_p; + Fl_Text_Editor * editor_p; +}; + + +// Class for Edit Menu from main toolbar + +class Edit { +public: + Edit(); + ~Edit(); + + // Callbacks + static void Undo_cb(Fl_Widget *, void * data); + static void Cut_cb(Fl_Widget *, void * data); + static void Copy_cb(Fl_Widget *, void * data); + static void Paste_cb(Fl_Widget *, void * data); + static void Delete_cb(Fl_Widget *, void * data); + static void Find_cb(Fl_Widget *, void * data); + static void FindNext_cb(Fl_Widget *, void * data); + static void Replace_cb(Fl_Widget *, void * data); + static void GoTo_cb(Fl_Widget *, void * data); + static void SelectAll_cb(Fl_Widget *, void * data); + static void modify_cb(int, int, int, int, const char *, void * data); + + // Tells us which editor instance to use + void set_editor(Fl_Text_Editor * ed); + + // true if there is something in the clipboard that can be pasted + bool can_paste() { return wrote_to_clipboard; } + void set_can_paste(); + +private: + // Callbacks + void Undo(void); + void Cut(void); + void Copy(void); + void Paste(void); + void Delete(void); + void Find(void); + void FindNext(void); + void Replace(void); + void GoTo(void); + void SelectAll(void); + + // Widgets + Fl_Text_Editor * editor_p; + Fl_Text_Buffer * buffer_p; + Find_dialog * find_p; + GoTo_dialog * goto_p; + + // if wrote something to the cut/copy buffer + bool wrote_to_clipboard; +}; + +#endif diff --git a/mup/mupmate/File.C b/mup/mupmate/File.C new file mode 100644 index 0000000..3c1001a --- /dev/null +++ b/mup/mupmate/File.C @@ -0,0 +1,608 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +// Code for the File menu off the main toolbar + +#include +#include +#include +#include +#include +#include +#include +#ifndef OS_LIKE_WIN32 +#include +#endif +#include +#include +#include +#include +#include +#include "globals.H" +#include "File.H" +#include "Main.H" +#include "Preferences.H" +#include "utils.H" +#include +#ifdef OS_LIKE_WIN32 +#include +#include +#endif + +// The file name filters +#define Mup_filter "*.mup" +#define All_filter "*.*" + +extern char dir_separator(); +extern const char * const template_text; + + +//-----------------Class to implement the File menu off the main menu bar + +File::File() +{ + filename = 0; + unsaved_changes = false; +} + +File::~File() +{ + if (filename) { + delete filename; + filename = 0; + } +} + + +//--- the "New" menu item ------------- + +CALL_BACK(File, New) +{ + // Ask user if they want to save any unsaved change on + // current file first. + switch (save_changes_check()) { + default: // default case should be impossible + case Save_confirm_dialog::Cancel: + return; + case Save_confirm_dialog::No: + break; + case Save_confirm_dialog::Yes: + Save(false); + break; + } + + // Clear the current edit buffer + Fl_Text_Buffer * buffer_p = editor_p->buffer(); + buffer_p->replace(0, buffer_p->length(), ""); + + if (filename) { + delete filename; + filename = 0; + } + set_window_label(); + // Reset state information + begin_new_file(); +} + + +// --- the "New From Template" menu item + +CALL_BACK(File, NewFromTemplate) +{ + New(); + editor_p->buffer()->append(template_text); + unsaved_changes = false; +} + +//--- the "Open" menu item ------------- + +CALL_BACK(File, Open) +{ + // If already editing a file, ask user if they want to + // save any unsaved changes first + switch (save_changes_check()) { + default: // default case should be impossible + case Save_confirm_dialog::Cancel: + return; + case Save_confirm_dialog::No: + break; + case Save_confirm_dialog::Yes: + Save(false); + break; + } + + // Clear out label to "Untitled" in case the load fails + set_window_label(); + + // Ask user for filename. If they give one, load it into editor. + const char * newfile = open_ask_user(); + if (newfile != 0 && newfile[0] != '\0') { + load_file(newfile); + } +} + + +//--- the "Save" menu item ------------- + +// Save the current buffer contents. +// If honor_auto_display is true and user has requested auto display, +// do the Run>Display action. If the save was due to finishing up an old +// file to start on a new or due to saving before exiting, we don't do that; +// it is only done if user did an explicit Save or Save As. + +CALL_BACK_A(File, Save, bool honor_auto_display) +{ + if (filename == 0) { + // No file name given yet, so change into a Save As + SaveAs(honor_auto_display); + } + else { + save_file(honor_auto_display); + } +} + + +//--- the "SaveAs" menu item ------------- + +CALL_BACK_A(File, SaveAs, bool honor_auto_display) +{ + // Ask user for name of file to save to + const char * newfile = save_as_ask_user(); + if (newfile != 0 && newfile[0] != '\0') { + + // If user didn't give a suffix, add .mup suffix. + // If they used .ps or .mid or .err suffix, don't allow that. + const char * suffix = fl_filename_ext(newfile); + char * suffixed_filename = 0; + if (*suffix == '\0') { + // User did not supply a suffix, so we add .mup + suffixed_filename = new char[strlen(newfile) + 5]; + (void) sprintf(suffixed_filename, "%s.mup", newfile); + newfile = suffixed_filename; + } + else if (strcasecmp(suffix, ".ps") == 0 + || strcasecmp(suffix, ".mid") == 0 + || strcasecmp(suffix, ".err") == 0) { + fl_alert("A filename extension of .ps .mid or .err\n" + "is not allowed for Mup input files,\n" + "since those extensions are used for\n" + "PostScript, MIDI, and error output files."); + return; + } + + if (access(newfile, F_OK) == 0) { + const char * ask_replace = " already exists. Do you want to replace it?"; + char question[strlen(newfile) + strlen(ask_replace) + 1]; + (void) sprintf(question, "%s%s\n", newfile, ask_replace); + switch (Save_confirm_dialog::confirm_save(question)) { + default: // default case should be impossible. + case Save_confirm_dialog::Cancel: + case Save_confirm_dialog::No: + if (suffixed_filename != 0) { + delete suffixed_filename; + } + return; + case Save_confirm_dialog::Yes: + break; + } + } + + // Save the name of the new file + if (filename != 0) { + // forget previous file name + delete filename; + } + if (suffixed_filename != 0) { + filename = suffixed_filename; + } + else { + filename = new char[strlen(newfile) + 1]; + (void) sprintf(filename, newfile); + } + + set_window_label(); + save_file(honor_auto_display); + } +} + + +//--- the "Exit" menu item ------------- + +CALL_BACK(File, Exit) +{ + switch (save_changes_check()) { + default: // default case should be impossible + case Save_confirm_dialog::Cancel: + return; + case Save_confirm_dialog::No: + break; + case Save_confirm_dialog::Yes: + Save(false); + break; + } + Main::clean_exit(); +} + +//------------------------------------------------------------------------ + +// This class needs access to editor window, so whoever creates an instance +// of this class needs to call this function to give it access. + +void +File::set_editor(Fl_Text_Editor * ed) +{ + editor_p = ed; +} + + +// We need to set parent's label, etc. Save info about parent. + +void +File::set_parent(Main * win_p) +{ + parent_window_p = win_p; +} + +// Called when user makes a change in editor window. +// Let's us know if we need to prompt user about unsaved changes. + +void +File::modify_cb(int, int num_inserted, int num_deleted, int, const char *, void * data) +{ + if (num_inserted > 0 || num_deleted > 0) { + ((File *)data)->unsaved_changes = true; + } +} + + +// Utility method that does the details of saving the current file + +void +File::save_file(bool honor_auto_display) +{ + if (editor_p->buffer()->savefile(filename) != 0) { + fl_alert("failed to save file %s", filename); + } + else { + // All unsaved changes have now been saved + unsaved_changes = false; + + // If user wants auto-display on save, do that + if (honor_auto_display) { + int auto_display; + (void) Preferences_p->get(Auto_display_preference, auto_display, + Default_auto_display); + if (auto_display) { + parent_window_p->runmenu_p->Display(); + } + } + } +} + + +// Utility method to ask user if they want to save changes. +// Returns: +// Cancel don't do anything +// No do action without saving changes +// Yes save changes before doing action +// The extra_text argument allows caller to enhance the question +// asked of the user. The "No" button can be hidden. + +Save_confirm_dialog::Answer +File::save_changes_check(const char * extra_text, bool hide_the_No) +{ + if ( ! unsaved_changes ) { + return Save_confirm_dialog::No; + } + const char * name = effective_filename(); + char question[200 + strlen(name) + strlen(extra_text)]; + (void) sprintf(question, "The text in the %s file has changed. " + "Do you want to save the changes? %s", name, extra_text); + return(Save_confirm_dialog::confirm_save(question, hide_the_No)); +} + + +// Read the given file into the editor window. + +void +File::load_file(const char * name) +{ + // Free up existing file name, if any + if (filename != 0) { + delete filename; + filename = 0; + } + + // If name supplied doesn't have .mup suffix, + // try again with that suffix added. + char * newname = 0; + if (access(name, F_OK) != 0) { + if (strlen(name) < 5 || + strcasecmp(name + strlen(name) - 4, ".mup") != 0) { + newname = new char[strlen(name) + 5]; + (void) sprintf(newname, "%s.mup", name); + } + } + if (newname == 0) { + newname = new char[strlen(name) + 1]; + (void) strcpy(newname, name); + } + + // Mup files are typically only a few Kbytes, + // so we probably don't need the default 128 K buffer, + // but memory is cheap enough these days, so just go with that. + if (editor_p->buffer()->loadfile(newname) != 0) { + fl_alert("Unable to load file \"%s\"", newname); + delete newname; + } + else { + filename = newname; + } + + // Reset state information for a new file + begin_new_file(); + + // add file name to window label + set_window_label(); +} + +void +File::set_window_label() +{ + if (parent_window_p == 0) { + return; + } + const char * name = effective_filename(); + char label[strlen(name) + 11]; + (void) sprintf(label, "%s - Mupmate", name); + parent_window_p->copy_label(label); +} + + +const char * +File::effective_filename(void) +{ + return(filename == 0 ? "Untitled.mup" : filename); +} + +void +File::begin_new_file(void) +{ + parent_window_p->begin_new_file(); + unsaved_changes = false; +} + +#ifndef OS_LIKE_WIN32 +// Add Icon for Mup files. + +// Figure out note polygon one time and just add these offsets for the other... +#define RIGHT_NOTE_X 5800 +#define RIGHT_NOTE_Y -1200 + +static short Mup_icon_data[] = { + Fl_File_Icon::COLOR, 0, FL_RED, + + // left stem + Fl_File_Icon::POLYGON, + Fl_File_Icon::VERTEX, 600, 1200, + Fl_File_Icon::VERTEX, 600, 8200, + Fl_File_Icon::VERTEX, 1200, 8200, + Fl_File_Icon::VERTEX, 1200, 1200, + Fl_File_Icon::VERTEX, 600, 1200, + Fl_File_Icon::END, + + // right stem + Fl_File_Icon::POLYGON, + Fl_File_Icon::VERTEX, 6400, 600, + Fl_File_Icon::VERTEX, 6400, 7000, + Fl_File_Icon::VERTEX, 7000, 7000, + Fl_File_Icon::VERTEX, 7000, 600, + Fl_File_Icon::VERTEX, 6400, 600, + Fl_File_Icon::END, + + // beam + Fl_File_Icon::POLYGON, + Fl_File_Icon::VERTEX, 600, 1200, + Fl_File_Icon::VERTEX, 600, 2700, + Fl_File_Icon::VERTEX, 7000, 2100, + Fl_File_Icon::VERTEX, 7000, 600, + Fl_File_Icon::VERTEX, 600, 2000, + Fl_File_Icon::END, + + // left note + Fl_File_Icon::POLYGON, + Fl_File_Icon::VERTEX, 600, 8200, + Fl_File_Icon::VERTEX, 1600, 9400, + Fl_File_Icon::VERTEX, 3200, 9400, + Fl_File_Icon::VERTEX, 3800, 8800, + Fl_File_Icon::VERTEX, 3800, 8000, + Fl_File_Icon::VERTEX, 3000, 7200, + Fl_File_Icon::VERTEX, 1600, 7200, + Fl_File_Icon::VERTEX, 800, 7900, + Fl_File_Icon::VERTEX, 800, 8200, + Fl_File_Icon::VERTEX, 500, 9000, + Fl_File_Icon::END, + + // right note + Fl_File_Icon::POLYGON, + Fl_File_Icon::VERTEX, 600 + RIGHT_NOTE_X, 8200 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 1600 + RIGHT_NOTE_X, 9400 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 3200 + RIGHT_NOTE_X, 9400 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 3800 + RIGHT_NOTE_X, 8800 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 3800 + RIGHT_NOTE_X, 8000 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 3000 + RIGHT_NOTE_X, 7200 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 1600 + RIGHT_NOTE_X, 7200 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 800 + RIGHT_NOTE_X, 7900 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 800 + RIGHT_NOTE_X, 8200 + RIGHT_NOTE_Y, + Fl_File_Icon::VERTEX, 500 + RIGHT_NOTE_X, 9000 + RIGHT_NOTE_Y, + Fl_File_Icon::END, + + Fl_File_Icon::END +}; + +void +File::add_mup_icon(void) +{ + new Fl_File_Icon("*.mup", Fl_File_Icon::PLAIN, + sizeof(Mup_icon_data) / sizeof(Mup_icon_data[0]), + Mup_icon_data); +} +#endif + + + +// Ask user for name of file to open, and return their choice + +const char * +File::open_ask_user(void) +{ +#ifdef OS_LIKE_WIN32 + OPENFILENAME openfilename; + static CHAR path[FL_PATH_MAX] = "*.mup"; + CHAR dir[FL_PATH_MAX]; + memset(&openfilename, 0, sizeof(openfilename)); + GetCurrentDirectory(sizeof(dir), dir); + openfilename.lStructSize = sizeof(openfilename); + parent_window_p->make_current(); + openfilename.hwndOwner = fl_window; + openfilename.hInstance = fl_display; + openfilename.lpstrFilter = "Mup files (*.mup)\0*.mup\0All files (*.*)\0*.*\0"; + openfilename.lpstrFile = path; + openfilename.nMaxFile = sizeof(path); + openfilename.lpstrInitialDir = dir; + openfilename.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; + openfilename.lpstrDefExt = ".mup"; + + if (GetOpenFileName(&openfilename)) { + return(path); + } + else { + return(0); + } + +#else + fl_file_chooser_ok_label("Open"); + return (fl_file_chooser("Open Mup file", "Mup files (*.mup)\tAll files (*)", "*.mup")); +#endif +} + + +// Ask user for name of file to save to, and return their choice + +const char * +File::save_as_ask_user(void) +{ +#ifdef OS_LIKE_WIN32 + OPENFILENAME openfilename; + static CHAR path[FL_PATH_MAX] = "*.mup"; + CHAR dir[FL_PATH_MAX]; + memset(&openfilename, 0, sizeof(openfilename)); + GetCurrentDirectory(sizeof(dir), dir); + openfilename.lStructSize = sizeof(openfilename); + parent_window_p->make_current(); + openfilename.hwndOwner = fl_window; + openfilename.hInstance = fl_display; + openfilename.lpstrFilter = "Mup files (*.mup)\0*.mup\0All files (*.*)\0*.*\0"; + openfilename.lpstrFile = path; + openfilename.nMaxFile = sizeof(path); + openfilename.lpstrInitialDir = dir; + openfilename.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; + openfilename.lpstrDefExt = ".mup"; + if (GetSaveFileName(&openfilename)) { + return(path); + } + else { + return(0); + } +#else + fl_file_chooser_ok_label("Save"); + return (fl_file_chooser("Save Mup file", "Mup files (*.mup)\tAll files (*)", "*.mup")); +#endif +} + + +//--------------------------------------------------------------------- +// The fl_choice function has the middle button as the default, +// but we want the left button (Yes) to be the default for whether +// to save before exiting, so we have a special class for it. +// It is based on the fl_choice code. + +Save_confirm_dialog::Save_confirm_dialog(const char * text) + : Fl_Double_Window(500, 130, "Confirm") +{ + // Make question mark "icon" + icon_p = new Fl_Box(10, 10, 50, 50); + icon_p->box(FL_THIN_UP_BOX); + icon_p->labelfont(FL_TIMES_BOLD); + icon_p->labelsize(30); + icon_p->color(FL_WHITE); + icon_p->labelcolor(FL_BLUE); + icon_p->label("?"); + + // Print the question + message_p = new Fl_Box(90, 20, 400, 40); + message_p->label(text); + message_p->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_WRAP); + + yes_p = new Fl_Return_Button(210, h() - 50, 70, 30, "Yes"); + + no_p = new Fl_Button(300, h() - 50, 70, 30, "No"); + + cancel_p = new Fl_Button(390, h() - 50, 70, 30, "Cancel"); + cancel_p->shortcut(FL_Escape); + show(); + + // Arrange for destructor to free new-ed widgets + end(); +} + +Save_confirm_dialog::~Save_confirm_dialog() +{ +} + + +// Method to bring up dialog to ask user if they want to save changes. +// Returns: +// Cancel don't do anything +// No do action without saving changes +// Yes save changes before doing action + +Save_confirm_dialog::Answer +Save_confirm_dialog::confirm_save(const char * text, bool hide_the_No) +{ + // Create dialog window + Save_confirm_dialog * confirm_p = new Save_confirm_dialog(text); + + // Only show desired buttons + if (hide_the_No) { + confirm_p->no_p->hide(); + } + + // Wait for user to select a button + Answer ret; + for ( ; ; ) { + Fl_Widget *widget_p = Fl::readqueue(); + if (widget_p == 0) { + Fl::wait(); + } + else if (widget_p == confirm_p->cancel_p || + widget_p == confirm_p) { + ret = Cancel; + break; + } + else if (widget_p == confirm_p->no_p) { + ret = No; + break; + } + else if (widget_p == confirm_p->yes_p) { + ret = Yes; + break; + } + } + + // Clean up the dialog window + confirm_p->hide(); + delete confirm_p; + + return ret; +} diff --git a/mup/mupmate/File.H b/mup/mupmate/File.H new file mode 100644 index 0000000..e39bb6d --- /dev/null +++ b/mup/mupmate/File.H @@ -0,0 +1,122 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _FILE_H_ +#define _FILE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class Main; + + +// Class used to ask user if they want to save changes. +// The FLTK fl_choice doesn't do quite what we want, so we make our own... + +class Save_confirm_dialog : Fl_Double_Window { +public: + enum Answer { Cancel, No, Yes }; + + // This brings up the dialog + static Answer confirm_save(const char * text, bool hide_the_No = false); + +private: + Save_confirm_dialog(const char * text); + ~Save_confirm_dialog(void); + + // Widgets + Fl_Box * icon_p; + Fl_Box * message_p; + Fl_Return_Button * yes_p; + Fl_Button * no_p; + Fl_Button * cancel_p; +}; + + + +// Class for the items off of "File" on the main menu bar + +class File { + +friend class Run; + +public: + File(); + ~File(); + + // Callbacks + static void modify_cb(int, int, int, int, const char *, void * data); + static void New_cb(Fl_Widget *, void * data); + static void NewFromTemplate_cb(Fl_Widget *, void * data); + static void Open_cb(Fl_Widget *, void * data); + static void Save_cb(Fl_Widget *, void * data); + static void SaveAs_cb(Fl_Widget *, void * data); + static void Exit_cb(Fl_Widget *, void * data); + + // Load a file into the text editor + void load_file(const char * name); + + // Give access to the text editor buffer + Fl_Text_Buffer * get_buffer() { return editor_p->buffer(); } + + // Gives real filename, or "Untitled.mup" if there is none + const char * effective_filename(); + + // This class needs access to Main class and its text editor. + // Creator should call these to point to the proper instances + void set_editor(Fl_Text_Editor * ed_p); + void set_parent(Main * main_p); + + // These show the dialog and return the file name the user enters. + const char * open_ask_user(void); + const char * save_as_ask_user(void); + + // Ask user if they want to save the currently unsaved changes. + Save_confirm_dialog::Answer save_changes_check(const char * extra_text = "", + bool hide_the_No = false); + +#ifndef OS_LIKE_WIN32 + // Make icon for Mup files. + static void add_mup_icon(void); +#endif + + +private: + // Callbacks + void New(void); + void Open(void); + void NewFromTemplate(void); + void Save(bool honor_auto_display = true); + void SaveAs(bool honor_auto_display = true); + void Exit(void); + + // Write out the current file + void save_file(bool honor_auto_display); + + // Put current file name in window label + void set_window_label(void); + + // Reset things for starting to edit a different file + void begin_new_file(void); + + // The name of file being edited + char * filename; + + // If buffer has changed since last being saved + bool unsaved_changes; + + // Pointers to other class instances we need + Fl_Text_Editor * editor_p; + Main * parent_window_p; +}; + +#endif diff --git a/mup/mupmate/Help.C b/mup/mupmate/Help.C new file mode 100644 index 0000000..59e8f87 --- /dev/null +++ b/mup/mupmate/Help.C @@ -0,0 +1,291 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +// Code for Help menu item from main toolbar + +#include "globals.H" +#include "Preferences.H" +#include "Config.H" +#include "Help.H" +#include +#include +#include + + +// Window for browsing Mup User's Guide + +Uguide_browser::Uguide_browser(void) + : Fl_Double_Window(0, 0, Default_width, Default_height, "Mup User's Guide") +{ + browser_p = new Fl_Help_View(x(), y(), w(), h(), ""); + // Set font/size and arrange to get notified of changes in them + font_change_reg_p = new Font_change_registration(font_change_cb, (void *) this); + + // Haven't loaded the User's Guide yet + loaded = false; + + // Allow browser window to be made as big as the user wants + size_range(Min_width, Min_height, 0, 0); + resizable((Fl_Widget *)browser_p); + + // Fix problem with following relative links properly. + browser_p->link(resolve_link); + + // Arrange for destructor to clean up new-ed widgets + end(); +} + + +Uguide_browser::~Uguide_browser(void) +{ + delete font_change_reg_p; + font_change_reg_p = 0; +} + + +// Load Mup User's Guide into browser, if haven't already done so. + +void +Uguide_browser::load_uguide(void) +{ + if (!loaded) { + // Entry under File Locations tells the base directory + // for Mup documentation. We concatenate the uguide/index.file + // to that directory to get top level file for User's Guide. + char * base_url; + (void) Preferences_p->get(Mup_documentation_location, base_url, + Default_Mup_documentation_location); + const char * url = users_guide_index_file(base_url); + + // Fltk has a bug (at least in some versions): + // the documentation claims load() + // returns -1 on failure, but in fact it always returns 0. + // So the strncmp attempts to deduce if it failed. + if (browser_p->load(url) != 0 || + strstr(browser_p->value(), "Mup User's Guide") + == 0) { + fl_alert("Unable to load User's Guide.\n %s\n" + "Check settings in Config > File Locations", url); + } + else { + loaded = true; + } + } +} + + +// Callback for when user changes font/size + +void +Uguide_browser::font_change_cb(void * data, Fl_Font font, unsigned char size) +{ + ((Uguide_browser *)data)->font_change(font, size); +} + +void +Uguide_browser::font_change(Fl_Font font, unsigned char size) +{ + browser_p->textfont(font); + browser_p->textsize(size); +} + +// On Windows, Fl_Help_View doesn't seem to properly follow relative +// URLs (it goes relative to current working directory rather than +// relative to the file containing the link), +// so we use the link() callback to prepend the proper directory. +// On Linux, things work fine without this kludge, but things also +// work with it, so to keep code common, we do it always. + +const char * +Uguide_browser::resolve_link(Fl_Widget * help_browser_p, const char * uri) +{ + static char link_path[FL_PATH_MAX]; + + if (strncmp(uri, "http:", 5) == 0) { + // Uguide has a few links to arkkra.com. + // They won't actually work, because we don't handle + // http, but it's better to let them through than to + // change the path and really confuse the user. + return(uri); + } + + char * base_url; + (void) Preferences_p->get(Mup_documentation_location, base_url, + Default_Mup_documentation_location); + (void) sprintf(link_path, "%s%c%s%c%s", base_url, dir_separator(), + uguide_directory, dir_separator(), + fl_filename_name(uri)); + return((const char *) link_path); +} + +//---- Hints for user when they use Mupmate for the first time +// (or they can ask to see it later too) + +const char * Welcome_message = + "Welcome to Mupmate. Mupmate provides an interface to the\n" + "Mup music publication program from Arkkra Enterprises,\n" + "making it easy to edit, display, and print musical scores.\n" + "\n" + "If you have not used Mup before, you should begin by selecting\n" + " Help > Mup User's Guide\n" + "for information on how to use Mup.\n" + "\n" + "You may also want to verify that the settings under\n" + " Config > File Locations and Config > Preferences\n" + "are what you want, and adjust them if you wish.\n" + "\n" + "You are welcome to try out Mup for free to decide whether\n" + "it meets your needs. If you decide to keep it, select\n" + " Config > Registration Form\n"; + +StartupHints::StartupHints(void) + : Fl_Double_Window(Default_width - 100, Default_height - 100, + "Mup Startup Hints") +{ + text_p = new Fl_Text_Display(20, 20, w() - 40, h() - 90); + resizable((Fl_Widget *) text_p); + text_p->buffer( new Fl_Text_Buffer () ); + font_change_reg_p = new Font_change_registration(font_change_cb, (void *) this); + text_p->buffer()->text(Welcome_message); + char * doc_dir; + (void) Preferences_p->get(Mup_documentation_location, doc_dir, + Default_Mup_documentation_location); + text_p->buffer()->append("\nAdditional documentation is available in the folder:\n "); + text_p->buffer()->append(doc_dir); + + OK_p = new Fl_Return_Button(w() / 2 - 50, h() - 50, 100, 30, + "OK"); + OK_p->callback(OK_cb, this); + show(); + end(); + + Preferences_p->set(Showed_startup_hints, 1); + Preferences_p->flush(); +} + +StartupHints::~StartupHints() +{ + delete font_change_reg_p; + font_change_reg_p = 0; +} + +// Callback for user clicking OK when done reading startup hints + +CALL_BACK(StartupHints, OK) +{ + hide(); +} + + +// Callback for when user changes font/size + +void +StartupHints::font_change_cb(void * data, Fl_Font font, unsigned char size) +{ + ((StartupHints *)data)->font_change(font, size); +} + +void +StartupHints::font_change(Fl_Font font, unsigned char size) +{ + text_p->textfont(font); + text_p->textsize(size); + text_p->redisplay_range(0, text_p->buffer()->length()); +} + +//-----the "About" window----------------------------------------------- + +About_dialog::About_dialog(void) + : Fl_Double_Window(270, 200, "About Mupmate") +{ + message_p = new Fl_Multiline_Output(20, 20, w() - 40, 120, ""); + message_p->value("\n Mupmate is a user interface\n" + " for the Mup music publisher\n" + " program from www.arkkra.com\n" + "\n" + " This is Version 5.3"); + // Hide the cursor by making same color as background + message_p->cursor_color(message_p->color()); + + ok_p = new Fl_Return_Button((w() - 100) / 2, 155, 100, 30, "OK"); + ok_p->callback(OK_cb, this); + + // Arrange for destructor to clean up new-ed widgets + end(); +} + +About_dialog::~About_dialog(void) +{ +} + + +CALL_BACK(About_dialog, OK) +{ + hide(); +} + +//------the Help menu item from main toolbar----------------------------- + +Help::Help(void) +{ + uguide_p = 0; + startup_hints_p = 0; + about_p = 0; +} + +Help::~Help(void) +{ + if (about_p != 0) { + delete about_p; + about_p = 0; + } + if (startup_hints_p != 0) { + delete startup_hints_p; + startup_hints_p = 0; + } + if (uguide_p != 0) { + delete uguide_p; + uguide_p = 0; + } +} + + +// Callback for when user requests viewing the Mup User's Guide + +CALL_BACK(Help, Uguide) +{ + if (uguide_p == 0) { + // first time, create widget + uguide_p = new Uguide_browser(); + } + // Always attempt to load in case URL was bad last time but okay now. + // If already loaded, this will be a no-op. + uguide_p->load_uguide(); + uguide_p->show(); +} + + +// Callback for when user clicks "Startup Hints" button + +CALL_BACK(Help, Startup_Hints) +{ + // We delete any existing instance and start over, + // just in case the path to the documentation has changed. + if (startup_hints_p != 0) { + delete startup_hints_p; + } + startup_hints_p = new StartupHints(); + startup_hints_p->show(); +} + + +// Callback for when user clicks "About" button + +CALL_BACK(Help, About) +{ + if (about_p == 0) { + // first time, create widget + about_p = new About_dialog(); + } + about_p->show(); +} diff --git a/mup/mupmate/Help.H b/mup/mupmate/Help.H new file mode 100644 index 0000000..bf92110 --- /dev/null +++ b/mup/mupmate/Help.H @@ -0,0 +1,113 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _HELP_H_ +#define _HELP_H_ + +// Classes for Help menu item off of main toolbar + +#include +#include +#include +#include +#include +#include +#include "Config.H" + + +// Class for window to let user browse the HTML version of Mup User's Guide + +class Uguide_browser : Fl_Double_Window { + +friend class Help; + +public: + Uguide_browser(void); + ~Uguide_browser(void); + + // User can change font/size preference. This callback notifies + // of such changes, so we can adjust the output accordingly + static void font_change_cb(void * data, Fl_Font font, unsigned char size); + + // Load the User's Guide top level index.html file + void load_uguide(void); + +private: + void font_change(Fl_Font font, unsigned char size); + + // On Windows, Fl_Help_View doesn't seem to properly follow relative + // URLs, so we use the link() callback to prepend the proper directory. + static const char * resolve_link(Fl_Widget *, const char * uri); + + Fl_Help_View *browser_p; + Font_change_registration * font_change_reg_p; + bool loaded; +}; + + +// Class to give first time user some hints. + +class StartupHints : Fl_Double_Window { + +friend class Help; + +public: + StartupHints(void); + ~StartupHints(void); + + static void OK_cb(Fl_Widget *, void * data); + // User can change font/size preference. This callback notifies + // of such changes, so we can adjust the output accordingly + static void font_change_cb(void * data, Fl_Font font, unsigned char size); +private: + void OK(void); + void font_change(Fl_Font font, unsigned char size); + + Font_change_registration * font_change_reg_p; + Fl_Text_Display * text_p; // The text of the hints + Fl_Return_Button * OK_p; +}; + + +// Class for "About" window + +class About_dialog : Fl_Double_Window { + +friend class Help; + +public: + About_dialog(void); + ~About_dialog(void); + + static void OK_cb(Fl_Widget *, void * data); + +private: + void OK(void); + + Fl_Multiline_Output * message_p; + Fl_Return_Button * ok_p; +}; + + +// Class for Help menu item from main toolbar + +class Help { +public: + Help(void); + ~Help(void); + + static void Uguide_cb(Fl_Widget *, void * data); + static void Startup_Hints_cb(Fl_Widget *, void * data); + static void About_cb(Fl_Widget *, void * data); + +private: + void Uguide(void); + void Startup_Hints(void); + void About(void); + + About_dialog * about_p; + StartupHints * startup_hints_p; + Uguide_browser * uguide_p; +}; + +#endif diff --git a/mup/mupmate/Main.C b/mup/mupmate/Main.C new file mode 100644 index 0000000..906f6d4 --- /dev/null +++ b/mup/mupmate/Main.C @@ -0,0 +1,724 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +// Code for the main window for Mupmate, a front end program for +// the Mup music publisher program from Arkkra Enterprises. +// It uses the FLTK toolkit for OS independence. + +// This file contains code for the toolbar and editor window, +// as well as general startup and showing the license. + +// We only support editing a single file at a time, so most classes +// as really effectively singletons, but the code is written to be +// able to support multiple instances, in case we ever want to do that. +// That means callback functions are always passed a pointer to +// a class instance as their second argument, and all they do is cast +// that to the appropriate type, and call the corresponding class method. + +// For the most part, widgets are only allocated when needed, but then +// stay around for the life of the process, in case they are needed again. + +// Callbacks are named with _cb suffix. +// Pointers are named with _p suffix, except for (char *) types +// that are pointing to text strings, which don't have any special suffix. + + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "globals.H" +#include "Main.H" +#include "Preferences.H" +#include "utils.H" + +#include +#ifdef OS_LIKE_WIN32 +#include "resource.h" +#else +#include +#ifdef OS_LIKE_UNIX +#include +#include "mup32.xpm" +#endif +#endif + +// Height of the tool bar on the main window +#define TOOLBAR_HEIGHT 30 + +// How often to blink the cursor. +#define BLINK_RATE 0.5 + +// If file indicating user has agreed to license terms doesn't exist, +// we ask them to agree. This is the text of the license. +extern const char * const license_text; + +//---------------------------------------------------------------------- + +// Define the toolbar and its submenus. +// Indented lines indicate the submenus. +// The & indicates shortcut key + +const char * File_label = "&File"; + const char * New_label = "&New"; + const char * NewFromTemplate_label = "New From &Template"; + const char * Open_label = "&Open..."; + const char * Save_label = "&Save"; + const char * SaveAs_label = "Save &As..."; + const char * Exit_label = "E&xit"; +const char * Edit_label = "&Edit"; + const char * Undo_label = "&Undo"; + const char * Cut_label = "Cu&t"; + const char * Copy_label = "&Copy"; + const char * Paste_label = "&Paste"; + const char * Delete_label = "&Delete"; + const char * Find_label = "&Find..."; + const char * FindNext_label = "Find &Next"; + const char * Replace_label = "&Replace..."; + const char * GoTo_label = "&Go To..."; + const char * SelectAll_label = "&Select All"; +const char * Run_label = "&Run"; + const char * Display_label = "&Display"; + const char * Play_label = "&Play"; + const char * WritePostScript_label = "&Write PostScript File"; + const char * WriteMIDI_label = "Write &MIDI File"; + const char * Options_label = "&Set Options..."; +const char * Config_label = "&Config"; + const char * FileLocations_label = "&File Locations..."; + const char * Preferences_label = "&Preferences..."; + const char * RegistrationForm_label = "&Registration Form..."; + const char * RegistrationKey_label = "Registration &Key..."; +const char * Help_label = "&Help"; + const char * UserGuide_label = "Mup &User's Guide"; + const char * StartupHints_label = "&Startup Hints"; + const char * AboutMupmate_label = "&About Mupmate"; + +Fl_Menu_Item Toolbar_menu[] = { + { File_label, 0, 0, 0, FL_SUBMENU }, + { New_label, FL_CTRL + 'n', File::New_cb }, + { NewFromTemplate_label, FL_CTRL + 't', File::NewFromTemplate_cb }, + { Open_label, FL_CTRL + 'o', File::Open_cb }, + { Save_label, FL_CTRL + 's', File::Save_cb }, + { SaveAs_label, 0, File::SaveAs_cb, 0, FL_MENU_DIVIDER }, + { Exit_label, 0, File::Exit_cb }, + { 0 }, + { Edit_label, 0, 0, 0, FL_SUBMENU }, + { Undo_label, FL_CTRL + 'z', Edit::Undo_cb, 0, FL_MENU_INACTIVE | FL_MENU_DIVIDER }, + { Cut_label, FL_CTRL + 'x', Edit::Cut_cb, 0, FL_MENU_INACTIVE }, + { Copy_label, FL_CTRL + 'c', Edit::Copy_cb, 0, FL_MENU_INACTIVE }, + { Paste_label, FL_CTRL + 'v', Edit::Paste_cb, 0, FL_MENU_INACTIVE }, + { Delete_label, FL_Delete, Edit::Delete_cb, 0, FL_MENU_INACTIVE | FL_MENU_DIVIDER }, + { Find_label, FL_CTRL + 'f', Edit::Find_cb, 0, FL_MENU_INACTIVE }, + { FindNext_label, FL_F + 3, Edit::FindNext_cb, 0, FL_MENU_INACTIVE }, + { Replace_label, FL_CTRL + 'h', Edit::Replace_cb, 0, FL_MENU_INACTIVE }, + { GoTo_label, FL_CTRL + 'g', Edit::GoTo_cb, 0, FL_MENU_DIVIDER }, + { SelectAll_label, FL_CTRL + 'a', Edit::SelectAll_cb, 0, FL_MENU_INACTIVE }, + { 0 }, + { Run_label, 0, 0, 0, FL_SUBMENU }, + { Display_label, 0, Run::Display_cb, 0, FL_MENU_INACTIVE }, + { Play_label, 0, Run::Play_cb, 0, FL_MENU_INACTIVE }, + { WritePostScript_label, 0, Run::WritePostScript_cb, 0, FL_MENU_INACTIVE }, + { WriteMIDI_label, 0, Run::WriteMIDI_cb, 0, FL_MENU_DIVIDER | FL_MENU_INACTIVE }, + { Options_label, 0, Run::Options_cb }, + { 0 }, + { Config_label, 0, 0, 0, FL_SUBMENU }, + { FileLocations_label, 0, Config::FileLocations_cb }, + { Preferences_label, 0, Config::Preferences_cb, 0, FL_MENU_DIVIDER }, + { RegistrationForm_label, 0, Config::RegistrationForm_cb }, + { RegistrationKey_label, 0, Config::RegistrationKey_cb }, + { 0 }, + { Help_label, 0, 0, 0, FL_SUBMENU }, + { UserGuide_label, 0, Help::Uguide_cb }, + { StartupHints_label, 0, Help::Startup_Hints_cb }, + { AboutMupmate_label, 0, Help::About_cb }, + { 0 }, + { 0 } +}; + + +//---------------------------------------------------------------------- + +// Linked list of main windows, in case we ever support more than one +// at a time. (Currently we don't, because we're not sure if it +// might be more confusing than useful.) +Main * Main::list_p; + + +// Constructor for main window. It contains toolbar and editor window. + +Main::Main(const char * title) + : Fl_Double_Window(Default_width, Default_height, title) +{ + xclass("mup"); +#ifdef OS_LIKE_WIN32 + icon((char *)LoadIcon(fl_display, MAKEINTRESOURCE(IDI_ICON))); +#else +#ifdef OS_LIKE_UNIX + fl_open_display(); + Pixmap p, mask; + XpmCreatePixmapFromData(fl_display, DefaultRootWindow(fl_display), + mup32_xpm, &p, &mask, NULL); + icon((char *)p); +#endif +#endif + // Try to use user's default foreground/background + Fl::get_system_colors(); + + void * data = 0; + + // Create class instances for each toolbar item + filemenu_p = new File(); + editmenu_p = new Edit(); + configmenu_p = new Config(); + helpmenu_p = new Help(); + runmenu_p = new Run(); + + // Add to list of windows + next = list_p; + list_p = this; + + // Create the toolbar and populate its menu items + toolbar_p = new Fl_Menu_Bar(0, 0, w(), TOOLBAR_HEIGHT); + int numitems = sizeof(Toolbar_menu) / sizeof(Toolbar_menu[0]); + for (int i = 0; i < numitems; i++) { + if (Toolbar_menu[i].text != 0) { + // As we move to each top-level menu item, + // keep a pointer to that item, which is then + // used as the argument to callback functions, + // so they know what object to act on. + if (strcmp(Toolbar_menu[i].text, File_label) == 0) { + data = (void *) filemenu_p; + } + else if (strcmp(Toolbar_menu[i].text, Edit_label) == 0) { + data = (void *) editmenu_p; + } + else if (strcmp(Toolbar_menu[i].text, Config_label) == 0) { + data = (void *) configmenu_p; + } + else if (strcmp(Toolbar_menu[i].text, Run_label) == 0) { + data = (void *) runmenu_p; + } + else if (strcmp(Toolbar_menu[i].text, Help_label) == 0) { + data = (void *) helpmenu_p; + } + } + Toolbar_menu[i].user_data(data); + } + toolbar_p->copy(Toolbar_menu); + + // Create and configure the editor window + editor_p = new Fl_Text_Editor(0, TOOLBAR_HEIGHT, w(), + h() - TOOLBAR_HEIGHT, ""); + editor_p->buffer( new Fl_Text_Buffer ); + + // Set font/size and arrange to be notified of changes in them + font_change_reg_p = new Font_change_registration(font_change_cb, + (void *) this); + + // Several objects need to be notified of changes in the + // editor window, so they can do things like gray-ungray menu items. + editor_p->buffer()->add_modify_callback(modify_cb, (void*) this); + editor_p->buffer()->add_modify_callback(File::modify_cb, + (void*) filemenu_p); + editor_p->buffer()->add_modify_callback(Edit::modify_cb, + (void*) editmenu_p); + + // Initialize state information. + have_selection = false; + can_paste = false; + prev_bufflength = 0; + // Undo is inactive until user does something that can be undone. + undo_active = false; + undo_active_on_next_change = true; + + // Arrange to make cursor blink + Fl::add_timeout(BLINK_RATE, blinker, this); + cursor_state = 1; + + // Let editor take as much space as is available + // if the user resizes the main window. + size_range(Min_width, Min_height, 0, 0); + resizable((Fl_Widget *) editor_p); + + // Other classes need to have access to editor and such + filemenu_p->set_editor(editor_p); + filemenu_p->set_parent(this); + editmenu_p->set_editor(editor_p); + runmenu_p->set_file(filemenu_p); + + // Arrange for destructor to free the new-ed child widgets + end(); + + show(); + + // Arrange for window manager closes to do Exit. + callback(atclose_cb, this); + when(FL_WHEN_NEVER); + +#ifdef OS_LIKE_UNIX + // Arrange for icon to be associated with window + XWMHints hints; + hints.flags = IconPixmapHint | IconMaskHint ; + hints.icon_pixmap = p; + hints.icon_mask = mask; + XSetWMHints(fl_display, fl_xid((Fl_Window *)this), &hints); +#endif +} + + +// Destructor for main window + +Main::~Main() +{ + delete font_change_reg_p; + font_change_reg_p = 0; + Fl::remove_timeout(blinker, this); + // Remove from list of Main windows + if (list_p == this) { + list_p = next; + } + else { + for (Main * m = list_p; m != 0; m = m->next) { + if (m->next == this) { + m->next = this->next; + break; + } + } + } + delete filemenu_p; + filemenu_p = 0; + delete editmenu_p; + editmenu_p = 0; + delete configmenu_p; + configmenu_p = 0; + delete helpmenu_p; + helpmenu_p = 0; + delete runmenu_p; + runmenu_p = 0; +} + + +// Callback for when user changes font/size + +void +Main::font_change_cb(void * data, Fl_Font font, unsigned char size) +{ + ((Main *)data)->font_change(font, size); +} + + +void +Main::font_change(Fl_Font font, unsigned char size) +{ + // Get shorter name for buffer, as we'll be using it a lot. + Fl_Text_Buffer * buffer_p = editor_p->buffer(); + + // Don't want this change to count as something that can be undone + buffer_p->canUndo(false); + + // We want to change the entire text buffer, so need to + // select its whole contents. If there was already a selection, + // save that and put it back when we are done + int sel_start, sel_end; + int had_selection; + int cursorplace = editor_p->insert_position(); + if ((had_selection = buffer_p->selected()) != 0) { + buffer_p->selection_position(&sel_start, &sel_end); + buffer_p->unselect(); + } + + // set new font and size + buffer_p->select(0, editor_p->buffer()->length() - 1); + editor_p->textfont(font); + editor_p->textsize(size); + buffer_p->unselect(); + + // Put selection and cursor back as they were before font change + if (had_selection) { + buffer_p->select(sel_start, sel_end); + } + editor_p->insert_position(cursorplace); + buffer_p->canUndo(true); +} + + +// Callback for when editor window changes. +// This arranges to gray/ungray toolbar menu items. + +void +Main::modify_cb(int, int, int, int, const char *, void * data) +{ + ((Main *)data)->modify(); +} + +void +Main::modify() +{ + int bufflength = editor_p->buffer()->length(); + // See if what changed is something we might care about. + if (editor_p->buffer()->selected() != have_selection || + editmenu_p->can_paste() != can_paste + || undo_active != undo_active_on_next_change + || bufflength < 2 || prev_bufflength == 0) { + + // Something changed, and we may need to + // gray or ungray menu items in response. + have_selection = editor_p->buffer()->selected(); + const Fl_Menu_Item * menu_p = toolbar_p->menu(); + Fl_Menu_Item * item_p; + // Walk through toolbar and submenus, checking + // if anything needs to be grayed/ungrayed. + for (int i = 0; i < toolbar_p->size(); i++) { + const char * mtext = toolbar_p->text(i); + if (mtext == 0) { + continue; + } + // Can only Copy, Cut, and Delete if something + // is selected. + if (strcmp(mtext, Copy_label) == 0 || + strcmp(mtext, Cut_label) == 0 || + strcmp(mtext, Delete_label) == 0) { + // have to un-const so we can (de)activate + item_p = (Fl_Menu_Item *) &(menu_p[i]); + if (have_selection) { + item_p->activate(); + } + else { + item_p->deactivate(); + } + } + + // Paste is different. It becomes active when there + // is something in clipboard, and never again becomes + // inactive. + if (strcmp(mtext, Paste_label) == 0 && + editmenu_p->can_paste()) { + ((Fl_Menu_Item *)&(menu_p[i]))->activate(); + can_paste = true; + } + + // Undo is also different. On first change of any + // kind it become active, and stays that way, + // except it gets reset on new file. + if (strcmp(mtext, Undo_label) == 0) { + if (undo_active && ! undo_active_on_next_change) { + ((Fl_Menu_Item *)&(menu_p[i]))->deactivate(); + undo_active = false; + undo_active_on_next_change = true; + } + else if ( ! undo_active && undo_active_on_next_change) { + ((Fl_Menu_Item *)&(menu_p[i]))->activate(); + undo_active = true; + } + } + + // Find and FindNext are inactive when file is empty, + // because obviously there is nothing to find. + // Similar for Replace and Select All. + // Also for all the Run things + if (strcmp(mtext, Find_label) == 0 || + strcmp(mtext, FindNext_label) == 0 || + strcmp(mtext, Replace_label) == 0 || + strcmp(mtext, SelectAll_label) == 0 || + strcmp(mtext, Display_label) == 0 || + strcmp(mtext, Play_label) == 0 || + strcmp(mtext, WritePostScript_label) == 0 || + strcmp(mtext, WriteMIDI_label) == 0) { + if (bufflength == 0) { + ((Fl_Menu_Item *)&(menu_p[i]))->deactivate(); + } + else { + ((Fl_Menu_Item *)&(menu_p[i]))->activate(); + } + } + } + } + prev_bufflength = bufflength; +} + + +// This method gets called when user starts working on a new file. +// It sets state information so we can know how to gray menu items properly. + +void +Main::begin_new_file() +{ + // transition Undo-ability state from true to false + undo_active = true; + undo_active_on_next_change = false; + editor_p->buffer()->call_modify_callbacks(); + runmenu_p->clean_up(); +} + + +// Handle some special cases. +// 1. By default fltk will exit the main window upon getting escape. +// That seems bad, since a vi user will be used to hitting escape all the +// time when editing, because that is always a "safe" thing to do, +// and if they did it here by mistake, they would lose all +// their text entry since the last save. So we ignore the escape in this window. +// I suppose we could ask if they really want to quit... +// 2. If user does cut or copy via keyboard accelerator, the normal code +// for ungraying the Paste button doesn't get called, so we catch that case +// here and ungray it. + +int +Main::handle_events(int e) +{ + // If escape is received while on main window, + // return 1 to show that we consumed the event. + if (e == FL_SHORTCUT && Fl::event_key() == FL_Escape) { + for (Main * m_p = list_p; m_p != 0; m_p = m_p->next) { + if (Fl::first_window() == m_p) { + return(1); + } + } + } + + // If user did cut or copy via cntl-c or cntl-x, + // arrange to ungray Paste. + if (e == FL_KEYUP && (Fl::event_state() & FL_CTRL) && + (Fl::event_key() == 'v' || Fl::event_key() == 'x')) { + for (Main * m_p = list_p; m_p != 0; m_p = m_p->next) { + if (Fl::first_window() == m_p) { + m_p->editmenu_p->set_can_paste(); + break; + } + } + } + + return(0); +} + + +// If user tries to close the main window via the window manager +// while having unsaved changes, we ask user if they want to save +// the changes first. + +CALL_BACK(Main, atclose) +{ + File::Exit_cb(0, filemenu_p); +} + + +// Blink the cursor. It can be hard to see if next to selected text if not +// blinking. We could potentially optimize to only do this while +// the window has focus, but it doesn't seem worth the complication... + +void +Main::blinker(void * data) +{ + Main * obj_p = (Main *) data; + // Put cursor into opposite of its current state + obj_p->cursor_state ^= 1; + obj_p->editor_p->show_cursor(obj_p->cursor_state); + // Reset timer to call ourselves again. + Fl::repeat_timeout(BLINK_RATE, blinker, data); +} + + +// Give user hints if we haven't already done that before. + +void +Main::hints(void) +{ + int did_startup; + (void) Preferences_p->get(Showed_startup_hints, did_startup, + Default_startup_hints_flag); + if ( ! did_startup) { + Help::Startup_Hints_cb(0, (void *) helpmenu_p); + } +} + +//---------------------------------------------------------------------- + +int +main(int argc, char **argv, const char **arge) +{ + // The arge value may get changed when we set new environment + // variables, so look up PATH first thing. + get_path(arge); + + // Uguide browser needs to show images + fl_register_images(); + +#ifndef OS_LIKE_WIN32 + // On Windows we use the native Open/Save As dialogs. + // On other platforms we use FLTK's, but add icon for Mup files. + Fl_File_Icon::load_system_icons(); + File::add_mup_icon(); +#endif + + // Try to get best hardware support for graphics + Fl::visual(FL_DOUBLE|FL_INDEX); + + // Get the user's preferences that persists across sessions + Preferences_p = new Fl_Preferences(Fl_Preferences::USER, + "arkkra.com", "mupmate"); + + // Enable tips when user hovers their mouse over a widget. + // If user doesn't like them, they can set delay to huge value. + Fl_Tooltip::enable(); + double tooltips_delay; + (void) Preferences_p->get(Tooltips_delay_preference, tooltips_delay, + Default_tooltips_delay); + Fl_Tooltip::delay(tooltips_delay); + + // Set $MUPPATH + char * val; + (void) Preferences_p->get(MUPPATH_location, val, + Default_MUPPATH_location); + set_muppath(val); + + // Tell Mup that it is being run via mupmate, + // so it can give more appropriate error messages. + putenv("MUPMATE=1"); + + // Create main window + Main *main_p = new Main("Mupmate"); + + // Ensure "escape" key doesn't kill main window, + // and make sure Paste ungraying works + Fl::add_handler(Main::handle_events); + + // Try to find some reasonable defaults for configuration items + // that aren't already set. + deduce_helper_locations(); + + // If magic file indicating license agreement isn't there, + // ask user to agree to Mup license. + if (access(magic_file(argv[0]), F_OK) != 0) { + // Show the license and get agreement before continuing + new License(main_p, magic_file(argv[0])); + } + else { + // Display the main window. + main_p->show(1, argv); + + // The first time, we show user some hints. + main_p->hints(); + } + + // Go to where user said they want to store their Mup files by default. + // Need to wait to do this until after we have deduced locations + // of executable, in case they were in current directory. + char * mup_dir; + (void) Preferences_p->get(Music_files_location, mup_dir, + Default_music_files_location); + if (strcmp(mup_dir, ".") != 0) { + if (chdir(mup_dir) != 0) { + char curr_dir[FL_PATH_MAX] = "current"; + char message[2 * FL_PATH_MAX + 100]; + (void *) getcwd(curr_dir, sizeof(curr_dir)); + sprintf(message, "Unable to change to folder\n" + "\"%s.\"\nStaying in \"%s\" folder.\n" + "Fix setting of \"Folder for Mup Files\"\n" + "in Config->File Locations.", + mup_dir, curr_dir); + fl_alert(message); + } + } + + // Expect 0 or 1 args. If 1, should be name of file to load + if (argc > 1) { + main_p->filemenu_p->load_file(argv[1]); + } + if (argc > 2) { + fl_alert("Only expecting one file; extra arguments are being ignored."); + } + + // Go into main event-handler loop + int exitvalue = Fl::run(); + Main::clean_exit(exitvalue); + /*NOTREACHED*/ + return(exitvalue); +} + + +// Clean up all the windows and their children and exit. + +void +Main::clean_exit(int exitval) +{ + Main * m_p; + Main * nextwin_p; + + for (m_p = list_p; m_p != 0; m_p = nextwin_p) { + nextwin_p = m_p->next; + delete m_p; + } + exit(exitval); +} + +//---------- class to show Mup license and get user's agreement + + +License::License(Main *m_p, const char * magic) + : Fl_Double_Window(Default_width, Default_height, "Mup License") +{ + // save passed-in info in object data + main_p = m_p; + magic_file_name = magic; + + // widget for displaying the license text + text_p = new Fl_Text_Display(20, 20, w() - 40, h() - 90); + resizable((Fl_Widget *) text_p); + text_p->buffer( new Fl_Text_Buffer () ); + text_p->textsize(18); + text_p->buffer()->text(license_text); + + i_agree_p = new Fl_Return_Button(100, h() - 50, 100, 30, "I Agree"); + i_agree_p->callback(IAgree_cb, this); + + cancel_p = new Fl_Button(w() - 200, h() - 50, 100, 30, "Cancel"); + cancel_p->callback(Cancel_cb, this); + cancel_p->shortcut(FL_Escape); + + show(); + + // Arrange for destructor to free the new-ed child widgets + end(); + + // Arrange for window manager closes to do Cancel. + callback(Cancel_cb, this); + when(FL_WHEN_NEVER); +} + + +License::~License() +{ +} + + +// Callback for when user clicks that they agree to the license. + +CALL_BACK(License, IAgree) +{ + // Create the magic file + int fd; + if ((fd = open(magic_file_name, O_WRONLY | O_CREAT, 0644)) < 0) { + fl_alert("Unable to create file indicating license agreement."); + } + else { + close(fd); + } + + hide(); + + // Bring up the normal main window + main_p->show(); + main_p->hints(); +} + +// Callback if user refuses to accept license. We just exit if they refuse. + +CALL_BACK(License, Cancel) +{ + exit(0); +} diff --git a/mup/mupmate/Main.H b/mup/mupmate/Main.H new file mode 100644 index 0000000..fc1e6f9 --- /dev/null +++ b/mup/mupmate/Main.H @@ -0,0 +1,133 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _MAIN_H_ +#define _MAIN_H_ + +// Header file for the main Mupmate window, containing toolbar and editor. + +#include +#include +#include +#include +#include +#include + +#include "File.H" +#include "Edit.H" +#include "Run.H" +#include "Config.H" +#include "Help.H" + +class Main; + +//---------- class to show Mup license and get user's agreement + +class License : public Fl_Double_Window { +public: + License(Main * m_p, const char * magic); + ~License(void); + + // Callbacks + static void IAgree_cb(Fl_Widget *, void * data); + static void Cancel_cb(Fl_Widget *, void * data); + static void Continue_cb(Fl_Widget *, void * data); + +private: + // Callbacks + void IAgree(void); + void Cancel(void); + void Continue(void); + + // Widgets + Fl_Text_Display * text_p; // The text of the license + Fl_Return_Button * i_agree_p; + Fl_Button * cancel_p; + + // Name of file that tells us if user has agreed to license + const char * magic_file_name; + + // The main window + Main * main_p; +}; + + + +// Class for main window, with editor and toolbar + +class Main : public Fl_Double_Window { + +friend class License; + +public: + Main(const char * title); + ~Main(); + + // Callbacks + static void modify_cb(int, int, int, int, const char *, void * data); + static void font_change_cb(void * data, Fl_Font font, unsigned char size); + static void atclose_cb(Fl_Widget *, void * data); + + // We don't want Escape to cause main window to close, + // and need to handle Paste ungraying specially. + // This event handler takes care of those things. + static int handle_events(int); + + // Show user hints the first time they bring up Mupmate + void hints(void); + + // Reset state information when user opens a new file. + void begin_new_file(); + + // Pointers to the classes for each toolbar menu item widgets + File * filemenu_p; + Edit * editmenu_p; + Config * configmenu_p; + Help * helpmenu_p; + Run * runmenu_p; + + // Clean up all windows + static void clean_exit(int exitval = 0); + +private: + // called when input text is modified + void modify(void); + + // Sets font/size of editor + void font_change(Fl_Font font, unsigned char size); + + // Make window manager close like Exit + void atclose(void); + + // Cursor blinker + static void blinker(void *); + + // Ponters to the top level widgets + Fl_Menu_Bar * toolbar_p; + Fl_Text_Editor * editor_p; + + // For font/size change notification + Font_change_registration * font_change_reg_p; + + // True if there is a selected area in editor window + bool have_selection; + + // True if something in clipboard + bool can_paste; + + // For knowing when to gray out Undo menu item + bool undo_active; + bool undo_active_on_next_change; + int prev_bufflength; + + // Current cursor on/off state, for blinker + int cursor_state; + + // We currently only have one main window, but code is + // general to allow multiple windows. We keep a linked list + // of all the windows. + static Main * list_p; + Main * next; +}; + +#endif diff --git a/mup/mupmate/Preferences.C b/mup/mupmate/Preferences.C new file mode 100644 index 0000000..23aba11 --- /dev/null +++ b/mup/mupmate/Preferences.C @@ -0,0 +1,317 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +// This file contains code for defining and using things +// related to user configuration settings and preferences. + +#include +#include +#include +#include "globals.H" +#include "utils.H" +#include "Preferences.H" +#include + +// Access to the user preferences file +Fl_Preferences * Preferences_p; + +// Preference names and default values +const char * const Editor_font_preference = "editor_font"; +const char * const Default_editor_font = "Courier"; + +const char * const Editor_size_preference = "editor_size"; +const char * const Default_editor_size = "12"; + +const char * const Auto_display_preference = "auto_display"; +const int Default_auto_display = 0; + +const char * const Auto_save_preference = "auto_save"; +const int Default_auto_save = 1; + +const char * const Tooltips_delay_preference = "tooltips_delay"; +const double Default_tooltips_delay = 1.0; + +const char * const Mup_program_location = "Mup_program"; +const char * const Default_Mup_program_location = "mup"; + +const char * const Mup_documentation_location = "Mup_documentation"; +#if defined(__WIN32) +const char * const Default_Mup_documentation_location = "c:\\Program Files\\mupmate"; +#else +const char * const Default_Mup_documentation_location = "/usr/share/doc/packages/mup"; +#endif + +const char * const Music_files_location = "Music_folder"; +const char * const Default_music_files_location = "."; + +const char * const MUPPATH_location = "MUPPATH"; +const char * const Default_MUPPATH_location = "."; + +const char * const Viewer_location = "Viewer"; +#if defined(__WIN32) +const char * const Default_viewer_location = "c:\\Program Files\\Ghostgum\\gsview\\gsview32.exe"; +#else +const char * const Default_viewer_location = "gv"; +#endif + +const char * const MIDI_player_location = "MIDI_player"; +#if defined(__WIN32) +const char * const Default_MIDI_player_location = "c:\\Program Files\\Windows Media Player\\wmplayer.exe"; +#else +const char * const Default_MIDI_player_location = "xplaymidi"; +#endif + +const char * const Showed_startup_hints = "showed_startup_hints"; +const int Default_startup_hints_flag = 0; + +// Name of User's Guide directory and index file +// relative to Mup documentation directory. +const char * uguide_directory = "uguide"; +#ifdef OS_LIKE_WIN32 +const char * uguide_filename = "index.htm"; +#else +const char * uguide_filename = "index.html"; +#endif + +// Don't use un-readable tiny font, but especially avoid size of zero, +// which could happen if preferences file contains a bad number, so that +// atoi() returns zero. Keep max small enough to fit reasonable number +// of characters in a window. +const unsigned char Min_size = 5; +const unsigned char Max_size = 30; + +// Minimum and default sizes for Main and Help browser windows. +const int Min_width = 600; +const int Default_width = 720; +const int Min_height = 400; +const int Default_height = 480; + + +// If user hasn't specified any program yet to use for PostScript viewer +// and/or MIDI file player, we try to deduce what they have available +// that could be used, and set one of those as the default. + +// List of likely programs to use as PostScript viewers +static const char * const viewer_candidates[] = { +#if defined(__WIN32) + "GSview32", + "GSview", +#else +#ifdef OS_LIKE_UNIX + "gv", + "ghostview", +#endif +#endif + 0 +}; + +// List of likely programs to use as MIDI file players +static const char * const player_candidates[] = { +#if defined(__WIN32) + "wmplayer", + "mplayer", +#else +#ifdef OS_LIKE_UNIX + "xplaymidi", + "timidity", + "pmidi", + "playmidi", +#endif +#endif + 0 +}; + + +// If the default preference value for a program location is no good, +// try to find where it is. +// pgm_location = the preference name of the program of interest +// default_location = the default path to the program +// file_suffix = .ps or .mod or .mup +// Returns true if the preference value was updated. + +static bool +deduce_location(const char * pgm_location, const char * default_location, + const char * file_suffix, const char * const * candidates) +{ + char * place; // a path to try for finding the pgm + char location[FL_PATH_MAX]; // full path to pgm when it is found + + if (Preferences_p->get(pgm_location, place, default_location) != 0) { + // There was a value already set. Make sure it is good. + if (find_executable(place, location)) { + if (strcmp(place, location) != 0) { + // Must have started as relative path + // and now we know the full path. + (void) Preferences_p->set(pgm_location, location); + return(true); + } + else { + // Existing setting was okay as is. + return(false); + } + } + } + +#ifdef OS_LIKE_WIN32 + // Try looking in the registry for what to use for + // files of this type. + if ((place = lookup_pgm_for_file_suffix(file_suffix)) != 0) { + (void) Preferences_p->set(place, default_location); + return(true); + } +#endif + + // If there had been nothing set, see if the default location is good. + if (find_executable(default_location, location)) { + (void) Preferences_p->set(pgm_location, location); + return(true); + } + + // Try looking in the various educated guess locations. + if (candidates != 0) { + int i; + for (i = 0; candidates[i] != 0; i++) { + if (find_executable(candidates[i], location)) { + (void) Preferences_p->set(pgm_location, location); + return(true); + } + } + } + + return(false); +} + + +// Returns true is the Mup User's Guide can be found at the given location. + +static bool +doc_found(const char * location) +{ + return(access(users_guide_index_file(location), F_OK) == 0); +} + + +// Try to deduce where the Mup documentation is. +// Returns true if updated the Preferences to point to new location. + +static bool +deduce_documentation_location(const char * doc_location, const char * default_doc_location) +{ + char * place; + // First try the stored location, if any + if (Preferences_p->get(doc_location, place, default_doc_location) != 0) { + if (doc_found(place)) { + // Existing preference is good. No update needed. + return(false); + } + } + + // Try default location + if (doc_found(default_doc_location)) { + Preferences_p->set(doc_location, default_doc_location); + return(true); + } + + // Try relative to where Mup executable is. + char *muploc; + (void) Preferences_p->get(Mup_program_location, muploc, + Default_Mup_program_location); + char * basename_p; + if ((basename_p = strrchr(muploc, dir_separator())) != 0) { + int len = basename_p - muploc; + char mupdir[len + 1]; + (void) strncpy(mupdir, muploc, len); + mupdir[len] = '\0'; + if (doc_found(mupdir)) { + Preferences_p->set(doc_location, mupdir); + return(true); + } + + // Try at ../docs from where mup executable was, + // since it could be there from unpacking tar file. + char * parentdir_p; + if ((parentdir_p = strrchr(mupdir, dir_separator())) != 0) { + len = parentdir_p - mupdir + 1; + // Add room for doc and terminator + char mupdocdir[len + 5]; + (void) strncpy(mupdocdir, muploc, len); + (void) strcpy(mupdocdir + len, "docs"); + if (doc_found(mupdocdir)) { + Preferences_p->set(doc_location, mupdocdir); + return(true); + } + } + } + return(false); +} + + +// This function attempts to find the locations of what we need, +// like a PostScript viewer and MIDI player. + +void +deduce_helper_locations(void) +{ + bool updated = false; + + // First try to find a PostScript viewer + if (deduce_location(Viewer_location, Default_viewer_location, ".ps", + viewer_candidates)) { + updated = true; + } + + // Next do MIDI player + if (deduce_location(MIDI_player_location, Default_MIDI_player_location, + ".mid", player_candidates)) { + updated = true; + } + + // Find the Mup command itself + if (deduce_location(Mup_program_location, Default_Mup_program_location, ".mup", 0)) { + updated = true; + } + + if (deduce_documentation_location(Mup_documentation_location, + Default_Mup_documentation_location)) { + updated = true; + } + +#ifdef OS_LIKE_WIN32 + // Try to guess a good default place for Mup input files. + char * place; + if (Preferences_p->get(Music_files_location, place, + Default_music_files_location) == 0) { + if ((place = find_music_folder()) != 0) { + Preferences_p->set(Music_files_location, place); + updated = true; + } + } + // The same place is probably a good guess for Mup include files. + if (Preferences_p->get(MUPPATH_location, place, + Default_MUPPATH_location) == 0) { + if ((place = find_music_folder()) != 0) { + Preferences_p->set(MUPPATH_location, place); + updated = true; + } + } +#endif + + // If at least one better choice was found, update the persistent data. + if (updated) { + Preferences_p->flush(); + } +} + + +// Given a path to Mup's documentation directory, +// add on the name of the User's Guide index file. +// Return that in a static area. + +const char * +users_guide_index_file(const char * const doc_dir) +{ + static char file_path[FL_PATH_MAX]; + (void) sprintf(file_path, "%s%c%s%c%s", doc_dir, dir_separator(), + uguide_directory, dir_separator(), uguide_filename); + return((const char *) file_path); +} diff --git a/mup/mupmate/Preferences.H b/mup/mupmate/Preferences.H new file mode 100644 index 0000000..374f574 --- /dev/null +++ b/mup/mupmate/Preferences.H @@ -0,0 +1,64 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _PREFERENCES_H_ +#define _PREFERENCES_H_ + +// This file contains things related to user configuration options +// and preferences. + +#include + +// Names and default values for things stored in preferences file +extern const char * const Mup_program_location; +extern const char * const Mup_documentation_location; +extern const char * const Music_files_location; +extern const char * const MUPPATH_location; +extern const char * const Viewer_location; +extern const char * const MIDI_player_location; +extern const char * const Editor_font_preference; +extern const char * const Editor_size_preference; +extern const char * const Auto_display_preference; +extern const char * const Auto_save_preference; +extern const char * const Tooltips_delay_preference; +extern const char * const Showed_startup_hints; + +extern const char * const Default_Mup_program_location; +extern const char * const Default_Mup_documentation_location; +extern const char * const Default_music_files_location; +extern const char * const Default_MUPPATH_location; +extern const char * const Default_viewer_location; +extern const char * const Default_MIDI_player_location; +extern const char * const Default_editor_font; +extern const char * const Default_editor_size; +extern const int Default_auto_display; +extern const int Default_auto_save; +extern const double Default_tooltips_delay; +extern const int Default_startup_hints_flag; + +// This lets us access user preferences that persist across sessions +extern Fl_Preferences * Preferences_p; + +// Minimum and maximum font size we use +extern const unsigned char Min_size; +extern const unsigned char Max_size; + +// Default and minimum sizes of Main and Help browser windows +extern const int Min_width; +extern const int Default_width; +extern const int Min_height; +extern const int Default_height; + +// The directory containing User's Guide, relative to top of +// documentation tree +extern const char * uguide_directory; + +// Given a path to Mup's documentation directory, +// add on the name of the User's Guide index file. +// Return that in a static area. +extern const char * users_guide_index_file(const char * const doc_dir); + +// This tries to find reasonable default applications for viewing and playing +extern void deduce_helper_locations(void); + +#endif diff --git a/mup/mupmate/Run.C b/mup/mupmate/Run.C new file mode 100644 index 0000000..de95228 --- /dev/null +++ b/mup/mupmate/Run.C @@ -0,0 +1,1371 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +// This file includes methods related to the "Run" menu on the main toolbar. + +#include "Run.H" +#include "Preferences.H" +#include "globals.H" +#include "Config.H" +#include "defines.h" +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef OS_LIKE_UNIX +#include +#include +#endif + +// Message for when Mup fails, but we can't figure out why. +const char * Unknown_Mup_failure = "Mup failed. Reason unknown."; + +// Describe use of numbers passed to -x option +#define EXTRACT_NUM_DESCRIPTION "0 is used for pickup measure.\n" \ + "Negative numbers are used to specify\n" \ + "number of measures from the end.\n" + +// Tooltip is the same for all macro entries +const char * macro_definition_tip = + "Your Mup input can use macros to vary characteristics\n" + "of the output for different runs.\n" + "Enter the name of a macro you want to define,\n" + "optionally followed by an equals sign and macro definition.\n" + "Macro names must consist of upper case letters,\n" + "numbers, and underscores, starting with an upper case letter."; + +//------ Class for user to set parameters to pass to Mup + +Run_parameters_dialog::Run_parameters_dialog(void) + : Fl_Double_Window(0, 0, 700, 350, "Mup Options") +{ + enable_combine_p = new Fl_Check_Button(20, 20, 165, 30, + "Enable Auto Multirest"); + enable_combine_p->tooltip("Set whether to automatically combine\n" + "consecutive measures of rests into a multirest."); + enable_combine_p->callback(combine_cb, this); + enable_combine_p->when(FL_WHEN_CHANGED); + + rest_combine_p = new Positive_Int_Input(370, 20, 40, 30, + "Min Measures to Combine"); + rest_combine_p->tooltip("Minimum number of consecutive measures\n" + "of rest that will be combined into a multirest."); + // Only becomes active if auto-multirest combine becomes active + rest_combine_p->deactivate(); + + // -p firstpage + first_page_p = new Positive_Int_Input(300, 60, 50, 30, "First Page's Page Number"); + first_page_p->tooltip("Set the page number to use\n" + "for the first page of music output."); + + // -o pagelist + pages_p = new Fl_Group(30, 100, 380, 70, "Pages to Display"); + pages_p->box(FL_ENGRAVED_BOX); + pages_p->align(FL_ALIGN_TOP_LEFT | FL_ALIGN_INSIDE); + + all_p = new Fl_Check_Button(170, 105, 55, 20, "All"); + all_p->type(FL_RADIO_BUTTON); + all_p->tooltip("You can restrict to displaying only a subset\n" + "of the pages of music, but this shows all pages."); + all_p->callback(selected_pages_cb, this); + all_p->when(FL_WHEN_CHANGED); + + odd_p = new Fl_Check_Button(245, 105, 60, 20, "Odd"); + odd_p->type(FL_RADIO_BUTTON); + odd_p->tooltip("This restricts to displaying only\n" + "odd numbered pages. This is generally\n" + "most useful for printing to a\n" + "single-sided printer."); + odd_p->callback(selected_pages_cb, this); + odd_p->when(FL_WHEN_CHANGED); + + even_p = new Fl_Check_Button(320, 105, 70, 20, "Even"); + even_p->type(FL_RADIO_BUTTON); + even_p->tooltip("This restricts to displaying only\n" + "even numbered pages. This is generally\n" + "most useful for printing to a\n" + "single-sided printer."); + even_p->callback(selected_pages_cb, this); + even_p->when(FL_WHEN_CHANGED); + + selected_p = new Fl_Check_Button(50, 135, 85, 20, "Selected:"); + selected_p->tooltip("This restricts to displaying only\n" + "the pages you list in the blank to the right."); + selected_p->type(FL_RADIO_BUTTON); + selected_p->callback(selected_pages_cb, this); + selected_p->when(FL_WHEN_CHANGED); + + page_list_p = new Fl_Input(150, 130, 230, 30, ""); + page_list_p->tooltip("List the specific pages you want displayed.\n" + "You can list individual pages separated by commas,\n" + "and/or ranges of pages separated by dashes.\n" + "Pages may be listed more than once and in any order."); + page_list_p->deactivate(); + saved_page_list = 0; + pages_p->end(); + + // -s stafflist + staff_list_p = new Fl_Input(150, 180, 260, 30, "Staffs to Display/Play"); + staff_list_p->tooltip("If you wish to display or play only a subset\n" + "of the staffs, or voices on a staff, list them here.\n" + "Staffs are specified by comma-separated numbers\n" + "or ranges, like 1,4 or 1-3,5-6. Staff numbers can be\n" + "followed by v1, v2, or v3 to limit to a single voice.\n"); + saved_staff_list = 0; + + // -x extract list + extract_begin_p = new Int_Input(150, 220, 95, 30, "Extract Measures"); + extract_begin_p->tooltip("If you wish to display or play only selected\n" + "measures, enter the starting measure here.\n" + EXTRACT_NUM_DESCRIPTION); + extract_begin_p->callback(extract_cb, this); + extract_begin_p->when(FL_WHEN_CHANGED); + extract_end_p = new Int_Input(315, 220, 95, 30, "through"); + extract_end_p->tooltip("If you wish to display or play only selected\n" + "measures, enter the ending measure here.\n" + EXTRACT_NUM_DESCRIPTION); + extract_end_p->deactivate(); + + // Macros + macros_group_p = new Fl_Group(430, 20, 250, 40 + MAX_MACROS * 40, "Macro Definitions"); + macros_group_p->box(FL_ENGRAVED_BOX); + macros_group_p->align(FL_ALIGN_TOP | FL_ALIGN_INSIDE); + int m; + for (m = 0; m < MAX_MACROS; m++) { + + macro_definitions_p[m] = new Fl_Input(450, 50 + m * 40, 210, 30, ""); + macro_definitions_p[m]->tooltip(macro_definition_tip); + + saved_macro_definitions[m] = 0; + } + macros_group_p->end(); + + save_p = new Fl_Return_Button(100, h() - 50, 80, 30, "Save"); + save_p->callback(Save_cb, this); + save_p->when(FL_WHEN_RELEASE); + + clear_form_p = new Fl_Button((w() - 150) / 2, h() - 50, 150, 30, + "Clear Options"); + clear_form_p->callback(clear_form_cb, this); + clear_form_p->when(FL_WHEN_RELEASE); + + cancel_p = new Fl_Button(w() - 180, h() - 50, 80, 30, "Cancel"); + cancel_p->shortcut(FL_Escape); + cancel_p->callback(Cancel_cb, this); + cancel_p->when(FL_WHEN_RELEASE); + + // Set everything to default values + clear_form(); + + // Arrange to clean up all the new-ed widgets in destructor. + end(); + + // Arrange for window manager closes to do Cancel. + callback(Cancel_cb, this); + when(FL_WHEN_NEVER); +} + + +Run_parameters_dialog::~Run_parameters_dialog(void) +{ + int m; + for (m = 0; m < MAX_MACROS; m++) { + if (saved_macro_definitions[m] != 0) { + delete saved_macro_definitions[m]; + } + } +} + + +//---- Callback for when user changes enablement of rest combining, +// to gray or ungray the field for how many measures to combine. + +CALL_BACK(Run_parameters_dialog, combine) +{ + if (enable_combine_p->value()) { + rest_combine_p->activate(); + } + else { + rest_combine_p->value(""); + rest_combine_p->deactivate(); + } +} + + +//---- Callback for when user changes setting of start of measure extraction, +// to gray or ungray the field for ending measure of extraction. + +CALL_BACK(Run_parameters_dialog, extract) +{ + if (extract_begin_p->size() > 0) { + extract_end_p->activate(); + } + else { + extract_end_p->value(""); + extract_end_p->deactivate(); + } +} + +//---- Callback for when user changes setting of page selection, +// to gray or ungray the field for listing the specific pages to display + +CALL_BACK(Run_parameters_dialog, selected_pages) +{ + page_list_p->value(""); + if (selected_p->value() == 1) { + page_list_p->activate(); + } + else { + page_list_p->deactivate(); + } +} + + +//----Callback for button for clearing the form + +CALL_BACK(Run_parameters_dialog, clear_form) +{ + // Set everything to default values + saved_enable_combine = false; + enable_combine_p->value(saved_enable_combine); + + (void) sprintf(saved_combine_measures, ""); + rest_combine_p->value(saved_combine_measures); + + (void) sprintf(saved_first_page, "%d", MINFIRSTPAGE); + first_page_p->value(saved_first_page); + + if (saved_page_list != 0) { + delete saved_page_list; + } + saved_page_list = new char[1]; + saved_page_list[0] = '\0'; + page_list_p->value(saved_page_list); + all_p->value(1); + saved_pages = ALL_PAGES; + + if (saved_staff_list != 0) { + delete saved_staff_list; + } + saved_staff_list = new char[1]; + saved_staff_list[0] = '\0'; + staff_list_p->value(saved_staff_list); + + saved_extract_begin[0] = '\0'; + extract_begin_p->value(saved_extract_begin); + saved_extract_end[0] = '\0'; + extract_end_p->value(saved_extract_end); + + int m; + for (m = 0; m < MAX_MACROS; m++) { + macro_definitions_p[m]->value(""); + if (saved_macro_definitions[m] != 0) { + delete saved_macro_definitions[m]; + saved_macro_definitions[m] = 0; + } + } +} + + +//---- callback for when user clicks "Save" on Set Options form + +CALL_BACK(Run_parameters_dialog, Save) +{ + // -c rest combine option + bool error = false; + saved_enable_combine = enable_combine_p->value(); + int num_meas = (int) atoi(rest_combine_p->value()); + if (saved_enable_combine && (num_meas < MINRESTCOMBINE || num_meas > MAXRESTCOMBINE)) { + fl_alert("\"Min Measures to Combine\" must be between\n" + "%d and %d.", MINRESTCOMBINE, MAXRESTCOMBINE); + error = true; + } + else { + (void) strcpy(saved_combine_measures, rest_combine_p->value()); + } + + // -p first page option + int page_num = (int) atoi(first_page_p->value()); + if (page_num < MINFIRSTPAGE || page_num > MAXFIRSTPAGE) { + fl_alert("\"First Page\" number must be between\n" + "%d and %d.", MINFIRSTPAGE, MAXFIRSTPAGE); + error = true; + } + else { + (void) strcpy(saved_first_page, first_page_p->value()); + } + + // We don't really fully parse and error check the -o argument, + // but make sure it at least is made up of only valid characters. + if (page_list_p->size() > 0) { + if (strspn(page_list_p->value(), "0123456789,- \t") + != page_list_p->size()) { + fl_alert("\"Pages to Display\" value is not valid."); + error = true; + } + else { + // Free existing, if any, and save new value. + if (saved_page_list != 0) { + delete saved_page_list; + } + saved_page_list = new char[page_list_p->size() + 1]; + strcpy(saved_page_list, page_list_p->value()); + } + } + else if (saved_page_list[0] != '\0') { + // Had a list before but not anymore. + // Null out the existing list. + delete saved_page_list; + saved_page_list = new char[1]; + saved_page_list[0] = '\0'; + } + if (all_p->value() == 1) { + saved_pages = ALL_PAGES; + } + if (odd_p->value() == 1) { + saved_pages = ODD_PAGES; + } + if (even_p->value() == 1) { + saved_pages = EVEN_PAGES; + } + if (selected_p->value() == 1) { + saved_pages = SELECTED_PAGES; + } + if (saved_pages == SELECTED_PAGES && page_list_p->size() == 0) { + fl_alert("You did not list which selected pages you want."); + error = true; + } + + // Similar for staff list (-s option) + if (staff_list_p->size() > 0) { + if (strspn(staff_list_p->value(), "0123456789,-v \t") + != staff_list_p->size()) { + fl_alert("\"Staffs to Display/Play\" is not valid"); + error = true; + } + else { + if (saved_staff_list != 0) { + delete saved_staff_list; + } + saved_staff_list = new char[staff_list_p->size() + 1]; + strcpy(saved_staff_list, staff_list_p->value()); + } + } + else if (saved_staff_list[0] != '\0') { + delete saved_staff_list; + saved_staff_list = new char[1]; + saved_staff_list[0] = '\0'; + } + + // We can't really error check -x option values. + // Widget will have already constrained to integer, + // and we have no way to know what range is valid, + // since we don't know how many measures the song has. + // However, to keep things simple, we have fixed-size array of 8 bytes + // for saving value, so can only allow up to 6 digits plus sign. + if (abs(atoi(extract_begin_p->value())) >= 1000000) { + fl_alert("\"Extract Measures\" start value is out of range."); + error = true; + } + else { + (void) strcpy(saved_extract_begin, extract_begin_p->value()); + } + if (abs(atoi(extract_end_p->value())) >= 1000000) { + fl_alert("\"Extract Measures\" end value is out of range."); + error = true; + } + else { + (void) strcpy(saved_extract_end, extract_end_p->value()); + } + + // Macros + int m; + int macsize; + bool changed; + for (m = 0; m < MAX_MACROS; m++) { + changed = false; + if ((macsize = macro_definitions_p[m]->size()) > 0) { + if (macro_error(macro_definitions_p[m]->value())) { + fl_alert("Macro %d has invalid format.", m + 1); + error = true; + } + else if (saved_macro_definitions[m] == 0) { + // no macro before, but is one now + changed = true; + } + else if (strcmp(macro_definitions_p[m]->value(), + saved_macro_definitions[m]) != 0) { + // A different macro value than before + delete saved_macro_definitions[m]; + changed = true; + } + if (changed) { + saved_macro_definitions[m] = new char[macsize + 1]; + (void) strcpy(saved_macro_definitions[m], + macro_definitions_p[m]->value()); + } + } + else if (macsize == 0 && saved_macro_definitions[m] != 0) { + // Used to be a macro value, but not anymore + delete saved_macro_definitions[m]; + saved_macro_definitions[m] = 0; + } + } + + + // If there were user errors, we leave the window up for user to + // correct the errors. User can, of course, cancel without correcting, + // in which case if they try to run, Mup will complain about the + // bad arguments. + if ( ! error ) { + hide(); + } +} + + +//---- Callback for when user clicks "Cancel" on Set Options form + +CALL_BACK(Run_parameters_dialog, Cancel) +{ + // Put back all the previous values + enable_combine_p->value(saved_enable_combine); + rest_combine_p->value(saved_combine_measures); + first_page_p->value(saved_first_page); + + // It seems setting a radio button via value(1) doesn't reset the + // others, so clear all, then set the one we want + all_p->value(0); + odd_p->value(0); + even_p->value(0); + selected_p->value(0); + switch (saved_pages) { + default: // default should be impossible + case ALL_PAGES: + all_p->value(1); + break; + case ODD_PAGES: + odd_p->value(1); + break; + case EVEN_PAGES: + even_p->value(1); + break; + case SELECTED_PAGES: + selected_p->value(1); + break; + } + page_list_p->value(saved_page_list); + staff_list_p->value(saved_staff_list); + extract_begin_p->value(saved_extract_begin); + extract_end_p->value(saved_extract_end); + + int m; + for (m = 0; m < MAX_MACROS; m++) { + macro_definitions_p[m]->value( saved_macro_definitions[m] == 0 + ? "" : saved_macro_definitions[m]); + } + hide(); +} + +// Return true if check of macro finds an error. + +bool +Run_parameters_dialog::macro_error(const char * macro) +{ + // First character must be an upper case letter. + if ( ! isupper(macro[0])) { + return(true); + } + // Everything up to = or end of string, whichever comes first, + // must be upper case letter, digit, or underscore. + const char * m_p; + for (m_p = macro; *m_p != '\0' && *m_p != '='; m_p++) { + if ( ! isupper(*m_p) && ! isdigit(*m_p) && *m_p != '_') { + return(true); + } + } + return(false); +} + + +//--------class for Run menu ----------------------------------------------- + +Run::Run() +{ + parameters_p = 0; + report_p = 0; +#ifdef OS_LIKE_WIN32 + display_child.hProcess = 0; + display_child.dwProcessId = 0; + MIDI_child.hProcess = 0; + MIDI_child.dwProcessId = 0; +#else + display_child = 0; + MIDI_child = 0; +#endif +} + +Run::~Run() +{ + if (parameters_p != 0) { + delete parameters_p; + parameters_p = 0; + } + if (report_p != 0) { + delete report_p; + report_p = 0; + } + // Kill off any child processes + clean_up(); +} + + + +//------------callback for Display menu item + +CALL_BACK(Run, Display) +{ + Run_Mup(false, true); +} + + +//-----Callback for menu item to play MIDI file + +CALL_BACK(Run, Play) +{ + Run_Mup(true, true); +} + + +//---------callback for menu item for writing PostScript output + +CALL_BACK(Run, WritePostScript) +{ + Run_Mup(false, false); +} + +//---------callback for menu item for writing MIDI output + +CALL_BACK(Run, WriteMIDI) +{ + Run_Mup(true, false); +} + +//---- callback for menu item to collect Mup command line parameters from user + +CALL_BACK(Run, Options) +{ + if (parameters_p == 0) { + parameters_p = new Run_parameters_dialog(); + } + parameters_p->show(); +} + + +//--------- This lets Run class know the file name and editor buffer, +// which it needs access to, so it can run Mup on its contents. + +void +Run::set_file(File * file_info_p) +{ + file_p = file_info_p; +} + + +// Run Mup commands with user's parameters on the current file + +void +Run::Run_Mup(bool midi, bool show_or_play) +{ + + const char * mup_input = file_p->effective_filename(); + // Make sure file has been written. + // The fiilename == 0 will be hit in the case where + // user did New From Template but made no changes. + if (file_p->unsaved_changes || file_p->filename == 0) { + int auto_save; + (void) Preferences_p->get(Auto_save_preference, auto_save, + Default_auto_save); + if (auto_save) { + file_p->Save(false); + if (file_p->unsaved_changes || file_p->filename == 0) { + // User probably canceled a Save that got + // turned into a SaveAs, + // or maybe Save failed. If not properly + // saved, we shouldn't try to process it. + return; + } + } + else { + bool hide_the_No; + const char * extra_text; + // If there is a previous version of the file, + // allow user to select "No," which means use that + // previous version rather than writing out current. + if (access(mup_input, F_OK) == 0) { + hide_the_No = false; + extra_text = "(If you select \"No,\" " + "the most recently saved version " + "of the Mup input file will be used.)"; + } + else { + // No previous version + hide_the_No = true; + extra_text = ""; + } + switch (file_p->save_changes_check(extra_text, hide_the_No)) { + default: // default case should be impossible + case Save_confirm_dialog::Cancel: + return; + case Save_confirm_dialog::No: + break; + case Save_confirm_dialog::Yes: + file_p->Save(false); + if (file_p->unsaved_changes + || file_p->filename == 0) { + // User probably canceled the Save, + // or maybe it failed. If not properly + // saved, we shouldn't try to process it. + return; + } + break; + } + } + // If was "Untitled" before, it is now saved under a good + // name, so get what that is. + mup_input = file_p->effective_filename(); + } + + // Get length of file name without the extension + int base_length = strlen(mup_input) + - strlen(fl_filename_ext(mup_input)); + + // Create output file name + char mup_output[base_length + (midi ? 5 : 4)]; + strncpy(mup_output, mup_input, base_length); + strcpy(mup_output + base_length, (midi ? ".mid" : ".ps")); + + // Create error file name + char mup_error[base_length + 5]; + strncpy(mup_error, mup_input, base_length); + strcpy(mup_error + base_length, ".err"); + + // Get Mup command to use. + char * mup_command; + (void) Preferences_p->get(Mup_program_location, mup_command, + Default_Mup_program_location); + char full_location[FL_PATH_MAX]; + if ( ! find_executable(mup_command, full_location)) { + fl_alert("Mup command not found.\n" + "Check Config > File Locations setting."); + return; + } + + if (parameters_p == 0) { + // User hasn't set any parameters, so we will use all + // defaults. Creating the instance lets us deference it + // below, so we don't have to care whether user ever + // went to the Set Options page or not. + parameters_p = new Run_parameters_dialog(); + } + + // Build up list of arguments. + // array slots needed for args: + // 1 for Mup command itself + // 2 for -e and arg + // 2 for -f or -m and arg + // 2 for -c and arg + // 2 for -p and arg + // 2 for -o and arg + // 2 for -s and arg + // 2 for -x and arg + // 1 for Mup input file name + // 2 for each -D and its macro definition arg + // 1 for null terminator + const char * command[17 + 2 * MAX_MACROS]; + command[0] = full_location; + command[1] = "-e"; + command[2] = mup_error; + command[3] = (midi ? "-m" : "-f"); + command[4] = mup_output; + int arg_offset = 5; + + // rest combine + if (parameters_p->enable_combine_p->value() && + parameters_p->rest_combine_p->size() > 0) { + command[arg_offset++] = "-c"; + command[arg_offset++] = parameters_p->rest_combine_p->value(); + } + + // first page + if (parameters_p->first_page_p->size() > 0) { + command[arg_offset++] = "-p"; + command[arg_offset++] = parameters_p->first_page_p->value(); + } + + // page list + switch (parameters_p->saved_pages) { + default: // default should be impossible + case Run_parameters_dialog::ALL_PAGES: + break; + case Run_parameters_dialog::ODD_PAGES: + command[arg_offset++] = "-o"; + command[arg_offset++] = "odd"; + break; + case Run_parameters_dialog::EVEN_PAGES: + command[arg_offset++] = "-o"; + command[arg_offset++] = "even"; + case Run_parameters_dialog::SELECTED_PAGES: + if (parameters_p->page_list_p->size() > 0) { + command[arg_offset++] = "-o"; + command[arg_offset++] = parameters_p->page_list_p->value(); + } + // Else they said selected, but then didn't list + // any particular pages. We treat like ALL_PAGES, + // since no pages is useless. + // We would have already given error message, + // but they must have ignored it. + break; + } + + // staff list + if (parameters_p->staff_list_p->size() > 0) { + command[arg_offset++] = "-s"; + command[arg_offset++] = parameters_p->staff_list_p->value(); + } + + // extract list + char xoption[parameters_p->extract_begin_p->size() + + parameters_p->extract_end_p->size() + 2]; + if (parameters_p->extract_begin_p->size() > 0) { + command[arg_offset++] = "-x"; + (void) strcpy(xoption, parameters_p->extract_begin_p->value()); + if (parameters_p->extract_end_p->size() > 0) { + (void) strcat(xoption, ","); + (void) strcat(xoption, parameters_p->extract_end_p->value()); + } + command[arg_offset++] = xoption; + } + + // -D options + int m; + for (m = 0; m < MAX_MACROS; m++) { + if (parameters_p->saved_macro_definitions[m] != 0) { + command[arg_offset++] = "-D"; + command[arg_offset++] = parameters_p->saved_macro_definitions[m]; + } + } + + // Mup input file name and null terminator + command[arg_offset++] = mup_input; + command[arg_offset++] = 0; + + static bool set_mupquiet = false; + if ( ! set_mupquiet ) { + putenv("MUPQUIET=1"); + set_mupquiet = true; + } + + // Look up the right (dis)player program to use. + // On Windows we need this even if we are only writing the file, + // not actually (dis)playing. To keep the code simpler, + // we just always look it up. + char * player_command; + if (midi) { + (void) Preferences_p->get(MIDI_player_location, + player_command, + Default_MIDI_player_location); + } + else { + (void) Preferences_p->get(Viewer_location, + player_command, + Default_viewer_location); + } +#ifdef OS_LIKE_WIN32 + // Media player locks the file it plays, so if we had + // run it before, we have to make it release the lock + // before we run Mup. Also, if it was playing a different file + // before, it doesn't seem to want to play ours. + // So if the MIDI player of choice is the media player, + // we first try to make it close somewhat gracefully, + // and wait a second for that to complete. + // In any case we try to kill off any child MIDI players we + // know of. If the graceful close already worked, + // it should find the child already dead. + // If they are using some other MIDI player, + // we don't know what to do, so we'll just kill any child + // MIDI player we know spawned previously, if any. + // Would be nice to be able to do something less drastic than + // kill the process, but we're not sure what else would be effective. + if (midi) { + if (is_mplayer(player_command)) { + HWND window_handle; + if ((window_handle = FindWindow(0, "Windows Media Player")) != 0) { + SendMessage(window_handle, WM_CLOSE, 0, 0); + } + _sleep(1000); + } + if (has_MIDI_child()) { + kill_process(&MIDI_child, "MIDI player"); + } + } + // Somewhat similarly, we kill off any prior displayer, unless + // the displayer is GSview, which we know we can pass -e argument + // to make it reuse existing instance, if any. + else if ( ! is_gsview(player_command) && has_display_child()) { + kill_process(&display_child, "display"); + } +#endif + + // Run the command. + int ret = execute_command(command, 0, true); + + // Report the errors, if any. + struct stat info; + if (stat(mup_error, &info) == 0) { + if (info.st_size > 0) { + if (report_p == 0) { + report_p = new Error_report(); + } + report_p->loadfile(mup_error); + report_p->show(); + } + unlink(mup_error); + } + else if (ret != 0) { + // Exited with error, but left no error file. + // Must have died badly (core dumped, execvp failed, etc) +#if defined(WIFEXITED) && defined(WIFSIGNALED) + if (WIFEXITED(ret)) { + // Did exit(), so most likely exec failed + // due to bad path to Mup program, + // although we should have caught that above. + fl_alert("Mup exited with return code %d but no error output.\n" + "Check Config > File Locations setting.", + WEXITSTATUS(ret)); + } + else if (WIFSIGNALED(ret)) { + // Probably core dump :-( + fl_alert("Mup exited due to signal %d.", WTERMSIG(ret)); + } else { + fl_alert(Unknown_Mup_failure); + } +#else // WIF... macros not defined + if (ret == -1) { +#ifdef OS_LIKE_WIN32 + // Look up the error reason to include in message. + DWORD format_retval; + LPVOID error_string = 0; + if (FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ARGUMENT_ARRAY, + 0, GetLastError(), + LANG_NEUTRAL, (LPTSTR)&error_string, + 0, 0)) { + fl_alert("Failed to execute Mup program:\n%s" + "Check settings in Config > File Locations.", + (char *) error_string); + LocalFree((HLOCAL)error_string); + } + else { + fl_alert(Unknown_Mup_failure); + } + } +#else // not Windows + fl_alert(Unknown_Mup_failure); + } +#endif + else { + fl_alert(Unknown_Mup_failure); + } +#endif // WIF... macros + } + + if (ret != 0) { + // Something went wrong. We should not go on to + // display/play even if user had asked for that. + return; + } + + // We wrote the output file successfully. + // Hide any previous error window and + // check if we need to (dis)play the results. + if (report_p != 0) { + report_p->hide(); + } + if ( ! show_or_play ) { + // User just asked to generate a file, not (dis)play it. + fl_message("%s output file\n\n %s\n\n" + "has been successfully created.", + (midi ? "MIDI" : "PostScript"), mup_output); + return; + } + + + if ( ! find_executable(player_command, full_location)) { + fl_alert("Unable to run %s command.\n" + "Check Config > File Locations setting.", + player_command); + return; + } + +#ifdef OS_LIKE_UNIX + // For MIDI, we try to kill the previous player + // if any, since we'll probably need the same + // sound card. Note that for Windows, we did this + // even before running Mup, since the player may lock + // the file so Mup would be unable to write it. + if (midi) { + kill_process(&MIDI_child, "MIDI player"); + } + + // If using gv as displayer and one already running on + // this file, it would be nice to get send it SIGHUP + // to make it re-read the file + // rather than starting a new one. + // But for other displayers, we don't know what signal + // might work, if any. And even with gv, if we send + // the signal, we have no way of knowing whether it + // actually worked. And there are lots of cases to + // consider. Suppose the displayer was gv, + // and they brought up an instance, + // then they changed to some other displayer, + // and then back to gv. Should we have killed off + // the first gv when bringing up the other viewer, + // of should we keep it up and reuse it after they + // change back? What if they kill the current + // instance just after we decided to re-use it? + // So just keep things simple for now. Always + // kill off any existing viewer we know of and + // start up a new one. + else { // displaying + kill_process(&display_child, "display"); + } +#endif + + // Fill in the argv array for displayer/player + command[0] = full_location; +#ifdef OS_LIKE_WIN32 + // Media player appears to ignore its argument + // if it isn't a full path name, including drive. + // So ensure we have everything. + char fullpath[FL_PATH_MAX]; + if (mup_output[1] != ':' ) { + // We don't have complete path. + // Get current directory including drive. + if (getcwd(fullpath, sizeof(fullpath)) == 0) { + fl_alert("Unable to determine current folder."); + return; + } + if (mup_output[0] != dir_separator()) { + // Relative path + (void) sprintf(fullpath + strlen(fullpath), + "%c%s", dir_separator(), + mup_output); + } + else { + // Was full path except for drive. + (void) strcpy(fullpath + 2, mup_output); + } + } + else { + // Can use existing path as is. + (void) strcpy(fullpath, mup_output); + } + + if ( ! midi && is_gsview(player_command)) { + // For gsview, use -e to make it use + // existing instance if any. + command[1] = "-e"; + command[2] = fullpath; + command[3] = '\0'; + } + else { + command[1] = fullpath; + command[2] = '\0'; + + } +#else + command[1] = mup_output; + command[2] = '\0'; +#endif + + if (execute_command(command, + (midi ? &MIDI_child : &display_child)) != 0) { + fl_alert("Unable to run %s command.\n" + "Check settings under Config > File Locations.", + command[0]); + } +} + + +// Execute given command with the given argv. +// If proc_info_p is zero, wait for the process to complete, +// otherwise save information about the spawned process in what it points to, +// so that the caller can keep track of it while it runs independently. +// The hide_window parameter is only used for Windows and causes the +// spawned process to be created with flags to not create a window, +// This lets us use a console mode version of Mup, so traditional users +// can continue to run Mup in a console without mupmate, but we can +// run the same .exe without the annoyance of a console popping up. +// Returns 0 on success, -1 on failure to create process, +// or what the process returned if it had non-zero exit code, +// and was waited for. + +int +Run::execute_command(const char ** argv, Proc_Info *proc_info_p, bool hide_window) +{ + int ret = -1; + +#ifdef OS_LIKE_UNIX + pid_t child; + switch (child = fork()) { + case 0: + execvp(argv[0], (char * const *)argv); + // If here, the exec failed. Child must die. + exit(1); + case -1: + // failed + if (proc_info_p != 0) { + *proc_info_p = 0; + } + break; + default: + if (proc_info_p == 0) { + // wait for child to complete + if (waitpid(child, &ret, 0) < 0) { + ret = -1; + } + } + else { + *proc_info_p = child; + ret = 0; + } + break; + } +#else + +#ifdef OS_LIKE_WIN32 + + // Convert the argv array into a string with each argument quoted. + // First calculate how much space is needed. + int a; + int length = 0; + bool has_quote = false; // to optimize normal case + for (a = 0; argv[a] != 0; a++) { + length += strlen(argv[a]); + // A quoted argv[0] won't work; just quote the other args. + if (a > 0) { + // Add space before the arg and quotes on each end. + length += 3; + const char * s; + // If embedded quote, add space for escaping it + for (s = argv[a]; *s != '\0'; s++) { + if (*s == '"') { + length++; + has_quote = true; + } + } + } + } + + // Get space and fill in all the arguments, properly quoted. + char command[length + 1]; + (void) strcpy(command, argv[0]); + char * dest = command + strlen(command); + for (a = 1; argv[a] != 0; a++) { + *dest++ = ' '; + *dest++ = '"'; + if (has_quote) { + int i; + for (i = 0; argv[a][i] != '\0'; i++) { + if (argv[a][i] == '"') { + *dest++ = '\\'; + } + *dest++ = argv[a][i]; + } + } + else { + (void) strcpy(dest, argv[a]); + dest += strlen(dest); + } + *dest++ = '"'; + } + *dest = '\0'; + + // Fill in information for starting up the process + PROCESS_INFORMATION process_info; + STARTUPINFO startup_info; + memset( &startup_info, 0, sizeof(startup_info)); + startup_info.cb = sizeof(startup_info); + DWORD create_flags; // flags to control creation aspects + if (hide_window) { + startup_info.dwFlags = STARTF_USESHOWWINDOW; + startup_info.wShowWindow = SW_HIDE; + create_flags = CREATE_NO_WINDOW; + } + else { + create_flags = 0; + } + + // Run the process + BOOL proc = CreateProcess(NULL, command, NULL, NULL, + TRUE, create_flags, NULL, NULL, + &startup_info, &process_info); + + if (proc) { + // It was successfully created. + if (proc_info_p == 0) { + // wait for child to complete + DWORD result = WaitForSingleObject( + process_info.hProcess, INFINITE); + switch (result) { + case WAIT_FAILED: + case WAIT_ABANDONED: + case WAIT_TIMEOUT: + ret = -1; + break; + default: + GetExitCodeProcess(process_info.hProcess, &result); + ret = (int) result; + } + } + else { + *proc_info_p = process_info; + ret = 0; + } + } + else { + proc_info_p->hProcess = 0; + proc_info_p->dwProcessId = 0; + ret = -1; + } + +#else + fl_alert("Process execution only implemented\n" + "for Linux (and similar) and Windows so far..."); + ret = -1; +#endif + +#endif + return(ret); +} + + +// Kill the specified process, if it exists. +// The description is used in error messages + +void +Run::kill_process(const Proc_Info * const proc_info_p, const char * const description) +{ +#ifdef OS_LIKE_UNIX + int exitstatus; + if (*proc_info_p == 0 || waitpid(*proc_info_p, &exitstatus, WNOHANG) + == *proc_info_p) { + // No process spawned or the one we had already died + return; + } + // Not clear how hard to try to kill process. + // SIGTERM should usually work, and is preferable if it works. + // We wait a little while and try SIGKILL if it hasn't died yet. + // We don't check for errors, because the + // only errors that should be possible are bad signal (should be + // impossible, since we hard-code SIGTERM), process doesn't exist + // (already dead, so no need to kill it), or bad permission (we + // spawned it ourself, so ought to have permission to kill it). + (void) kill(*proc_info_p, SIGTERM); + // Wait for up to 3 seconds for it to die + int w; + int ret; + for (w = 0; w < 3; w++) { + if ((ret = waitpid(*proc_info_p, &exitstatus, WNOHANG)) + == *proc_info_p) { + // It died. + // *** Especially in the case of MIDI, there is a + // chance the player has already written stuff out + // to the device driver that it won't clear out when + // it dies, so that if we try to start a new one, + // the device will still be busy. But we have no way + // to know how long to wait, if at all, and don't + // want to always sleep a long time just to cover + // the case of trying to play again while in the middle + // of playing. + return; + } + if (ret == -1 && errno == ECHILD) { + // Child doesn't exist, so nothing to kill + return; + } + sleep(1); + } + // Okay. Resort to SIGKILL and wait 1 more second to let it die. + kill(*proc_info_p, SIGKILL); + sleep(1); +#endif +#ifdef OS_LIKE_WIN32 + if (proc_info_p->hProcess == 0 || WaitForSingleObject( + proc_info_p->hProcess, 0) != WAIT_TIMEOUT) { + // No process spawned or the one we had must have already died. + return; + } + HANDLE handle; + if ( (handle = OpenProcess(PROCESS_TERMINATE, + FALSE, proc_info_p->dwProcessId)) == 0 || + TerminateProcess(handle, 0) == 0) { + // Warn user we were unable to kill the old child. + DWORD format_retval; + LPVOID error_string = 0; + if (FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER + | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ARGUMENT_ARRAY, + 0, GetLastError(), + LANG_NEUTRAL, (LPTSTR)&error_string, + 0, 0)) { + fl_alert("Unable to terminate %s process.\n%s", + description, (char *) error_string); + LocalFree((HLOCAL)error_string); + } + } + if (handle != 0) { + CloseHandle(handle); + } +#endif +} + + +#ifdef OS_LIKE_WIN32 +// Return true if the given command is for Windows Media Player. + +bool +Run::is_mplayer(const char * command) +{ + int length = strlen(command); + if (strcasecmp(command + length - 12, "wmplayer.exe") == 0 || + strcasecmp(command + length - 11, "mplayer.exe") == 0 || + strcasecmp(command + length - 8, "wmplayer") == 0 || + strcasecmp(command + length - 7, "mplayer") == 0) { + return(true); + } + return(false); +} + + +// Return true if the given command is for GSview. + +bool +Run::is_gsview(const char * command) +{ + int length = strlen(command); + if (strcasecmp(command + length - 12, "gsview32.exe") == 0 || + strcasecmp(command + length - 10, "gsview.exe") == 0 || + strcasecmp(command + length - 8, "gsview32") == 0 || + strcasecmp(command + length - 6, "gsview") == 0) { + return(true); + } + return(false); +} +#endif + + +// Called when user begins a new file, or when exiting, +// to kill off child proceses that were spawned. +// We start new processes for new file, +// even if one already up for current file. +// Not sure if that's what user wants, but... + +void +Run::clean_up(void) +{ + kill_process(&display_child, "display"); + kill_process(&MIDI_child, "MIDI player"); +} + + +// Report whether we spawned a display child and think it is still alive. + +bool +Run::has_display_child(void) +{ +#ifdef OS_LIKE_WIN32 + return(display_child.hProcess != 0); +#else + return(display_child != 0); +#endif +} + + +// Report whether we spawned a MIDI child and think it is still alive. + +bool +Run::has_MIDI_child(void) +{ +#ifdef OS_LIKE_WIN32 + return(MIDI_child.hProcess != 0); +#else + return(MIDI_child != 0); +#endif +} + + +//------------ Class for displaying errors from Mup + +Error_report::Error_report(void) + : Fl_Double_Window(Default_width, Default_height, "Error report") +{ + text_p = new Fl_Text_Display(20, 20, w() - 40, h() - 90); + resizable((Fl_Widget *) text_p); + text_p->buffer( new Fl_Text_Buffer() ); + + // Set font/size and arrange to get notified of changes in them + font_change_reg_p = new Font_change_registration( + font_change_cb, (void *) this); + + ok_p = new Fl_Return_Button(w() / 2 - 40, h() - 50, 80, 30, "OK"); + ok_p->callback(OK_cb, this); + show(); + + // Arrange to clean up new-ed widgets in destructor. + end(); +} + +Error_report::~Error_report() +{ +} + + +// Load the error file (from -e of Mup) into window to show user. + +int +Error_report::loadfile(const char * filename) +{ + return text_p->buffer()->loadfile(filename); +} + + +// Callback for when user clicks OK after reading Mup error report + +CALL_BACK(Error_report, OK) +{ + hide(); +} + + +// Callback for change in font/size + +void +Error_report::font_change_cb(void * data, Fl_Font font, unsigned char size) +{ + ((Error_report *)data)->font_change(font, size); +} + +void +Error_report::font_change(Fl_Font font, unsigned char size) +{ + text_p->textfont(font); + text_p->textsize(size); + text_p->redisplay_range(0, text_p->buffer()->length()); +} diff --git a/mup/mupmate/Run.H b/mup/mupmate/Run.H new file mode 100644 index 0000000..9e6356e --- /dev/null +++ b/mup/mupmate/Run.H @@ -0,0 +1,209 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _RUN_H_ +#define _RUN_H_ + +// Classes for Run menu off of main toolbar + +#include +#include +#include +#include +#include +#include +#include +#include +#include "globals.H" +#include "File.H" +#include "Config.H" +#include +#include +#ifdef OS_LIKE_UNIX +#include +#endif +#ifdef OS_LIKE_WIN32 +#include +#include +#include +#include +#endif + +// Information about a non-waited-for process +#ifdef OS_LIKE_WIN32 +typedef PROCESS_INFORMATION Proc_Info; +#else +typedef pid_t Proc_Info; +#endif + +// We limit the number of macros user can define, +// to fit in a reasonably small dialog window. +#define MAX_MACROS 5 + + +// Class for asking user what arguments to pass to Mup when running it + +class Run_parameters_dialog : Fl_Double_Window { + +friend class Run; + +public: + Run_parameters_dialog(void); + ~Run_parameters_dialog(void); + + // Callbacks + static void combine_cb(Fl_Widget *, void * data); + static void extract_cb(Fl_Widget *, void * data); + static void selected_pages_cb(Fl_Widget *, void * data); + static void clear_form_cb(Fl_Widget *, void * data); + static void Macros_cb(Fl_Widget *, void * data); + static void Save_cb(Fl_Widget *, void * data); + static void Cancel_cb(Fl_Widget *, void * data); + + // Returns true if macro definition is invalid. + static bool macro_error(const char * macro); + +private: + // Callbacks + void combine(void); + void extract(void); + void selected_pages(void); + void clear_form(void); + void Macros(void); + void Save(void); + void Cancel(void); + + // Widgets + Fl_Check_Button * enable_combine_p; + Positive_Int_Input * rest_combine_p; + Positive_Int_Input * first_page_p; + Fl_Group * pages_p; + Fl_Check_Button * all_p; + Fl_Check_Button * odd_p; + Fl_Check_Button * even_p; + Fl_Check_Button * selected_p; + Fl_Input * page_list_p; + Fl_Input * staff_list_p; + Int_Input * extract_begin_p; + Int_Input * extract_end_p; + Fl_Group * macros_group_p; + Fl_Input * macro_definitions_p[MAX_MACROS]; + Fl_Return_Button * save_p; + Fl_Button * clear_form_p; + Fl_Button * cancel_p; + + // Saved values for run parameters + bool saved_enable_combine; + char saved_combine_measures[8]; + char saved_first_page[8]; + enum { ALL_PAGES, ODD_PAGES, EVEN_PAGES, SELECTED_PAGES } saved_pages; + char * saved_page_list; + char * saved_staff_list; + char saved_extract_begin[8]; + char saved_extract_end[8]; + char * saved_macro_definitions[MAX_MACROS]; +}; + + +// Class for displaying stderr output from Mup to user + +class Error_report : public Fl_Double_Window +{ +public: + Error_report(void); + ~Error_report(void); + + // Reads the file where stderr was saved + int loadfile(const char * filename); + + // Callbacks + static void OK_cb(Fl_Widget *, void *); + static void font_change_cb(void * data, Fl_Font font, unsigned char size); + +private: + // Callbacks + void font_change(Fl_Font font, unsigned char size); + void OK(void); + + // Widgets + Fl_Text_Display * text_p; + Font_change_registration * font_change_reg_p; + Fl_Return_Button * ok_p; +}; + + + +// Class for the Run menu on the main menu bar + +class Run { + +friend class File; // For auto-display + +public: + Run(void); + ~Run(void); + + // To know which file to run Mup on + void set_file(File * file); + // Kill off child processes + void clean_up(void); + + // Callbacks + static void Display_cb(Fl_Widget *, void * data); + static void Play_cb(Fl_Widget *, void * data); + static void WritePostScript_cb(Fl_Widget *, void * data); + static void WriteMIDI_cb(Fl_Widget *, void * data); + static void Options_cb(Fl_Widget *, void * data); + +private: + // Callbacks + void Display(void); + void Play(void); + void WritePostScript(void); + void WriteMIDI(void); + void Options(void); + + // This runs Mup and maybe viewer/player + void Run_Mup(bool midi, bool show_or_play); + + // Execute the command with given argv. + // If proc_info_p is zero, wait for the process to complete, + // otherwise fill it in with information about the spawned process, + // so that the caller can keep track of it while it runs independently. + // The hide_window parameter is only used for Windows and causes the + // spawned process to be created with flags to not create a window, + // This lets us use a console mode version of Mup, so traditional users + // can continue to run Mup in a console without mupmate, but we can + // run the same .exe without the annoyance of a console popping up. + // Returns 0 on success, -1 on failure to create process, + // or what the process returned if it had non-zero exit code + // and was waited for. If a not-waited-for process returns 0, + // proc_info_p will contain handle or pid information. + int execute_command(const char **argv, Proc_Info * proc_info_p, + bool hide_window = false); + + // kill off a previously spawned child process + void kill_process(const Proc_Info * const proc_info_p, + const char * const description); + + // Report if we have running helper programs + bool has_MIDI_child(void); + bool has_display_child(void); + +#ifdef OS_LIKE_WIN32 + // To check if using displayer/player we know how to handle specially + static bool is_gsview(const char * command); + static bool is_mplayer(const char * command); +#endif + + // Widgets + Run_parameters_dialog * parameters_p; + Error_report * report_p; + File * file_p; + + // Handles for child processes + Proc_Info display_child; + Proc_Info MIDI_child; +}; + +#endif diff --git a/mup/mupmate/globals.H b/mup/mupmate/globals.H new file mode 100644 index 0000000..71492d8 --- /dev/null +++ b/mup/mupmate/globals.H @@ -0,0 +1,32 @@ +#ifndef _GLOBALS_H +#define _GLOBALS_H + +// Try to consolidate OS-specific ifdef complicated clauses to this +// header file, so code can use descriptive ifdefs +#if defined(__WIN32) && ! defined(__CYGWIN__) +#define OS_LIKE_WIN32 +#endif + +#if defined(__linux) || defined(unix) +#define OS_LIKE_UNIX +#endif + + +// We use a class static method for callbacks which cast their "void * data" +// argument to an instance of the class, and call the class method. +// So we use these macros to enforce consistent usage of that technique. +// Most places will use CALL_BACK. The CALL_BACK_A is only needed in code +// when the object method takes an argument. +// Can't use CALLBACK as single word since under mingw that is already +// defined as something completely different. +#define CALL_BACK_A(classname, cb_name, arg) \ + void \ + classname::cb_name##_cb(Fl_Widget *, void * data) \ + { \ + ((classname *)data)->cb_name(); \ + } \ + void \ + classname::cb_name(arg) +#define CALL_BACK(classname, cb_name) CALL_BACK_A(classname, cb_name, void) + +#endif diff --git a/mup/mupmate/license.C b/mup/mupmate/license.C new file mode 100644 index 0000000..3bba4e9 --- /dev/null +++ b/mup/mupmate/license.C @@ -0,0 +1,69 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +extern const char * const license_text = +"\n\ +At Arkkra Enterprises, we'd like all our customers to be delighted with our\n\ +products. To ensure that Mup and any other products or services we provide\n\ +are readily available at the lowest possible cost to you, we need to\n\ +establish licensing terms.\n\ +\n\ +While there are other music publication programs on the market, we believe\n\ +Mup has unique features that you may find very useful. Since different\n\ +people may want different things in a music publication program, you do not\n\ +have to pay for Mup until after you've had a chance to try it out and\n\ +evaluate it for yourself. If you have problems with Mup, let us know and we\n\ +will try to resolve them. If you have paid your registration fee and we\n\ +cannot resolve problems to your satisfaction, we will gladly refund your\n\ +money.\n\ +\n\ + Mup License\n\ +\n\ +Arkkra Enterprises disclaims all warranties relating to this software,\n\ +whether expressed or implied, including but not limited to any implied\n\ +warranties of merchantability and fitness for a particular purpose, and all\n\ +such warranties are expressly and specifically disclaimed. Neither Arkkra\n\ +Enterprises nor anyone else who has been involved in the creation,\n\ +production, or delivery of this software shall be liable for any indirect,\n\ +consequential, or incidental damages arising out of the use of or inability\n\ +to use such software even if Arkkra Enterprises has been advised of the\n\ +possibility of such damages of claims. In no event shall Arkkra Enterprises'\n\ +liability for any damages ever exceed the price paid for the license to use\n\ +the software, regardless of the form of the claim. The person using the\n\ +software bears all risk as to the quality and performance of the software.\n\ +\n\ +Some states do not allow the exclusion of the limit of liability for\n\ +consequential damages, so the above limitation may not apply to you.\n\ +\n\ +This agreement shall be governed by the laws of the state of Illinois and\n\ +shall inure to the benefit of Arkkra Enterprises, and any successors,\n\ +administrators, heirs and assigns. Any action or proceeding brought by\n\ +either party against the other arising out of or related to this agreement\n\ +shall be brought only in the state or federal court of competent\n\ +jurisdiction located in DuPage County, Illinois. The parties hereby consent\n\ +to in personam jurisdiction of said courts.\n\ +\n\ +This software is licensed to you, for your own use. This is copyrighted\n\ +software. You are not obtaining title to the software or any copyright\n\ +rights. You may not sublicense, rent, lease, convey, modify, or translate\n\ +this software for any purpose.\n\ +\n\ +You may make as many copies as you need for back-up purposes. You may use\n\ +this software on more than one computer, provided there is no chance it will\n\ +be used simultaneously on more than one computer. If you need to use this\n\ +software on more than one computer simultaneously, you will need to obtain a\n\ +license for each copy or a site license.\n\ +\n\ +You may make copies of this software for other parties under the following\n\ +terms:\n\ +\n\ + * The copy must be an exact copy as would be obtained directly from\n\ + Arkkra Enterprises, including this license. It must clearly state that\n\ + it is a copy, and must give the address of Arkkra Enterprises.\n\ +\n\ + * The copy must be used by the obtaining party only for the purpose of\n\ + trialing the software. If after trialing the software, the receiving\n\ + party wishes to continue to use the software, they must submit their\n\ + license fee.\n\ +\n\ + * All limitations and disclaimers of this license apply to the copy."; diff --git a/mup/mupmate/mup16.xpm b/mup/mupmate/mup16.xpm new file mode 100644 index 0000000..d66f8eb --- /dev/null +++ b/mup/mupmate/mup16.xpm @@ -0,0 +1,23 @@ +/* XPM */ +static char * mup16_xpm[] = { +"16 16 4 1", +" c None", +". c white", +"X c #ff2222", +"o c #ff9999", +" ...... ", +"..XXXo. ", +".XXXXX. ......", +".XXXXX. ..XXXo.", +".XoXX.. .XXXXX.", +".X.... .XXXXX.", +".X. .XoXX..", +".X. .X.... ", +".X. .X. ", +".X. .X. ", +".X.... .X. ", +".XXXo.....X. ", +".XXXXXXX..X. ", +".XXXXXXXXXX. ", +".....oXXXXX. ", +" ........ "}; diff --git a/mup/mupmate/mup32.xpm b/mup/mupmate/mup32.xpm new file mode 100644 index 0000000..8557e9c --- /dev/null +++ b/mup/mupmate/mup32.xpm @@ -0,0 +1,42 @@ +/* XPM */ +static char * mup32_xpm[] = { +/* width height ncolors chars_per_pixel */ +"32 32 4 1", +/* colors */ +" c None", +". c white", +"X c #FF2222", +"o c #FF9999", +/* pixels */ +" ...... ", +" ......... ", +" ...XXXXo.. ", +" ..XXXXXXXo.. ", +" ..XXXXXXXXXo.. ..... ", +" ..XXXXXXXXXo.. ......... ", +"..XXXXXXXXXX.. ...XXXXo.. ", +"..XXXXXXXXXo.. ..XXXXXXXo..", +"..XXoXXXXXX.. ..XXXXXXXXXo.", +"..XX.oXXXX.. ..XXXXXXXXXo.", +"..XX....... ..XXXXXXXXXX..", +"..XX...... ..XXXXXXXXXo..", +"..XX.. ..XXoXXXXXX.. ", +"..XX.. ..XX.oXXXX.. ", +"..XX.. ..XX....... ", +"..XX.. ..XX...... ", +"..XX.. ..XX.. ", +"..XX.. ..XX.. ", +"..XX.. ..XX.. ", +"..XX.. ..XX.. ", +"..XX.. ..XX.. ", +"..XX.... ..XX.. ", +"..XX......... ..XX.. ", +"..XXXXXo............XX.. ", +"..XXXXXXXXXXo.......XX.. ", +"..XXXXXXXXXXXXXXXo..XX.. ", +"..XXXXXXXXXXXXXXXXXXXX.. ", +"..XXXXXXXXXXXXXXXXXXXX.. ", +".......oXXXXXXXXXXXXXX.. ", +"............oXXXXXXXXX.. ", +" ................. ", +" ............ "}; diff --git a/mup/mupmate/mup48.xpm b/mup/mupmate/mup48.xpm new file mode 100644 index 0000000..5e18ad2 --- /dev/null +++ b/mup/mupmate/mup48.xpm @@ -0,0 +1,58 @@ +/* XPM */ +static char * mup48_xpm[] = { +/* width height ncolors chars_per_pixel */ +"48 48 4 1", +/* colors */ +" c None", +". c white", +"X c #FF9999", +"o c #FF2222", +/* pixels */ +" ......... ", +" ........... ", +" ............. ", +" ..XooooooooX... ", +" ..XooooooooooX.... ", +" ..XooooooooooooX... ", +" ..Xoooooooooooooo... .......... ", +" ...ooooooooooooooo... ........... ", +" ...ooooooooooooooo... .............. ", +"...oooooooooooooooo... ..XooooooooX... ", +"...oooooooooooooooX.. ..XooooooooooX...", +"...ooooooooooooooX.. ..XooooooooooooX..", +"...oooXoooooooooX.. ..Xoooooooooooooo..", +"...ooo.XooooooX... ...ooooooooooooooo..", +"...ooo........... ...ooooooooooooooo..", +"...ooo.......... ...oooooooooooooooo..", +"...ooo......... ...oooooooooooooooX..", +"...ooo... ...ooooooooooooooX.. ", +"...ooo... ...oooXoooooooooX.. ", +"...ooo... ...ooo.XoooooooX.. ", +"...ooo... ...ooo........... ", +"...ooo... ...ooo.......... ", +"...ooo... ...ooo......... ", +"...ooo... ...ooo... ", +"...ooo... ...ooo... ", +"...ooo... ...ooo... ", +"...ooo... ...ooo... ", +"...ooo... ...ooo... ", +"...ooo... ...ooo... ", +"...ooo... ...ooo... ", +"...ooo... ...ooo... ", +"...ooo... ...ooo... ", +"...ooo.... ...ooo... ", +"...ooo......... ...ooo... ", +"...ooo............... ...ooo... ", +"...oooooooooX.................ooo... ", +"...oooooooooooooooX...........ooo... ", +"...ooooooooooooooooooooX......ooo... ", +"...ooooooooooooooooooooooooooXooo... ", +"...oooooooooooooooooooooooooooooo... ", +"...oooooooooooooooooooooooooooooo... ", +"...oooooooooooooooooooooooooooooo... ", +"............Xoooooooooooooooooooo... ", +"..................Xoooooooooooooo... ", +".......................Xooooooooo... ", +" ......................... ", +" ................... ", +" ............... "}; diff --git a/mup/mupmate/mupicons.ico b/mup/mupmate/mupicons.ico new file mode 100644 index 0000000..3523250 Binary files /dev/null and b/mup/mupmate/mupicons.ico differ diff --git a/mup/mupmate/mupmate.rc b/mup/mupmate/mupmate.rc new file mode 100644 index 0000000..c008169 --- /dev/null +++ b/mup/mupmate/mupmate.rc @@ -0,0 +1,2 @@ +#include "resource.h" +IDI_ICON ICON DISCARDABLE "mupicons.ico" diff --git a/mup/mupmate/regform.C b/mup/mupmate/regform.C new file mode 100644 index 0000000..fde93ce --- /dev/null +++ b/mup/mupmate/regform.C @@ -0,0 +1,32 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +extern const char * const registration_text = +"Mup is SHAREWARE. You can try out a copy for free, but if you decide\n\ +to keep and use it, you must register by filling out the form below\n\ +and sending the form and cash, check, or money order to:\n\ + Arkkra Enterprises\n\ + P. O. Box 315\n\ + Warrenville, IL 60555 USA\n\ +\n\ +Name______________________________________________________________\n\ +\n\ +Address___________________________________________________________\n\ +\n\ +City_____________________________ State/Province__________________\n\ +\n\ +Zip code/Postal code_____________________ Country_________________\n\ +\n\ +Email address (please print clearly)______________________________\n\ +\n\ +How did you find out about Mup?___________________________________\n\ +\n\ +__________________________________________________________________\n\ +\n\ +___Linux ___ Windows/MS-DOS ___Mac ___Other____________________\n\ +\n\ +Would you like to join the Mup users mailing list? ___ Yes ___ No\n\ +\n\ +___ Mup Version 5.3 Registrations.........................$29 each\n\ + (Illinois residents, add $2.18 sales tax)\n\ +(For credit card payment, see http://www.arkkra.com/doc/credtcrd.html)"; diff --git a/mup/mupmate/resource.h b/mup/mupmate/resource.h new file mode 100644 index 0000000..b9dd4e0 --- /dev/null +++ b/mup/mupmate/resource.h @@ -0,0 +1,3 @@ +#ifndef IDI_ICON +#define IDI_ICON 101 +#endif diff --git a/mup/mupmate/template.C b/mup/mupmate/template.C new file mode 100644 index 0000000..5ca4513 --- /dev/null +++ b/mup/mupmate/template.C @@ -0,0 +1,148 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +/* We build the template into Mupmate so we do not have to depend on the + * template file existing at run time. */ +extern const char * const template_text = +"//!Mup-Arkkra\n\ +// This is a Mup input file template.\n\ +// Lines starting with // are \"comments\" that are here for your benefit.\n\ +// You can remove them without affecting the output.\n\ +\n\ +/////////////////////////////////////////////////////////////////////////\n\ +// things to go on the top of the first page\n\ +top\n\ +\n\ + // centered title.\n\ + // The number in parentheses is the text point size.\n\ + // Make it bigger if you want a bigger title or smaller if you\n\ + // want a smaller title\n\ + title (18) \"Replace this with the title of your song\"\n\ +\n\ + // subtitle\n\ + // If you want a subtitle, remove the // from the beginning\n\ + // of the next line and fill in the appropriate subtitle text\n\ + // title (14) \"Replace this with the subtitle\"\n\ +\n\ + // composer info\n\ + // The first pair of double quotes enclose what to left justify,\n\ + // the second encloses what to right justify.\n\ + // If you want more than one line, add similar lines of input\n\ + title \"\" \"Replace this with composer info\"\n\ +\n\ +\n\ +/////////////////////////////////////////////////////////////////////////\n\ +// things to go on the bottom on the first page\n\ +bottom\n\ + // If you want a copyright notice, remove the //\n\ + // from the next line and edit in the appropriate information\n\ + // title \"\\(copyright) Copyright Replace this with year and name\"\n\ +\n\ +\n\ +/////////////////////////////////////////////////////////////////////////\n\ +// things to go on the top of pages other than the first\n\ +top2\n\ + // This example will give a centered page number between dashes.\n\ + // You can customize as you wish.\n\ + title \"- \\% -\"\n\ +\n\ +\n\ +/////////////////////////////////////////////////////////////////////////\n\ +// things to go at the bottom of pages other than the first\n\ +bottom2\n\ + // if you want things printed at the bottom of pages of than\n\ + // the first page, place them here\n\ +\n\ +\n\ +/////////////////////////////////////////////////////////////////////////\n\ +// score-wide parameters\n\ +//\n\ +// You may or may not need to change some items in this section\n\ +//\n\ +// The values given as examples are the default values that Mup uses\n\ +// if you don't specify anything for them\n\ +score\n\ + // time signature. Can be cut, com,\n\ + // or two numbers with a / between them\n\ + time = 4/4\n\ +\n\ + // key signature. Value is a number from 0 to 7\n\ + // followed by # or & for number of sharps or flats.\n\ + key = 0#\n\ +\n\ + // how many staffs. Can be a number from 1 to 40\n\ + staffs = 1\n\ +\n\ + // clef. Can be treble, treble8, 8treble, frenchviolin,\n\ + // soprano, mezzosoprano, alto, tenor, baritone, or bass\n\ + clef = treble\n\ +\n\ + // Note: there are many more parameters that can be set,\n\ + // but they are not included in this simple template.\n\ + // There are parameters to set margins, control how things\n\ + // are laid out on the page, transpositions value, font and size\n\ + // for text and lyrics, etc\n\ +\n\ +\n\ +/////////////////////////////////////////////////////////////////////////\n\ +// You can set some parameters for specific staffs,\n\ +// to override the score-wide parameters. For example,\n\ +// if you specify staffs = 2 in the score-wide parameters above,\n\ +// and want to use bass clef on staff 2, even though the score-wide\n\ +// clef parameter is set to treble, you can do\n\ +// staff 2\n\ +// clef = bass\n\ +\n\ +\n\ +/////////////////////////////////////////////////////////////////////////\n\ +// music input starts here\n\ +music\n\ +\n\ +\n\ +// For each measure, you enter one line of input for each staff,\n\ +// then indicate what kind of barline to print.\n\ +// The following specifies that staff 1 contains a measure of rest\n\ +// and that an ordinary bar line is to be used at the end of the measure.\n\ +\n\ +1: mr;\n\ +bar\n\ +\n\ +// Usually, a measure of input for one staff consists of one or more chords\n\ +// Each chord is specified by\n\ +// time_value notes ;\n\ +// where time_value is something like\n\ +// 4 for a quarter note\n\ +// 8 for an eighth note\n\ +// 4. for a dotted-quarter note\n\ +// etc and notes is a list of one or more notes, specified as a pitch from\n\ +// a to g, optionally followed by an accidental (#, &, x, &&, or n for sharp,\n\ +// flat, double sharp, double flat, or natural respectively).\n\ +// Examples:\n\ +// 4c;\n\ +// 2. ceg;\n\ +// 16 f#;\n\ +// 1 d b&;\n\ +// (Spaces are optional, you can put them in if you want, but don't have to)\n\ +//\n\ +// So a complete measure might look something like:\n\ +// 1: 4e; 4d; 2c;\n\ +// bar\n\ +//\n\ +// If you want a note in a different octave than the default octave\n\ +// (the octave from middle-C up for treble clef,\n\ +// or the octave below middle-C for bass clef),\n\ +// you can add a + for each octave to go up or - for each octave to go down.\n\ +// For example:\n\ +// 1: c+; gc+e+; a&-; f#---;\n\ +//\n\ +// There are many other things you can specify, such as ties, slurs, grace\n\ +// notes, etc, and there are also many shortcuts you can use to save typing.\n\ +// Consult the Mup documentation for more details.\n\ +\n\ +// Other bar types you may want to use are\n\ +// repeatstart\n\ +// repeatend\n\ +// repeatboth\n\ +// dblbar\n\ +// endbar\n\ +// invisbar"; diff --git a/mup/mupmate/utils.C b/mup/mupmate/utils.C new file mode 100644 index 0000000..ff4cda1 --- /dev/null +++ b/mup/mupmate/utils.C @@ -0,0 +1,573 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +// This file contains code for miscellaneous things that don't seem to really +// belong with any particular menu. + +#include +#include +#include +#include +#include "globals.H" +#include "utils.H" +#include +#include +#ifdef OS_LIKE_WIN32 +#include +#include +#include +#include +#include +#include +#endif + + +// The FLTK Fl_Int_Input is almost what we want, but it allows +// octal and hex input via leading 0 and 0x respectively. +// So the Int_Input derived class intercepts the input and throws away +// characters from the set [xX] and leading zeros. +// Sometimes we also want to restrict to positive numbers, +// so the Positive_Int_Input class discards the - character as well. + +Int_Input::Int_Input(int x, int y, int w, int h, const char * label) + : Fl_Int_Input(x, y, w, h, label) +{ + allow_negative = true; +} + + +Positive_Int_Input::Positive_Int_Input(int x, int y, int w, int h, const char * label) + : Int_Input(x, y, w, h, label) +{ + allow_negative = false; +} + +int +Int_Input::handle(int event) +{ + if (event == FL_KEYBOARD) { + int key = Fl::event_key(); + if (key == 'x' || key == 'X') { + return(1); + } + if (key == '0' && position() == 0) { + return(1); + } + if (key == '-' && ! allow_negative) { + return(1); + } + } + return(Fl_Int_Input::handle(event)); +} + + + +// Character used to separate items in $PATH and to separate directory names +#ifdef OS_LIKE_WIN32 + static const char path_sep = ';'; + static const char dir_sep = '\\'; +#else + static const char path_sep = ':'; + static const char dir_sep = '/'; +#endif + + +// Return the native OS's directory separator character + +char +dir_separator(void) +{ + return(dir_sep); +} + +// Return the native OS's path separator character +char +path_separator(void) +{ + return(path_sep); +} + +// Set the value of $MUPPATH. We "new" space for it and save a static +// pointer to that space. +// If it had been set before, we delete the old space. + +void +set_muppath(const char * new_muppath) +{ + static char * muppath = 0; + + if (muppath != 0) { + // The +8 is to skip past the MUPPATH= part + if (strcmp(muppath + 8, new_muppath) == 0) { + // Setting to existing value, so nothing to do + return; + } + delete muppath; + } + muppath = new char [strlen(new_muppath) + 9]; + (void) sprintf(muppath, "MUPPATH=%s", new_muppath); + (void) putenv(muppath); +} + + + +// Given a path to a file in "location", and the length of that path, +// and a suffix, see if the location with the suffix added is an +// executable file. If so, return true, with the suffixed name left +// in location. Otherwise return false with location as it came in. +// Could also return false if path would be longer than FL_PATH_MAX, +// and therefore will not fit. (Better to fail than core dump.) + +static bool +access_with_suffix(char * location, int length, const char * suffix) +{ + if (length + strlen(suffix) + 1 > FL_PATH_MAX) { + // Too long to store + return(false); + } + + // Add suffix and see if it is an executable file + (void) strcpy(location + length, suffix); + if(access(location, X_OK) == 0) { + return(true); + } + else { + // This suffix didn't work. Remove it before returning + location[length] = '\0'; + return(false); + } +} + + +// Given a file location, see if it exists as an executable file, +// taking into account the DOS/Windows strangeness of implicit suffixes. + +static bool +check_access(char * location) +{ + int len = strlen(location); +#ifdef __WIN32 + // If doesn't have a suffix, try with .com, .exe, and .bat suffix + if (len < 5 || strchr(location + len - 4, '.') == 0) { + // This is the precedence order for executable suffixes + if (access_with_suffix(location, len, ".com")) { + return(true); + } + if (access_with_suffix(location, len, ".exe")) { + return(true); + } + if (access_with_suffix(location, len, ".bat")) { + return(true); + } + return(false); + } + // If did have a suffix, go ahead and try name as is +#endif + return access_with_suffix(location, len, ""); +} + + +// Find the value of PATH. First try in third arg of main() +// since that seems more reliable on some OSs. Failing that, try getenv(). + +// We cache the value so we only have to search for it one time. +// This also rescues us in case env_p becomes invalid due to setting +// new environment variable values. + +static const char * Path = 0; + +void +get_path(const char ** const env_p) +{ + if (Path != 0) { + // Already did it before + return; + } + + if (env_p != 0) { + // Find $PATH in the environment variable list + int e; + for (e = 0; env_p[e] != 0; e++) { + if (strncmp(env_p[e], "PATH=", 5) == 0) { + Path = strdup(env_p[e] + 5); + break; + } + } + } + if (Path == 0) { + // Not found in the arge, so try looking up directly + Path = getenv("PATH"); + } +} + + +// Return true if given path is an absoluate path + +bool +is_absolute(const char * const path) +{ +#ifdef OS_LIKE_WIN32 + if ((path[0] != '\0' && path[1] == ':') || path[0] == dir_sep) { +#else + if (path[0] == dir_sep) { +#endif + return(true); + } + return(false); +} + + +// Given the name of a executable program, find the directory from +// which it comes, and put the full path into "location," +// which is expected to be at least FL_PATH_MAX bytes long. +// The incoming pgm_name is expected to be no more than FL_PATH_MAX long. +// It uses the components of PATH to try to find the executable. +// For Windows, if the program name doesn't have a suffix, +// it tries to find a .com, .exe, or .bat file with the pgm_name. +// It returns true on success. On failure, it returns false, +// and the contents of location are not defined. + +bool +find_executable(const char * const pgm_name, char * location) +{ + // If pgm_name is already absolute path, + // just check if it exists and is executable + if (is_absolute(pgm_name)) { + (void) strcpy(location, pgm_name); + return (check_access(location)); + } + + if (Path == 0) { + // Should have already looked up $PATH, + // but make another attempt, just in case... + get_path(0); + if (Path == 0) { + return(false); + } + } + + // We'll try the program name added to each PATH component + // until we find it or have to give up. +#ifdef OS_LIKE_WIN32 + // DOS/Windows implicitly adds current working directory first + bool add_implicit_cwd = true; +#else + bool add_implicit_cwd = false; +#endif + const char * component; // current component of PATH + const char * next_component; // next component of PATH + const char * sep_p; // location of PATH separator + int len; // length of component + for (component = Path; *component != '\0'; component = next_component) { + if (add_implicit_cwd) { + // DOS/Windows implicitly adds current directory + // as first PATH component. + len = 0; + next_component = component; + add_implicit_cwd = false; + } + + else if ((sep_p = strchr(component, path_sep)) != 0) { + // Not the last component in the PATH + len = sep_p - component; + next_component = sep_p + 1; + } + else { + // Is the last component in the PATH + len = strlen(component); + next_component = component + len; + } + + if (len == 0) { + // Empty path component means current directory. + // Allow enough room for directory separator, + // pgm_name, suffix, and null terminator + if (getcwd(location, FL_PATH_MAX + - strlen(pgm_name) - 6) == 0) { + // Current directory unobtainable or too long + return(false); + } + len = strlen(location); + } + else { + strncpy(location, component, len); + } + + // If PATH component didn't already add a directory + // separator, we add one. In some OSs it doesn't hurt + // to add another, but no reason to use an extra byte. + if (location[len-1] != dir_sep) { + location[len++] = dir_sep; + } + + // Now add the progam name itself and see if it exists. + // The check_access() will add implied suffix if necessary. + (void) strcpy(location + len, pgm_name); + if (check_access(location)) { + return(true); + } + } + return(false); +} + + +// Returns location of magic file that lets us know user agreed +// to the license. The value is saved so subsequent calls can just return +// the saved value. If something goes wrong, a null string is returned. + +#ifdef OS_LIKE_WIN32 + #define MAGIC_FILE_NAME "mup.ok" +#else + #if defined(OS_LIKE_UNIX) || defined(VMS) || defined(AMIGA) || defined(EMX) + #define MAGIC_FILE_NAME ".mup" + #else + #ifdef Mac_BBEdit + #define MAGIC_FILE_NAME (char *)(MupRegFileName + 1) + #endif + #endif +#endif + +#ifndef MAGIC_FILE_NAME +#error OS not supported +#endif + +const char * +magic_file(const char * pname, const char ** env_p) +{ + char * home; + char * fname = MAGIC_FILE_NAME; + static char * magicpath = 0; // Path is saved here + + if (magicpath != 0) { + // Must have figured it out on previous call + return(magicpath); + } + + // First check current directory. This will only work + // for the case where user has already created the file, + // and is of somewhat questionable use, since if the user + // changes directories to somewhere without the magic file, + // Mup will print the watermark. + if (access(fname, F_OK) == 0) { + magicpath = new char[strlen(fname) + 1]; + strcpy(magicpath, fname); + return(magicpath); + } + +#ifdef OS_LIKE_WIN32 + // Construct pathname to magic file in the directory where + // mup.exe came from + if (pname == 0) { + // Shouldn't happen; We should get called once with valid + // pname, and return cached value after that + fl_alert("Unable to determine magic file name."); + return(""); + } + char location[FL_PATH_MAX]; + if (find_executable(pname, location)) { + int baselength = strlen(location) + - strlen(fl_filename_name(location)); + magicpath = new char[baselength + strlen(fname) + 1]; + // Copy pname up to last backslash + (void) strncpy(magicpath, location, baselength); + // add magic file name + (void) strcpy(magicpath + baselength, fname); + } +#else + // Construct pathname to magic file if it is in $HOME + if ((home = getenv("HOME")) != (char *) 0) { + magicpath = new char[strlen(home) + strlen(fname) + 2]; +#ifdef VMS + (void) sprintf(magicpath, "%s%s", home, fname); +#else + (void) sprintf(magicpath, "%s/%s", home, fname); +#endif + } + +#endif +#ifdef Mac_BBEdit +#pragma unused(pname) + // Check for file in Preferences folder inside System folder + magicpath = 0; + home = 0; + { + short vRefNum; + long dirID; + FSSpec fsSpec; + + if (FindFolder(kOnSystemDisk, kPreferencesFolderType, false, + &vRefNum, &dirID) == noErr) { + // Preferences folder exists + if (FSMakeFSSpec(vRefNum, dirID, + (StringPtr) MupRegFileName, &fsSpec) + == noErr) { + // File exists + short old_vRefNum; + long old_dirID; + if (HGetVol((StringPtr) 0, &old_vRefNum, + &old_dirID) != noErr) { + return; + } + + if (HSetVol((StringPtr) 0, vRefNum, dirID) + != noErr) { + return; + } + HSetVol((StringPtr) 0, old_vRefNum, old_dirID); + magicpath = new char[strlen(MAGIC_FILE_NAME) + 1]; + (void) sprintf(magicpath, MAGIC_FILE_NAME); + } + } + } +#endif + + if (magicpath == 0) { + // Not sure what to really do here... Punt. + fl_alert("Unable to find magic file path."); + magicpath = ""; + } + + return(magicpath); +} + + +#ifdef OS_LIKE_WIN32 + +// On Windows, we read the registry to try to determine the proper +// program to use for a given file type, like .mid or .ps files. +// This function will return the path to the appropriate file, +// if found, in a static area that may get overwritten on next call, +// so caller needs to make its own copy. If program is not found, +// returns null. + + +char * +lookup_pgm_for_file_suffix(const char * file_suffix) +{ + static char data[512]; + char name[512]; + long len = sizeof(data); + // First find entry for file suffix mapping to a class + (void) sprintf(name, "Software\\Classes\\%s", file_suffix); + HRESULT result = RegQueryValue(HKEY_LOCAL_MACHINE, name, data, &len); + if (result != ERROR_SUCCESS) { + return(0); + } + + // Next look up the program associated with that class + (void) sprintf(name, "Software\\Classes\\%s\\shell\\open\\command", data); + len = sizeof(data); + result = RegQueryValue(HKEY_LOCAL_MACHINE, name, data, &len); + if (result != ERROR_SUCCESS) { + return(0); + } + + // We might get multiple strings back, + // giving the program itself plus arguments. + // We only want the program itself. So if the first string is quoted, + // strip the quotes and anything after it. + char * d; + if (*data == '"') { + for (d = data + 1; *d != '\0'; d++) { + if (*d == '"') { + *(d-1) = '\0'; + break; + } + *(d-1) = *d; + } + } + if (access(data, X_OK) == 0) { + return(data); + } + return(0); +} + + +// Look up the given name in the CURRENT_USER area of registry +// and if found, fill in the data and return true, except return false. + +static bool +reg_dir_found(char * name, char * data, DWORD len) +{ + HRESULT result = RegQueryValueEx(HKEY_CURRENT_USER, name, 0, 0, + (LPBYTE)data, &len); + if (result == ERROR_SUCCESS) { + struct stat info; + if (stat(data, &info) == 0 && (info.st_mode & S_IFDIR)) { + return(true); + } + } + return(false); +} + + +// Look for likely default folder for Mup files. +// Use the current user's "My Music" folder if there is one, +// otherwise try their "Personal" folder. +// Returns path in static area or null on failure. + +char * +find_music_folder(void) +{ + static char best_value[FL_PATH_MAX]; + + // Get the registry info about folders + HKEY key = 0; + // Win'98 uses "User Shell Folders" but newer versions use just + // "Shell Folders," so we check for both, newer first, since that + // is probably more likely to work. + if ((RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + 0, KEY_READ, &key) == ERROR_SUCCESS) || + (RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", + 0, KEY_READ, &key) == ERROR_SUCCESS)) { + DWORD max_key_length; + DWORD count; + DWORD max_name_length; + DWORD max_value_length; + // Find out how many subkeys there are, and max lengths. + if (RegQueryInfoKey(key, 0, 0, 0, 0, &max_key_length, 0, &count, + &max_name_length, &max_value_length, 0, 0) + == ERROR_SUCCESS) { + TCHAR name[max_name_length + 1]; + DWORD name_length; + DWORD value_type; + BYTE value[max_value_length + 1]; + DWORD value_length; + int i; + best_value[0] = '\0'; + // Look for "My Music" and "Personal" subkeys. + // There's probably a better way to query for specific + // subkey than linear search, but this works... + for (i = 0; i < count; i++) { + name_length = sizeof(name); + value_length = sizeof(value); + if (RegEnumValue(key, i, name, &name_length, 0, + &value_type, value, + &value_length) + == ERROR_SUCCESS) { + if (value_type != REG_SZ) { + continue; + } + if (strcasecmp(name, "My Music") == 0) { + // Found the ones we want. + strcpy(best_value, (char *) value); + break; + } + if (strcasecmp(name, "Personal") == 0) { + // This is our second choice. + // Save as best so far. + strcpy(best_value, (char *) value); + } + } + } + } + } + if (key != 0) { + RegCloseKey(key); + } + return(best_value[0] == '\0' ? 0 : best_value); +} + +#endif diff --git a/mup/mupmate/utils.H b/mup/mupmate/utils.H new file mode 100644 index 0000000..dee6435 --- /dev/null +++ b/mup/mupmate/utils.H @@ -0,0 +1,86 @@ +/* Copyright (c) 2006 by Arkkra Enterprises */ +/* All rights reserved */ + +#ifndef _UTILS_H_ +#define _UTILS_H_ + +// This file defines miscellaneous things that don't seem to really +// belong with any particular menu. + +#include +#include + +#ifdef OS_LIKE_WIN32 +// For some reason mingw doesn't seem to properly define va_list anywhere. +// I guess it needs a compiler-specific header file. +// We don't actually use any functions that use va_list, +// so just need to try to keep the compiler happy. +#ifndef va_list +#define va_list __VALIST +#endif +#endif + +// The FLTK Fl_Int_Input is almost what we want, but it allows +// octal and hex input via leading 0 and 0x respectively. +// So the Int_Input derived class intercepts the input and throws away +// characters from the set [xX] and leading zeros. +// Sometimes we also want to restrict to positive numbers, +// so the Positive_Int_Input class discards the - character as well. + +class Int_Input : public Fl_Int_Input { +public: + Int_Input(int x, int y, int w, int h, const char * label); + int handle(int event); +protected: + bool allow_negative; +}; + +class Positive_Int_Input : public Int_Input { +public: + Positive_Int_Input(int x, int y, int w, int h, const char * label); +}; + + +// Return the native OS's directory separator character +char dir_separator(void); +// Return the native OS's path separator character +char path_separator(void); + +// Set the $MUPPATH value +extern void set_muppath(const char * new_muppath); + +// Get value of PATH from third argument to main(), or failing that, +// from getenv(), and save it. +extern void get_path(const char ** const env_p); + +// Return true if given path is an absoluate path +extern bool is_absolute(const char * const path); + +// Find full path to an executable. +// If found, true is returned and full path is filled into location, +// which must be at least FL_PATH_MAX bytes long. +// If executable is not found, false is returned, and the contents of +// location is not defined. +extern bool find_executable(const char * const pgm_name, char * location); + +// Returns path to magic file saying user agrees to license +extern const char * magic_file(const char * pname = 0, const char ** env_p = 0); + +#ifdef OS_LIKE_WIN32 +// On Windows, we read the registry to try to determine the proper +// program to use for a given file type, like .mid or .ps files. +// This function will return the path to the appropriate file, +// if found, in a static area that may get overwritten on next call, +// so caller needs to make its own copy. If program is not found, +// returns null. +extern char * lookup_pgm_for_file_suffix(const char * file_suffix); + +// Look for likely default directory for Mup files. +// Use the current user's "My Music" place if there is one, +// otherwise try their "My Documents" folder. +// Returns path in static area or null on failure. +extern char * find_music_folder(void); + +#endif + +#endif diff --git a/mup/mupprnt b/mup/mupprnt new file mode 100755 index 0000000..a5a08b0 --- /dev/null +++ b/mup/mupprnt @@ -0,0 +1,57 @@ +# UNIX shell script for printing Mup output + +# **** NOTE: The GS_DEVICE shell variable needs to be set to the +# proper value for your printer type. +# Different versions of ghostscript may support different +# printer types, so execute ghostscript with the -h option +# to see what your version supports. +# +# PRINTERTYPE printer +# ------------------------------------------------------------------ +# bj10e Canon BubbleJet BJ10e +# cdeskjet H-P DeskJet 500C with 1 bit/pixel color +# cdjcolor H-P DeskJet 500C with 24 bit/pixel color and +# high-quality color (Floyd-Steinberg) dithering +# cdjmono H-P DeskJet 500C printing black only +# deskjet H-P DeskJet and DeskJet Plus +# dfaxhigh DigiBoard, Inc.'s DigiFAX software format (high resolution) +# dfaxlow DigiFAX low (normal) resolution +# djet500 H-P DeskJet 500 +# djet500c H-P DeskJet 500C +# epson Epson-compatible dot matrix printers (9- or 24-pin) +# eps9high Epson-compatible 9-pin, interleaved lines +# (triple resolution) +# epsonc Epson LQ-2550 and Fujitsu 3400/2400/1200 color printers +# laserjet H-P LaserJet +# la50 DEC LA50 printer +# la75 DEC LA75 printer +# lbp8 Canon LBP-8II laser printer +# ln03 DEC LN03 printer +# lj250 DEC LJ250 Companion color printer +# ljet2p H-P LaserJet IId/IIp/III* with TIFF compression +# ljet3 H-P LaserJet III* with Delta Row compression +# ljetplus H-P LaserJet Plus +# necp6 NEC P6/P6+/P60 printers at 360 x 360 DPI resolution +# paintjet H-P PaintJet color printer +# pjetxl H-P PaintJet XL color printer +# r4081 Ricoh 4081 laser printer +# tek4696 Tektronix 4695/4696 inkjet plotter + +echo "Mupprnt - Version 5.3" >&2 + +# if environment variable COPIES is set, use that as number of copies to print +if [ "$COPIES" != "" ] +then + _Mup_copies=-n$COPIES +fi + +muptmp=/usr/tmp/mtmp$$ +trap 'rm -f $muptmp' 0 1 2 15 +mup $* | gs -dNOPAUSE -sOutputFile=$muptmp - + + +if [ $? -eq 0 -a -s "$muptmp" ] +then + # use -c option to copy file to spool area, so we can remove tmp file + lp -c $_Mup_copies $muptmp +fi diff --git a/mup_5.3.orig.tar.gz b/mup_5.3.orig.tar.gz new file mode 100644 index 0000000..03d04ce Binary files /dev/null and b/mup_5.3.orig.tar.gz differ