The s ngs package∗ ¯ Kevin W. Hamlen July 10, 2013 Abstract ¯ The s ngs package produces songbooks that contain lyrics and chords (but not full sheet music). It allows lyric books, chord books, overhead slides, and digital projector slides to all be maintained and generated from a single LATEX source document. Automatic transposition, guitar tablature diagrams, handouts, and a variety of specialized song indexes are supported. 1 Introduction ¯ The s ngs LATEX package produces books of songs that contain lyrics and (optionally) chords. A single source document yields a lyric book for singers, a chord book for musicians, and overhead or digital projector slides for corporate singing. The software is especially well suited for churches and religious fellowships desiring to create their own books of worship songs. Rather than purchasing a fixed hymnal of songs, the s ngs package allows worship coordinators to maintain a constantly evolving repertoire of music to which they can add and remove songs over time. As the book content changes, the indexes, spacing, and other formatting details automatically adjust to stay consistent. Songs can also be quickly selected and arranged for specific events or services through the use of scripture indexes, automatic transposition, and handout and slide set creation features. ¯ 2 Terms of Use ¯ The s ngs package 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 of the License, or (at your option) any later version. A copy of the license can be found in §15. ∗ This document corresponds to songs v2.17, dated 2013/07/10, c 2013 Kevin W. Hamlen, and distributed under version 2 the GNU General Public License as published by the Free Software Foundation. 1 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 in §15 for more details. A copy of the license can also be obtained by writing to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. c 2013 Kevin W. Hamlen. For contact information or This software is copyright the latest version, see the project webpage at: http://songs.sourceforge.net 3 Sample Document For those who would like to start making song books quickly, the following is a sample document that yields a simple song book with one song and one title index. Starting from this template, you can begin to add songs and customizations to create a larger book. Instructions for compiling this sample song book follow the listing. \documentclass{article} \usepackage[chorded]{songs} \newindex{titleidx}{titleidx} \noversenumbers \begin{document} \showindex{Complete Index of Songs}{titleidx} \songsection{Worship Songs} \begin{songs}{titleidx} \beginsong{Doxology}[by={Louis Bourgeois and Thomas Ken}, sr={Revelation 5:13}, cr={Public domain.}, index={Praise God, from Whom all blessings flow}] \beginverse \[G]Praise God, \[D]from \[Em]Whom \[Bm]all \[Em]bless\[D]ings \[G]flow; \[G]Praise Him, all \[D]crea\[Em]tures \[C]here \[G]be\[D]low; \[Em]Praise \[D]Him \[G]a\[D]bove, \[G]ye \[C]heav’n\[D]ly \[Em]host; \[G]Praise Fa\[Em]ther, \[D]Son, \[Am]and \[G/B G/C]Ho\[D]ly \[G]Ghost. \[C]A\[G]men. \endverse \endsong \end{songs} \end{document} To compile this book, execute three commands. First, use LATEX (pdflatex is recommended) to compile the document: 2 pdflatex mybook.tex (where mybook.tex is the name of the source document above). Next, use the songidx program provided with this distribution to generate the indexes: songidx titleidx.sxd titleidx.sbx Finally, regenerate the document using LATEX so that the newly generated index data will be included: pdflatex mybook.tex The final document is named mybook.pdf if you use pdflatex or mybook.dvi if you use regular latex. A copy of the first page of a sample song section is shown in Figure 1. The page shown in that figure is from a chorded version of the book. When generating a lyric version, the chords are omitted. See §4 for information on how to generate different versions of the same book. 4 Initialization and Options ¯ Each LATEX document that uses the s ngs package should contain a line like the following near the top of the document: \usepackage[hoptionsi]{songs} Supported hoptionsi include the following: lyric chorded slides rawtext \chordson \chordsoff \slides nomeasures showmeasures \measureson \measuresoff ¯ Output Type. The s ngs package can produce four kinds of books: lyric books, chord books, books of overhead slides, and raw text output. You can specify which kind of book is to be produced by specifying one of lyric, chorded, slides, or rawtext as an option. If none of these are specified, chorded is the default. Lyric books omit all chords, whereas chord books include chords and additional information for musicians (specified using \musicnote). Books of overhead slides omit all chords and typeset one song per page in a large font, centered. Raw text output yields an ascii text file named hjobnamei.txt (where hjobnamei is the root filename) containing lyrics without chords. This can be useful for importing song books into another program, such as a spell-checker. Chords can be turned on or off in the middle of the document by using the \chordson or \chordsoff macros. Slides mode can be activated in the middle of the document by using the \slides macro. For best results, this should typically only be done in the document preamble or at the beginning of a fresh page. ¯ Measure Bars. The s ngs package includes a facility for placing measure bars in chord books (see §7.7). To omit these measure bars, use the nomeasures option; to display them, use the showmeasures option (the default). Measure bars can also be turned on or off in the middle of the document by using the \measureson or \measuresoff macros. 3 Worship Songs Doxology 1 A Mighty Fortress Is Our God 2 Revelation 5:13 Louis Bourgeois and Thomas Ken Martin Luther G D Em Bm Em D Praise God, from Whom all G flow; C #m B7 D A E7 A E our God, A bulwark never fail - ing. G D Em C GD Praise Him, all creatures here below; Em A blessings A mighty Fortress is D G D G C C #m B7 Our helper He, D D Em A E amid the flood E7 A Praise Him a - bove, ye heav’nly host; Of mortal ills prevailing. G Em D B7sus4 B7 E Am For still our an Praise Father, Son, and G/B G/C D G Ho - - cient foe E/G # A Doth seek to work ly Ghost. B7 C G F #m us woe; E His craft and pow’r are great, A - men. C# Bm And, armed with cruel hate, Public domain. The LORD is my rock and my fortress and my deliverer, my God, my rock, in whom I take refuge, my shield, and the horn of my salvation, my stronghold. I call upon the LORD, who is worthy to be praised, and I am saved from my enemies. The cords of death encompassed me; the torrents of destruction assailed me; the cords of Sheol entangled me; the snares of death confronted me. In my distress I called upon the LORD; to my God I cried for help. From his temple he heard my voice, and my cry to him reached his ears. D A E7 A A C #m D A On earth is not his e - qual. Did we in our B7 E own strength confide, E7 A Our striving would be los - ing. C #m B7 E Were not the right Man on our side, D A E7 A The Man of God’s own choosing. B7sus4 B7 E Dost ask who that A E/G may be? # Christ Jesus, it B7 F #m is He; E Lord Sabaoth His Name, C# Bm From age to age the same; D A E7 A And He must win the bat - tle. Psalm 18:2–6 Public Domain. Figure 1: Sample page from a chord book 4 transposecapos Transposition. The transposecapos option changes the effect of the \capo macro. Normally, using \capo{hni} within a song environment produces a textual note in chord books that suggests the use of a guitar capo on fret hni. However, when the transposecapos option is active, these textual notes are omitted and instead the effect of \capo{hni} is the same as for \transpose{hni}. That is, chords between the \capo macro and the end of the song are automatically transposed up by hni half-steps. This can be useful for adapting a chord book for guitarists to one that can be used by pianists, who don’t have the luxury of capos. See §7.8 and §10 for more information on the \capo and \transpose macros. noindexes \indexeson \indexesoff nopdfindex Indexes. The noindexes option suppresses the typesetting of any in-document indexes. Display of indexes can also be turned on or off using the \indexeson and \indexesoff macros. PDF bookmark entries and hyperlinks can be suppressed with the nopdfindex option. For finer control of PDF indexes, see §11.6. noscripture \scriptureon \scriptureoff Scripture Quotations. The noscripture option omits scripture quotations (see §8.2) from the output. You can also turn scripture quotations on or off in the middle of the document by using \scriptureon or \scriptureoff, respectively. noshading Shaded Boxes. The noshading option causes all shaded boxes, such as those that surround song numbers and textual notes, to be omitted. You might want to use this option if printing such shaded boxes causes problems for your printer or uses too much ink. \includeonlysongs Partial Song Sets. Often it is useful to be able to extract a subset of songs from the master document—e.g. to create a handout or set of overhead slides for a specific worship service. To do this, you can type \includeonlysongs{hsonglisti} in the document preamble (i.e., before the \begin{document} line), where hsonglisti is a comma-separated list of the song numbers to include. For example, \includeonlysongs{37,50,2} creates a document consisting only of songs 37, 50, and 2, in that order. Partial books generated with \includeonlysongs omit all scripture quotations (§8.2), and ignore uses of \nextcol, \brk, \sclearpage, and \scleardpage between songs unless they are followed by a star (e.g., \nextcol*). To force a column- or page-break at a specific point in a partial book, add the word nextcol, brk, sclearpage, or scleardpage at the corresponding point in the hsonglisti. The \includeonlysongs macro only reorders songs within each songs environment (see §7), not between different songs environments. It also cannot be used in conjunction with the rawtext option. 5 5 \songsection \songchapter Book Sections Section Titles. Section titles in a song book can be produced with \songsection{htitlei} which acts like LATEX’s \section command except that it centers the htitlei text in sans serif font and omits the section number. When using the book document class, use \songchapter instead of \songsection. \newindex \newauthorindex \newscripindex ¯ Indexes. The s ngs package supports three kinds of indexes: indexes by title and/or notable lyrics, indexes by author, and indexes by scripture reference. To generate an index, first declare the index in the document preamble (i.e., before the \begin{document} line) with one of the following: \newindex{hid i}{hfilenamei} \newauthorindex{hid i}{hfilenamei} \newscripindex{hid i}{hfilenamei} The hid i should be an alphabetic identifier that will be used to identify the index in other macros that reference it. The hfilenamei should be a string that, when appended with an extension, constitutes a valid filename on the system. Auxiliary files named hfilenamei.sxd and hfilenamei.sbx are generated during the automatic index generation process. For example: \newindex{mainindex}{idxfile} \showindex creates a title index named “mainindex” whose data is stored in files named idxfile.sxd and idxfile.sbx. To display the index in the document, use: \showindex[hcolumnsi]{htitlei}{hid i} where hid i is the same identifier used in the \newindex, \newauthorindex, or \newscripindex command, and where the htitlei is the title of the index, which should consist only of simple text (no font or formatting macros, since those cannot be used in pdf bookmark indexes). The [hcolumnsi] part is optional; if specified it dictates the number of columns if the index can’t fit in a single column. For example, for a 2-column title index, write: \showindex[2]{Index of Song Titles}{mainindex} 6 Compiling As with a typical LATEX document, compiling a song book document requires three steps. First, use LATEX (pdflatex is recommended) to generate auxiliary files from the .tex file: pdflatex mybook.tex 6 Second, use the songidx program to generate an index for each index that you declared with \newindex, \newauthorindex, or \newscripindex. The syntax of the songidx command is: songidx [-b hcanoni.can] hfilenamei.sxd hfilenamei.sbx where hfilenamei is the same hfilenamei that was used in the \newindex, \newauthorindex, or \newscripindex macro. If the index was declared with \newscripindex, then the -b option is used to specify which version of the bible you wish to use as a basis for sorting your scripture index. The hcanoni part can be any of the .can files provided with the songidx distribution. If you are using a Protestant, Catholic, or Greek Orthodox Christian bible with book names in English, then the bible.can canon file should work well. For other bibles, you should create your own .can file by copying and modifying one of the existing .can files. For example, if your song book .tex file contains the lines \newindex{titleidx}{titlfile} \newauthorindex{authidx}{authfile} \newscripindex{scripidx}{scrpfile} then the commands to generate indexes sorted according to a Christian English bible are: songidx titlfile.sxd titlfile.sbx songidx authfile.sxd authfile.sbx songidx -b bible.can scrpfile.sxd scrpfile.sbx Once the indexes are generated, generate the final book by invoking LATEX one more time: pdflatex mybook.tex 7 7.1 songs Songs Beginning a Song Song Sets. Songs are contained within songs environments. Each songs environment begins and ends with: \begin{songs}{hindexesi} .. . \end{songs} hindexesi is a comma-separated list of index identifiers (the hid i’s specified with \newindex)—one identifier for each index that is to include songs in this song set. Between the \begin{songs} and \end{songs} lines of a song section can appear only songs (see below) or inter-song environments (see §8). No text in a songs environment may lie outside of these environments. 7 \beginsong \endsong Songs. A song begins and ends with: \beginsong{htitlesi}[hotherinfoi] .. . \endsong Songs should appear only within songs environments (see above) unless you are supplying your own page-builder (see §11.5). In the \beginsong line, htitlesi is one or more song titles separated by \\. If multiple titles are provided, the first is typeset normally atop the song and the rest are each typeset in parentheses on separate lines. The [hotherinfoi] part is an optional comma-separated list of key-value pairs (keyvals) of the form hkeyi=hvaluei. The possible keys and their values are: by={hauthorsi} cr={hcopyrighti} li={hlicensei} sr={hrefsi} index={hlyricsi} ititle={htitlei} authors, composers, and other contributors copyright information licensing information related scripture references an extra index entry for a line of lyrics an extra index entry for a hidden title For example, a song that begins and ends with \beginsong{Title1 \\ Title2}[by={Joe Smith}, sr={Job 3}, cr={\copyright~2013 XYZ.}, li={Used with permission.}] \endsong looks like 1 Title1 (Title2) Job 3 Joe Smith c 2013 XYZ. Used with permission. The four keyvals used in the above example are described in detail in the remainder of this section; the final two are documented in §7.9. You can also create your own keyvals (see §11.8). by= Song Authors. The by={hauthorsi} keyval lists one or more authors, composers, translators, etc. An entry is added to each author index associated with the current songs environment for each contributor listed. Contributors are expected to be separated by commas, semicolons, or the word and. For example: by={Fred Smith, John Doe, and Billy Bob} Words separated by a macro-space (\ ) or tie (~) instead of a regular space are treated as single words by the indexer. For example, The Vienna Boys’ Choir is indexed as “Choir, The Vienna Boys’ ” but The Vienna\ Boys’\ Choir is indexed as “Vienna Boys’ Choir, The”. 8 cr= Copyright Info. The cr={hcopyrighti} keyval specifies the copyright-holder of the song, if any. For example: cr={\copyright~2000 ABC Songs, Inc.} Copyright information is typeset in fine print at the bottom of the song. li= \setlicense Licensing Info. Licensing information is provided by li={hlicensei}, where hlicensei is any text. Licensing information is displayed in fine print under the song just after the copyright information (if any). Alternatively, writing \setlicense{hlicensei} anywhere between the \beginsong and \endsong lines is equivalent to using li={hlicensei} in the \beginsong line. When many songs in a book are covered by a common license, it is usually convenient to create a macro to abbreviate the licensing information. For example, if your organization has a music license from Christian Copyright Licensing International with license number 1234567, you might define a macro like \newcommand{\CCLI}{(CCLI \#1234567)} Then you could write li=\CCLI in the \beginsong line of each song covered by CCLI. sr= ¯ Scripture References. The s ngs package has extensive support for scripture citations and indexes of scripture citations. To cite scripture references for the song, use the keyval sr={hrefsi}, where hrefsi is a list of scripture references. Index entries are added to all scripture indexes associated with the current songs environment for each such reference. The songidx index generation program expects hrefsi to be a list of references in which semicolons are used to separate references to different books, and commas are used to separate references to to different chapters and verses within the same book. For example, one valid scripture citation is sr={John 3:16,17, 4:1-5; Jude 3} The full formal syntax of a valid hrefsi argument is given in Figure 2. In those syntax rules, hchapter i and hversei stand for arabic numbers denoting a valid chapter number for the given book, and a valid verse number for the given chapter, respectively. Note that when referencing a book that has only one chapter, one should list only its verses after the book name (rather than 1:hversesi). 7.2 \beginverse \endverse \beginchorus \endchorus Verses and Choruses Starting A Verse Or Chorus. Between the \beginsong and \endsong lines of a song can appear any number of verses and choruses. A verse begins and ends with: \beginverse .. . \endverse 9 hrefsi −→ hnothingi | href i; href i;. . .; href i href i −→ hmany-chptr-book i hchaptersi | hone-chptr-book i hversesi hmany-chptr-book i −→ Genesis | Exodus | Leviticus | Numbers | . . . hone-chptr-book i −→ Obadiah | Philemon | 2 John | 3 John | Jude hchaptersi −→ hchref i, hchref i,. . ., hchref i hchref i −→ hchapter i | hchapter i-hchapter i | hchapter i:hversesi | hchapter i:hversei-hchapter i:hversei hversesi −→ hvref i,hvref i,. . .,hvref i hvref i −→ hversei | hversei-hversei Figure 2: Formal syntax rules for song scripture references and a chorus begins and ends with: \beginchorus .. . \endchorus Verses are numbered (unless \noversenumbers has been used to suppress verse numbering) whereas choruses have a vertical line placed to their left. To create an unnumbered verse, begin the verse with \beginverse* instead. This can be used for things that aren’t really verses but should be typeset like a verse (e.g. intros, endings, and the like). A verse that starts with \beginverse* should still end with \endverse (not \endverse*). Within a verse or chorus you should enter one line of text for each line of lyrics. Each line of the source document produces a separate line in the resulting document (like LATEX’s \obeylines macro). Lines that are too long to fit are wrapped with hanging indentation of width \parindent. \repchoruses \norepchoruses Repeating Choruses. When making overhead slides, it is often convenient to repeat the song’s chorus after the first verse on each page, so that the projectoroperator need not flip back to the first slide each time the chorus is to be sung. You can say \repchoruses to automate this process. This causes the first chorus in each song to be automatically repeated after the first verse on each subsequent page of the song (unless that verse is already immediately followed by a chorus). If the first chorus is part of a set of two or more consecutive choruses, then the whole set of choruses is repeated. (A set of choruses is assumed to consist of things like pre-choruses that should always be repeated along with the chorus.) Choruses are not automatically inserted immediately after unnumbered verses (i.e., verses that begin with \beginverse*). Unnumbered verses are assumed to be bridges or endings that aren’t followed by a chorus. The above covers the common cases, but some songs have more complex forms that demand a manual approach. Before a song with irregular form, say \norepchoruses to turn automatic chorus-repeating off. Then, at points within 10 the song where you want a chorus to be repeated on the overhead slides, type a construction like, \ifslides \beginchorus .. . \endchorus \fi and copy and paste the desired chorus into the middle. This inserts a repeated chorus at that point when generating slides, but not when generating a lyric book or chord book. After the song is concluded, type \ifslides\repchoruses\fi to turn automatic chorus-repeating back on, if desired. 7.3 \[ # & Chords Between the \beginverse and \endverse lines, or between the \beginchorus and \endchorus lines, chords can be produced using the macro \[hchordnamei]. Chords only appear in chord books; they are omitted from lyric books. The hchordnamei may consist of arbitrary text. To produce sharp and flat symbols, use # and & respectively. Any text that immediately follows the \[] macro with no intervening whitespace is assumed to be the word or syllable that is to be sung as the chord is struck, and is therefore typeset directly under the chord. For example: E[ Am produces peace and joy \[E&]peace and \[Am]joy If whitespace (a space or hreturni) immediately follows, then the chord name be typeset without any lyric text below it, indicating that the chord is to be struck between any surrounding words. For example: E[ produces peace and \[E&]peace and \[Am] joy Am joy If the lyric text that immediately follows the chord contains another chord, and if the width of the chord name exceeds the width of the lyric text, then hyphenation is added automatically. For example: F #sus4 A produces e \[F#sus4]e\[A]ternal - ternal Sequences of chords that sit above a single word can be written back-to-back with no intervening space, or as a single chord: A B Em \[A]\[B]\[Em]joy produces joy \[A B Em]joy produces joy A B Em 11 The only difference between the two examples above is that the chords in the first example can later be replayed separately (see §7.4) whereas the chords in the second example can only be replayed as a group. You can explicitly dictate how much of the text following a chord macro is to appear under the chord name by using braces. To exclude text that would normally be drawn under the chord, use a pair of braces that includes the chord macro. For example: GA produces e - ternal {\[G A]e}ternal (Without the braces, the syllables “ternal” would not be pushed out away from the chord.) This might be used to indicate that the chord transition occurs on the first syllable rather than as the second syllable is sung. Contrastingly, braces that do not include the chord itself can be used to include text under a chord that would otherwise be excluded. For example: Gmaj7sus4 produces th’ eternal \[Gmaj7sus4]{th’ eternal} Without the braces, the word “eternal” would be pushed out away from the chord so that the chord would appear only over the partial word “th’ ”. \nolyrics Chords Without Lyrics. Sometimes you may want to write a line of chords with no lyrics in it at all, such as for an instrumental intro or solo. To make the chords in such a line sit on the baseline instead of raised above it, use the \nolyrics macro. For example: produces Intro: {\nolyrics Intro: \[G] \[A] \[D]} G A D Note the enclosing braces that determine how long the effect should last. Multiple lines can be included in the braces. Instrumental solos should typically not appear in lyric books, so such lines should usually also be surrounded by \ifchorded and \fi (see §11.4). \DeclareLyricChar Symbols Under Chords. If you are typesetting songs in a language whose alphabet contains symbols that LATEX treats as punctuation, you can use the \DeclareLyricChar macro to instruct the s ngs package to treat the symbol as non-chord-ending, so that it is included under chords by default just like an alphabetic character. ¯ \DeclareLyricChar{htokeni} Here, htokeni must be a single TEX macro control sequence, active character, letter (something TEX assigns catcode 11), or punctuation symbol (something TEX assigns catcode 12). For example, by default, Fmaj7 produces s \[Fmaj7]s\dag range - †range because \dag is not recognized as an alphabetic symbol; but if you first type, 12 \DeclareLyricChar{\dag} then instead you will get: Fmaj7 produces s†range \[Fmaj7]s\dag range \DeclareNonLyric Likewise, you can type \DeclareNonLyric{htokeni} \DeclareNoHyphen \MultiwordChords to reverse the above effect and force a token to be lyric-ending. Such tokens are pushed out away from long chord names so that they never fall under a chord, and hyphenation is added to the resulting gap. To declare a token to be lyric-ending but without the added hyphenation, use \DeclareNoHyphen{htokeni} instead. Such tokens are pushed out away from long chord names so that they never fall under the chord, but hyphenation is not added to the resulting gap. Extending Chords Over Adjacent Words. The \MultiwordChords macro forces multiple words to be squeezed under one chord by default. Normally a long chord atop a short lyric pushes subsequent lyrics away to make room for the chord: Gmaj7sus4 produces my \[Gmaj7sus4]my life life But if you first type \MultiwordChords, then instead you get the more compact: Gmaj7sus4 produces my life \[Gmaj7sus4]my life Authors should exercise caution when using \MultiwordChords because including many words under a single chord can often produce output that is ambiguous or misleading to musicians. For example, F G Am produces me free \[F G Am]me free This might be misleading to musicians if all three chords are intended to be played while singing the word “me.” Liberal use of braces is therefore required to make \MultiwordChords produce good results, which is why it isn’t the default. \shrp \flt Accidentals Outside Chords. Sharp and flat symbols can be produced with # and & when they appear in chord macros, but if you wish to produce those symbols in other parts of the document, you must use the \shrp and \flt macros. For example, to define a macro that produces a C # chord, use: \newcommand{\Csharp}{C\shrp} 13 7.4 ^ Replaying Chords ¯ Many songs consist of multiple verses that use the same chords. The s ngs package simplifies this common case by providing a means to replay the chord sequence of a previous verse without having to retype all the chords. To replay a chord from a previous verse, type a hat symbol (^) anywhere you would otherwise use a chord macro (\[]). For example, \beginverse \[G]This is the \[C]first \[G]verse. \endverse \beginverse The ^second verse ^ has the same ^chords. \endverse produces G C G This is the first verse. G The second verse C G has the same chords. Normal chords can appear amidst replayed chords without disrupting the sequence of chords being replayed. Thus, a third verse could say, \beginverse The ^third verse ^has a \[Cm]new ^chord. \endverse to produce G C Cm G The third verse has a new chord. \memorize Replaying can be used in combination with automatic transposition to produce modulated verses. See §10 for an example. By default, chords are replayed from the current song’s first verse, but you can replay the chords of a different verse or chorus by saying \memorize at the beginning of any verse or chorus whose chords you want to later replay. Subsequent verses or choruses that use ^ replay chords from the most recently memorized verse or chorus. Selective Memorization. It is also possible to inject unmemorized chords into a memorized verse so that they are not later replayed. To suppress memorization of a chord, begin the chord’s name with a hat symbol. For example, \beginverse\memorize The \[G]third \[C]chord will \[^Cm]not be re\[G]played. \endverse \beginverse When ^replaying, the ^unmemorized chord is ^skipped. \endverse 14 produces G C Cm G The third chord will not be replayed. G C G When replaying, the unmemorized chord is skipped. This is useful when the first verse of a song has something unique, like an intro that won’t be repeated in subsequent verses, but has other chords that you wish to replay. ¯ \newchords Memorizing Multiple Chord Sequences. By default, the s ngs package only memorizes one sequence of chords at a time and ^ replays chords from that most recently memorized sequence. However, you can memorize and replay multiple independent sequences using the macros described in the following paragraphs. Memorized or replayed chord sequences are stored in chord-replay registers. To declare a new chord-replay register, type \newchords{hregnamei} where hregnamei is any unique alphabetic name. Once you’ve declared a register, you can memorize into that register by providing the hregnamei as an optional argument to \memorize: \memorize[hregnamei] \replay Memorizing into a non-empty register replaces the contents of that register with the new chord sequence. To replay chord from a particular register, type \replay[hregnamei] Subsequent uses of ^ reproduce chords from the sequence stored in register hregnamei. Register contents are global, so you can memorize a chord sequence from one song and replay it in others. You can also use \replay multiple times in the same verse or chorus to replay a sequence more than once. 7.5 \brk Line and Column Breaks Line Breaking. To cause a long line of lyrics to be broken in a particular place, put the \brk macro at that point in the line. This does not affect lines short enough to fit without breaking. For example, \beginverse This is a \brk short line. But this is a particularly long line of lyrics \brk that will need to be wrapped. \endverse produces 15 This is a short line. But this is a particularly long line of lyrics that will need to be wrapped. Column Breaks Within Songs. To suggest a column break within a verse or chorus too long to fit in a single column, use \brk on a line by itself. If there are no \brk lines in a long verse, it is broken somewhere that a line does not wrap. (A wrapped line is never divided by a column break.) If there are no \brk lines in a long chorus, it overflows the column, yielding an overfull vbox warning. \nextcol \sclearpage \scleardpage Column Breaks Between Songs. To force a column break between songs, use \nextcol, \brk, \sclearpage, or \scleardpage between songs. The \nextcol macro ends the column by leaving blank space at the bottom. The \brk macro ends the current column in lyric books by stretching the preceeding text so that the column ends flush with the bottom of the page. (In non-lyric books \brk is identical to \nextcol.) The \sclearpage macro is like \nextcol except that it shifts to the next blank page if the current page is nonempty. The \scleardpage macro is like \sclearpage except that it shifts to the next blank even-numbered page in two-sided documents. Column breaks usually need to be in different places in different book types. To achieve this, use a conditional block from §11.4. For example, \ifchorded\else\ifslides\else\brk\fi\fi forces a column break only in lyric books but does not affect chord books or books of overhead slides. When a partial list of songs is being extracted with \includeonlysongs, \brk, \nextcol, \clearpage, and \cleardpage macros between songs must be followed by a star to have any effect. To force a column-break at a specific point in a partial book, add the word nextcol, brk, clearpage, or cleardpage at the corresponding point in the argument to \includeonlysongs. 7.6 \echo Echoes and Repeats Echo Parts. To typeset an echo part, use \echo{hlyrics and chordsi}. Echo parts are parenthesized and italicized. For example, Alle\[G]luia! \echo{Alle\[A]luia!} \rep A Repeated Lines. To indicate that a line should be sung multiple times by all singers, put \rep{hni} at the end of the line. For example, produces Alleluia! (×4) Alleluia! \rep{4} \lrep \rrep G produces Alleluia! (Alleluia!) To indicate exactly where repeated parts begin and end, use \lrep and \rrep to create begin- and end-repeat signs. For example, 16 \lrep \[G]Alleluia!\rrep \rep{4} 7.7 \measurebar | \mbar :G : :Alleluia!: (×4) Measure Bars Measure bars can be added to chord books in order to help musicians keep time when playing unfamiliar songs. To insert a measure bar, type either \measurebar or type the vertical pipe symbol (“|”). For example, G produces Alle luia Alle|\[G]luia \meter produces In order for measure bars to be displayed, the showmeasures option must be enabled. Measure bars are only displayed by default in chord books. The first measure bar in a song has meter numbers placed above it to indicate the time signature of the piece. By default, these numbers are 4/4, denoting four quarter notes per measure. To change the default, type \meter{hni}{hd i} somewhere after the \beginsong line of the song but before the first measure bar, to declare a time signature of hni hd ith notes per measure. You can also change meters mid-song either by using \meter in the middle of the song or by typing \mbar{hni}{hd i} to produce a measure bar with a time signature of hni/hd i. For example, \meter{6}{8} \beginverse |Sing to the |heavens, ye \mbar{4}{4}saints of |old! \endverse produces 6 8 4 4 Sing to the heavens, ye saints of old! 7.8 \textnote \musicnote Textual Notes Aside from verses and choruses, songs can also contain textual notes that provide instructions to singers and musicians. To create a textual note that is displayed in both lyric books and chord books, use: \textnote{htexti} To create a textual note that is displayed only in chord books, use: \musicnote{htexti} Both of these create a shaded box containing htexti. For example, \textnote{Sing as a two-part round.} produces 17 Sing as a two-part round. Textual notes can be placed anywhere within a song, either within verses and choruses or between them. \capo Guitar Capos. One special kind of textual note suggests to guitarists a fret on which they should put their capos. Macro \capo{hni} should be used for this purpose. It normally has the same effect as \musicnote{capo hni}; however, if the transposecapos option is active then it instead has the effect of \transpose{hni}. See §10 for more information on automatic chord transposition. 7.9 Index Entries Every song automatically gets entries in the current section’s title index(es). However, you can also add extra index entries for a song to any index. index= Indexing Lyrics. For example, title indexes often have entries for memorable lines of lyrics in a song in addition to the song’s title. You can add an index entry for the current song to the section’s title index(es) by adding index={hlyricsi} to the song’s \beginsong line. For example, \beginsong{Doxology} [index={Praise God from Whom all blessings flow}] causes the song to be indexed both as “Doxology” and as “Praise God from Whom all blessings flow” in the section’s title index(es). You can use index= multiple times in a \beginsong line to produce multiple additional index entries. Index entries produced with index={hlyricsi} are typeset in an upright font instead of in italics to distinguish them from song titles. ititle= Indexing Extra Song Titles. To add a regular index entry typeset in italics to the title index(es), use: ititle={htitlei} \indexentry \indextitleentry in the \beginsong line instead. Like index= keyvals, ititle= can be used multiple times to produce multiple additional index entries. You can also create index entries by saying \indexentry[hindexesi]{hlyricsi} (which creates an entry like index=) or \indextitleentry[hindexesi]{htitlei} (which creates an entry like ititle=). These two macros can be used anywhere between the song’s \beginsong and \endsong lines, and can be used multiple times to produce multiple entries. If specified, hindexesi is a comma-separated list of the identifiers of indexes to which the entry should be added. Otherwise the new entry is added to all of the title indexes for the current songs environment. 18 7.10 \ch Chords in Ligatures This subsection covers an advanced topic and can probably be skipped by those creating song books for non-professional use. The \[ macro is the normal means by which chords should be inserted into a song; however, a special case occurs when a chord falls within a ligature. Ligatures are combinations of letters or symbols that TEX normally typesets as a single font character so as to produce cleaner-looking output. The only ligatures in English are: ff, fi, fl, ffi, and ffl. Other languages have additional ligatures like æ and œ. Notice that in each of these cases, the letters are “squished” together to form a single composite symbol. When a chord macro falls inside a ligature, LATEX fails to compact the ligature into a single font character even in non-chorded versions of the book. To avoid this minor typographical error, use the \ch macro to typeset the chord: \ch{hchord i}{hprei}{hposti}{hfull i} where hchord i is the chord text, hprei is the text to appear before the hyphen if the ligature is broken by auto-hyphenation, hposti is the text to appear after the hyphen if the ligature is broken by auto-hyphenation, and hfull i is the full ligature if it is not broken by hyphenation. For example, to correctly typeset \[Gsus4]dif\[G]ficult, in which the G chord falls in the middle of the “ffi” ligature, one should use: G produces difficult di\ch{G}{f}{fi}{ffi}cult \mch This causes the “ffi” ligature to appear intact yet still correctly places the G chord over the second f. To use the \ch macro with a replayed chord name (see §7.4), use ^ as the hchord i. The \mch macro is exactly like the \ch macro except that it also places a measure bar into the ligature along with the chord. For example, G produces dif ficult di\mch{G}{f}{fi}{ffi}cult places both a measure bar and a G chord after the first “f” in “difficult”, yet correctly produces an unbroken “ffi” ligature in copies of the book in which measure bars are not displayed. In the unusual case that a meter change is required within a ligature, this can be achieved with a construction like: 6 8 G \meter{6}{8}di\mch{G}{f}{fi}{ffi}cult produces dif ficult The \meter macro sets the new time signature, which appears above the next measure bar—in this case the measure bar produced by the \mch macro. Chords and measure bars produced with ^ or | are safe to use in ligatures. Thus, dif|^ficult requires no special treatment; it leaves the “ffi” ligature intact when measure bars are not being displayed. 19 8 Between Songs Never put any material directly into the top level of a songs environment. Doing so will disrupt the page-builder, usually producing strange page breaks and blank pages. To safely put material between songs, use one of the environments described in this section. 8.1 intersong Intersong Displays To put column-width material between the songs in a songs environment, use an intersong environment: \begin{intersong} .. . \end{intersong} intersong* Material contributed in an intersong environment is subject to the same columnbreaking rules as songs (see §11.5), but all other formatting is up to you. By default, LATEX inserts interline glue below the last line of an intersong environment. To suppress this, end the intersong content with \par\nointerlineskip. To instead put page-width material above a song, use an intersong* environment: \begin{intersong*} .. . \end{intersong*} songgroup This starts a new page if the current page already has column-width material in it. By default, all intersong displays are omitted when generating a partial book with \includeonlysongs. You can force them to be included whenever a particular song is included by using a songgroup environment: \begin{songgroup} .. . \end{songgroup} Each songgroup environment may include any number of intersong, intersong*, or scripture quotations (see §8.2), but must include exactly one song. When using \includeonlysongs, the entire group is included in the book if the enclosed song is included; otherwise the entire group is omitted. 8.2 \beginscripture \endscripture Scripture Quotations Starting a Scripture Quotation. A special form of intersong block typesets a scripture quotation. Scripture quotations begin and end with 20 \beginscripture{href i} .. . \endscripture where href i is a scripture reference that is typeset at the end of the quotation. The href i argument should conform to the same syntax rules as for the href i arguments passed to \beginsong macros (see §7). The text of the scripture quotation between the \beginscripture and \endscripture lines are parsed in normal paragraph mode. For example: \beginscripture{James 5:13} Is any one of you in trouble? He should pray. Is anyone happy? Let him sing songs of praise. \endscripture produces Is any one of you in trouble? He should pray. Is anyone happy? Let him sing songs of praise. James 5:13 \Acolon \Bcolon Tuplets. To typeset biblical poetry the way it appears in most bibles, begin each line with either \Acolon or \Bcolon. A-colons are typeset flush with the left margin, while B-colons are indented. Any lines too long to fit are wrapped with double-width hanging indentation. For example, \beginscripture{Psalm 1:1} \Acolon Blessed is the man \Bcolon who does not walk in the counsel of the wicked \Acolon or stand in the way of sinners \Bcolon or sit in the seat of mockers. \endscripture produces Blessed is the man who does not walk in the counsel of the wicked or stand in the way of sinners or sit in the seat of mockers. Psalm 1:1 \strophe Stanzas. Biblical poetry is often grouped into stanzas or “strophes”, each of which is separated from the next by a small vertical space. You can create that vertical space by typing \strophe. For example, 21 \beginscripture{Psalm 88:2-3} \Acolon May my prayer come before you; \Bcolon turn your ear to my cry. \strophe \Acolon For my soul is full of trouble \Bcolon and my life draws near the grave. \endscripture produces May my prayer come before you; turn your ear to my cry. For my soul is full of trouble and my life draws near the grave. Psalm 88:2–3 \scripindent \scripoutdent Indented Blocks. Some bible passages, such as those that mix prose and poetry, contain indented blocks of text. You can increase the indentation level within a scripture quotation by using \scripindent and decrease it by using \scripoutdent. For example, \beginscripture{Hebrews 10:17-18} Then he adds: \scripindent \Acolon ‘‘Their sins and lawless acts \Bcolon I will remember no more.’’ \scripoutdent And where these have been forgiven, there is no longer any sacrifice for sin. \endscripture produces Then he adds: “Their sins and lawless acts I will remember no more.” And where these have been forgiven, there is no longer any sacrifice for sin. Hebrews 10:17–18 9 \gtab Guitar Tablatures Guitar tablature diagrams can be created by using the construct \gtab{hchord i}{hfreti:hstringsi:hfingeringi} 22 where the hfreti and hfingeringi parts are both optional (and you may omit any colon that borders an omitted argument). hchord i is a chord name to be placed above the diagram. hfreti is an optional digit (any number from 2 to 9) placed to the left of the diagram. hstringsi should be a series of symbols, one for each string of the guitar from lowest pitch to highest. Each symbol should be one of: X if that string is not to be played, 0 (zero or the letter O) if that string is to be played open, or one of 1 through 9 if that string is to be played on the given numbered fret. hfingeringi is an optional series of digits, one for each string of the guitar from lowest pitch to highest. Each digit should be one of: 0 if no fingering information is to be displayed for that string (e.g., if the string is not being played or is being played open), or one of 1 through 4 to indicate that the given numbered finger is to be used to hold down that string. Here are some examples to illustrate: ×◦ ◦ ••• produces \gtab{A}{X02220:001230} A 1 2 3 C #sus4 ×× • produces 4 •• • \gtab{C#sus4}{4:XX3341} B[ • • ••• × produces \gtab{B&}{X13331} \minfrets By default, tablature diagrams always consist of at least 4 fret rows (more if the hstringsi argument contains a number larger than 4). To change the minimum number of fret rows, change the value of \minfrets. For example, typing \minfrets=1 causes tablature diagrams to have only as many rows are required to accommodate the largest digit appearing in the hstringsi argument. 10 \transpose Automatic Transposition You can automatically transpose some or all of the chords in a song up by hni half-steps by adding the line \transpose{hni} 23 somewhere between the song’s \beginsong line and the first chord to be transposed. For example, if a song’s first chord is \[D], and the line \transpose{2} appears before it, then the chord appears as an E in the resulting document. Specifying a negative number for hni transposes subsequent chords down instead of up. The \transpose macro affects all chords appearing after it until the \endsong line. If two \transpose macros appear in the same song, their effects are cumulative. When the transposecapos option is active, the \capo macro acts like \transpose. See §7.8 for more information. \preferflats \prefersharps Enharmonics. When using \transpose to automatically transpose the chords of a song, the s ngs package code chooses between enharmonically equivalent names for “black key” notes based on the first chord of the song. For example, if \transpose{1} is used, and if the first chord of the song is an E, then all A chords that appear in the song are transcribed as B [ chords rather than A# chords, since the key of F-major (E transposed up by one half-step) has a flatted key signature. Usually this guess produces correct results, but if not, you can use either \preferflats or \prefersharps after the \transpose line to force all transcription to use flatted names or sharped names respectively, when resolving enharmonic equivalents. ¯ Modulated Verses. Automatic transposition can be used in conjunction with chord-replaying (see §7.3) to produce modulated verses. For example, \beginverse\memorize \[F#]This is a \[B/F#]memorized \[F#]verse. \[E&7] \endverse \transpose{2} \beginverse ^This verse is ^modulated up two ^half-steps. \endverse produces F# B/F # F# This is a memorized verse. A[ E [7 D [/A[ A[ This verse is modulated up two half-steps. \trchordformat Both Keys. By default, when chords are automatically transposed using \transpose, only the transposed chords are printed. However, in some cases you may wish to print the old chords and the transposed chords together so that musicians playing transposing and non-transposing instruments can play from the same piece of music. This can be achieved by redefining the \trchordformat 24 macro, which receives two arguments—the original chord name and the transposed chord name, respectively. For example, to print the old chord above the new chord above each lyric, define \renewcommand{\trchordformat}[2]{\vbox{\hbox{#1}\hbox{#2}}} \solfedge \alphascale \notenames Changing Note Names. In many countries it is common to use the solfedge names for the notes of the scale (LA, SI, DO, RE, MI, FA, SOL) instead of the alphabetic names (A, B, C, D, E, F, G ). By default, the transposition logic only understands alphabetic names, but you can tell it to look for solfedge names by typing \solfedge. To return to alphabetic names, type \alphascale. You can use other note names as well. To define your own note names, type \notenames{hnameAi}{hnameB i}. . .{hnameGi} where each of hnameAi through hnameGi must consist entirely of a sequence of one or more uppercase letters. For example, some solfedge musicians use TI instead of SI for the second note of the scale. To automatically transpose such music, use: \notenames{LA}{TI}{DO}{RE}{MI}{FA}{SOL} \notenamesin \notenamesout ¯ The s ngs package can also automatically convert one set of note names to another. For example, suppose you have a large song book in which chords have been typed using alphabetic note names, but you wish to produce a book that uses the equivalent solfedge names. You could achieve this by using the \notenamesin macro to tell the s ngs package which note names you typed in the input file, and then using \notenamesout to tell the s ngs package how you want it to typeset each note name in the output file. The final code looks like this: ¯ ¯ \notenamesin{A}{B}{C}{D}{E}{F}{G} \notenamesout{LA}{SI}{DO}{RE}{MI}{FA}{SOL} The syntaxes of \notenamesin and \notenamesout are identical to that of \notenames (see above), except that the arguments of \notenamesout can consist of any LATEX code that is legal in horizontal mode, not just uppercase letters. To stop converting between note names, use \alphascale, \solfedge, or \notenames to reset all note names back to identical input and output scales. \transposehere Transposing Chords In Macros. The automatic transposition logic won’t find chord names that are hidden inside macro bodies. For example, if you abbreviate a chord by typing, \newcommand{\mychord}{F\shrp sus4/C\shrp} \transpose{4} \[\mychord] then the \transpose macro fails to transpose it; the resulting chord is still an F #sus4/C # chord. To fix the problem, you can use \transposehere in your macros to explicitly invoke the transposition logic on chord names embedded in macro bodies. The above example could be corrected by instead defining: 25 \newcommand{\mychord}{\transposehere{F\shrp sus4/C\shrp}} \notrans Transposition can be suppressed within material that would otherwise be transposed by using the \notrans macro. For example, writing \transposehere{G = \notrans{G}} would typeset a transposed G followed by a non-transposed G chord. This does not suppress note name conversion (see \notenames). To suppress both transposition and note name conversion, just use braces (e.g., {G} instead of \notrans{G}). \gtabtrans Transposing Guitar Tablatures. The songs package cannot automatically transpose tablature diagrams (see §9). Therefore, when automatic transposition is taking place, only the chord names of \gtab macros are displayed (and transposed); the diagrams are omitted. To change this default, redefine the \gtabtrans macro, whose two arguments are the two arguments to \gtab. For example, to display original tablatures without transposing them even when transposition has been turned on, write \renewcommand{\gtabtrans}[2]{\gtab{\notrans{#1}}{#2}} To transpose the chord name but not the diagram under it, replace \notrans{#1} with simply #1 in the above. To restore the default behavior, write \renewcommand{\gtabtrans}[2]{\transposehere{#1}} 11 Customizing the Book 11.1 songnum Song and Verse Numbering Song Numbering. The songnum counter defines the next song’s number. It is set to 1 at the beginning of a songs environment and is increased by 1 after each \endsong. It can be redefined anywhere except within a song. For example, \setcounter{songnum}{3} \thesongnum sets the next song’s number to be 3. You can change the song numbering style for a song section by redefining \thesongnum. For example, to cause songs to be numbered A1, A2, etc., in the current song section, type \renewcommand{\thesongnum}{A\arabic{songnum}} \printsongnum The expansion of \thesongnum must always produce plain text with no font formatting or unexpandable macro tokens, since its text is exported to auxiliary index generation files where it is sorted. To change the formatting of song numbers as they appear at the beginning of each song, redefine the \printsongnum macro, which expects the text yielded by \thesongnum as its only argument. For example, to typeset song numbers in italics atop each song, define 26 \renewcommand{\printsongnum}[1]{\it\LARGE#1} \songnumwidth The \songnumwidth length defines the width of the shaded boxes that contain song numbers at the beginning of each song. For example, to make each such box 2 centimeters wide, you could define \setlength{\songnumwidth}{2cm} \nosongnumbers versenum If \songnumwidth is set to zero, song numbers are not shown at all. To turn off song numbering entirely, type \nosongnumbers. This inhibits the display of the song number atop each song (but song numbers are still be displayed elsewhere, such as in indexes). The same effect can be achieved by setting \songnumwidth to zero. Verse Numbering. The versenum counter defines the next verse’s number. It is set to 1 after each \beginsong line and is increased by 1 after each \endverse (except if the verse begins with \beginverse*). The versenum counter can be redefined anywhere within a song. For example, \setcounter{versenum}{3} \theversenum sets the next verse’s number to be 3. You can change the verse numbering style by redefining \theversenum. For example, to cause verses to be numbered in uppercase roman numerals, define \renewcommand{\theversenum}{\Roman{versenum}} \printversenum To change the formatting of verse numbers as they appear at the beginning of each verse, redefine the \printversenum macro, which expects the text yielded by \theversenum as its only argument. For example, to typeset verse numbers in italics, define \renewcommand{\printversenum}[1]{\it\LARGE#1.\ } \versenumwidth The \versenumwidth length defines the horizontal space reserved for verse numbers to the left of each verse text. Verse text is shifted right by this amount. For example, to reserve half a centimeter of space for verse numbers, define \setlength{\versenumwidth}{0.5cm} \noversenumbers \placeversenum Verse numbers whose widths exceed \versenumwidth indent the first line of the verse an additional amount to make room, but subsequent lines of the verse are only indented by \versenumwidth. To turn off verse numbering entirely, use \noversenumbers. This is equivalent to saying \renewcommand{\printversenum}[1]{} \setlength{\versenumwidth}{0pt} The horizontal placement of verse numbers within the first line of each verse is controlled by the \placeversenum macro. By default, each verse number is placed flush-left. Authors interested in changing the placement of verse numbers should consult §16.2 of the implementation section for more information on this macro. 27 11.2 \lyricfont Song Appearance Font Selection. By default, lyrics are typeset using the document-default font (\normalfont) and with the document-default point size (\normalsize). You can change these defaults by redefining \lyricfont. For example, to cause lyrics to be typeset in small sans serif font, you could define \renewcommand{\lyricfont}{\sffamily\small} \stitlefont Song titles are typeset in a sans-serif, slanted font by default (sans-serif, upright if producing slides). You can change this default by redefining \stitlefont. For example, to cause titles to be typeset in a roman font, you could define \renewcommand{\stitlefont}{\rmfont\Large} \versefont \chorusfont \notefont You can apply additional font changes to verses, choruses, and textual notes produced with \textnote and \musicnote by redefining \versefont, \chorusfont, and \notefont, respectively. For example, to typeset choruses in italics, you could define \renewcommand{\chorusfont}{\it} \notebgcolor \snumbgcolor The colors of shaded boxes containing textual notes and song numbers can be changed by redefining the \notebgcolor and \snumbgcolor macros. For example: \renewcommand{\notebgcolor}{red} \printchord By default, chords are typeset in sans serif oblique (slanted) font. You can customize chord appearance by redefining \printchord, which accepts the chord text as its argument. For example, to cause chords to be printed in roman boldface font, you could define \renewcommand{\printchord}[1]{\rmfamily\bf#1} \sharpsymbol \flatsymbol Accidental Symbols. By default, sharp and flat symbols are typeset using LATEX’s \# (#) and \flat ([) macros. Users can change this by redefining \sharpsymbol and \flatsymbol. For example, to use \sharp (]) instead of #, one could redefine \sharpsymbol as follows. \renewcommand{\sharpsymbol}{\ensuremath{^\sharp}} \everyverse \everychorus Verse and Chorus Titles. The \everyverse macro is executed at the beginning of each verse, and \everychorus is executed at the beginning of each chorus. Thus, to begin each chorus with the word “Chorus:” one could type, \renewcommand{\everychorus}{\textnote{Chorus:}} 28 \versesep Spacing Options. The vertical distance between song verses and song choruses is defined by the skip register \versesep. For example, to put 12 points of space between each pair of verses and choruses, with a flexibility of plus or minus 2 points, you could define \versesep=12pt plus 2pt minus 2pt \afterpreludeskip \beforepostludeskip The vertical distance between the song’s body and its prelude and postlude material is controlled by skips \afterpreludeskip and \beforepostludeskip. This glue can be made stretchable for centering effects. For example, to cause each song body to be centered on the page with one song per page, you could write: \songcolumns{1} \spenalty=-10000 \afterpreludeskip=2pt plus 1fil \beforepostludeskip=2pt plus 1fil \baselineadj The vertical distance between the baselines of consecutive lines of lyrics is computed by the s ngs package based on several factors including the lyric font size, the chord font size (if in chorded mode), and whether slides mode is currently active. You can adjust the results of this computation by redefining skip register \baselineadj. For example, to reduce the natural distance between baselines by 1 point but allow an additional 1 point of stretching when attempting to balance columns, you could define ¯ \baselineadj=-1pt plus 1pt minus 0pt \clineparams To change the vertical distance between chords and the lyrics below them, redefine the \clineparams macro with a definition that adjusts the LATEX parameters \baselineskip, \lineskiplimit, and \lineskip. For example, to cause the baselines of chords and their lyrics to be 12 points apart with at least 1 point of space between the bottom of the chord and the top of the lyric, you could write: \renewcommand{\clineparams}{ \baselineskip=12pt \lineskiplimit=1pt \lineskip=1pt } \cbarwidth The width of the vertical line that appears to the left of choruses is controlled by the \cbarwidth length. To eliminate the line entirely (and the spacing around it), you can set \cbarwidth to 0pt: \setlength{\cbarwidth}{0pt} \sbarheight The height of the horizontal line that appears between each pair of songs is controlled by the \sbarheight length. To eliminate the line entirely (and the spacing around it), you can set \sbarheight to 0pt: \setlength{\sbarheight}{0pt} 29 \extendprelude \showauthors \showrefs Song Top and Bottom Material. You can adjust the header and footer material that precedes and concludes each song by redefining \extendprelude and \extendpostlude. By default, \extendprelude displays the song’s authors and scripture references using the macros \showauthors and \showrefs. The following definition changes it to also print copyright info: \renewcommand{\extendprelude}{ \showrefs\showauthors {\bfseries\songcopyright\par} } \extendpostlude By default, \extendpostlude prints the song’s copyright and licensing information as a single paragraph using \songcopyright and \songlicense. The following definition changes it to also print the words “Used with permission” at the end of every song’s footer information: \renewcommand{\extendpostlude}{ \songcopyright\ \songlicense\unskip \ Used with permission. } \makeprelude \makepostlude In general, any macro documented in §12 can be used in \extendprelude and \extendpostlude to print song information, such as \songauthors, \songrefs, \songcopyright, and \songlicense. For convenience, the \showauthors and \showrefs macros display author and scripture reference information as a preformatted paragraph the way it appears in the default song header blocks. See §11.8 for how to define new \beginsong keyvals and use them in \extendprelude. For complete control over the appearance of the header and footer material that precedes and concludes each song, you can redefine the macros \makeprelude and \makepostlude. When typesetting a song, the s ngs package code invokes both of these macros once (after processing all the material between the \beginsong and \endsong lines), placing the results within vboxes. The resulting vboxes are placed atop and below the song content. By default, \makeprelude displays the song’s titles, authors, and scripture references to the right of a shaded box containing the song’s number; and \makepostlude displays the song’s copyright and licensing information in fine print. ¯ \vvpenalty \ccpenalty \vcpenalty \cvpenalty \brkpenalty Page- and Column-breaking. Page-breaking and column-breaking within songs that are too large to fit in a single column/page is influenced by the values of several penalties. Penalties of value \interlinepenalty are inserted between consecutive lines of each verse and chorus; penalties of value \vvpenalty, \ccpenalty, \vcpenalty, and \cvpenalty are inserted into each song between consecutive verses, between consecutive choruses, after a verse followed by a chorus, and after a chorus followed by a verse, respectively; and penalties of value \brkpenalty are inserted wherever \brk is used on a line by itself. The higher the penalty, the less likely TEX is to place a page- or column-break at that site. If any are set to 30 \sepverses −10000 or lower, breaks are forced there. By default, \interlinepenalty is set to 1000 and the rest are set to 200 so that breaks between verses and choruses are preferred over breaks within choruses and verses, but are not forced. Saying \sepverses sets all of the above penalties to −10000 except for \ccpenalty which is set to 100. This is useful in slides mode because it forces each verse and chorus to be typeset on a separate slide, except for consecutive choruses, which remain together when possible. (This default reflects an expectation that consecutive choruses typically consist of a pre-chorus and chorus that are always sung together.) These defaults can be changed by changing the relevant penalty register directly. For example, to force a page- or column-break between consecutive choruses, type \ccpenalty=-10000 \versejustify \chorusjustify \justifyleft \justifycenter Text Justification. To cause verse or chorus text to be justified flushleft or centered, set \versejustify or \chorusjustify to \justifyleft or \justifycenter, respectively. For example, to cause choruses to be centered, one could type: \renewcommand{\chorusjustify}{\justifycenter} \notejustify \placenote Justification of textual notes too long to fit on a single line is controlled by the \notejustify macro. By default, it sets up an environment that fully justifies the note (i.e., all but the last line of each paragraph extends all the way from the left to the right margin). Authors interested in changing this behavior should consult §16.2 of the implementation section for more information about this macro. A textual note that is shorter than a single line is placed flush-left by default, or is centered when in slides mode. This placement of textual notes is controlled by \placenote. Authors interested in changing this behavior should consult §16.2 of the implementation section for more information about this macro. 11.3 \scripturefont Scripture Appearance By default, scripture quotations are typeset in Zaph Chancery font with the document-default point size (\normalsize). You can change these defaults by redefining \scripturefont. For example, to cause scripture quotations to be typeset in sans serif italics, define: \renewcommand{\scripturefont}{\sffamily\it} \printscrcite By default, the citation at the end of a scripture quotation is typeset in sans serif font at the document-default point size (\normalsize). You can customize the appearance of the citation by redefining \printscrcite, which accepts the citation text as its argument. For example, to cause citations to be printed in roman italics font, define: \renewcommand{\printscrcite}[1]{\rmfamily\it#1} 31 Type Processed only if. . . chorded lyric slides partiallist the the the the songindexes measures rawtext transcapos nolyrics pagepreludes vnumbered the the the the the the the chorded option is active chorded option is not active slides option is active \includeonlysongs macro is being used to extract a partial list of songs noindexes option is not active nomeasures option is not active rawtext option is active transposecapos option is active \nolyrics macro is in effect \pagepreludes macro is in effect current verse is numbered (i.e., it was started with \beginverse instead of \beginverse*) Table 1: Conditional macros 11.4 \if... Conditional Blocks Conditional macros allow certain material to be included in some books but not others. For example, a musician’s chord book might include extra verses with alternate chordings. A conditional block begins with a macro named \ifhtypei, where htypei is one of the types listed in the first column of Table 1. The conditional block concludes with the macro \fi. Between the \ifhtypei and the \fi may also appear an \else. For example, in the construction \ifchorded hAi \else hB i \fi material hAi is only included if the chorded option is active, and material hB i is only included if the chorded option is not active. 11.5 \songcolumns Page Layout The number of columns per page can be set with \songcolumns. For example, to create 3 columns per page, write \songcolumns{3} The number of columns should only be changed outside of songs environments. 32 Setting the number of columns to zero disables the page-building algorithm entirely. This can be useful if you want to use an external package, such as multicol or LATEX’s built-in \twocolumn macro, to build pages. For example, the following sets up an environment that is suitable for a lyric book that uses \twocolumn: \songcolumns{0} \flushbottom \twocolumn[\LARGE\centering My Songs] \begin{songs}{} .. . \end{songs} When disabling the page-builder, please note the following potential issues: • The \repchoruses feature does not work when the page-builder is disabled because the page-builder is responsible for inserting repeated choruses as new columns are formed. • External page-building packages tend to allow column- and page-breaks within songs because they have no mechanism for moving an entire song to the next column or page to avoid such a break (see \songpos below). • Indexes produced with \showindex are typeset to the width of the enclosing environment. Thus, you should be sure to reset LATEX back to one column (via \onecolumn) before executing \showindex. \pagepreludes \columnsep Song preludes (i.e., the material atop each song, including the title) are typeset by default at column width. Writing \pagepreludes typesets subsequent preludes at page width atop fresh pages, with the rest of the song in multiple columns beneath its title. (To prohibit separation of songs from their preludes, it also sets \songpos to 0.) The horizontal distance between consecutive columns is controlled by the \columnsep dimension. For example, to separate columns by 1 centimeter of space, write \columnsep=1cm \colbotglue When LATEX ends each column it inserts glue equal to \colbotglue. In lyric books this macro is set to 0pt so that each column ends flush with the bottom of the page. In other books that have ragged bottoms, it is set to stretchable glue so that columns end at whatever vertical position is convenient. The recommended setting for typsetting columns with ragged bottoms is: \renewcommand{\colbotglue}{0pt plus .5\textheight minus 0pt} \lastcolglue The last column in a songs environment gets \lastcolglue appended to it instead. By default it is infinitely stretchable so that the last column ends at its natural height. By setting it to 0pt, you can force the last column to be flush with the bottom of the page: 33 \renewcommand{\lastcolglue}{0pt} \songpos ¯ The s ngs package uses a song-positioning algorithm that moves songs to the next column or page in order to avoid column- or page-breaks within songs. The algorithm has four levels of aggressiveness, numbered from 0 to 3. You can change the aggressiveness level by typing \songpos{hlevel i} \spenalty The default level is 3, which avoids column-breaks, page-breaks, and page-turns within songs whenever possible. (Page-turns are page-breaks after odd-numbered pages in two-sided documents, or after all pages in one-sided documents.) Level 2 avoids page-breaks and page-turns but allows column-breaks within songs. Level 1 avoids only page-turns within songs. Level 0 turns off the song-positioning algorithm entirely. This causes songs to be positioned wherever TEX thinks is best based on penalty settings (see \vvpenalty and \spenalty). The value of \spenalty controls the undesirability of column breaks at song boundaries. Usually it should be set to a value between 0 and \vvpenalty so that breaks between songs are preferable to breaks between verses within a song. By default it is set to 100. When it is −10000 or less, breaks between songs are required, so that each song always begins a fresh column. 11.6 \indexsongsas Indexes Index Appearance. By default, the right-hand side of each index entry contains a list of one or more song numbers. To instead list page numbers, use the \indexsongsas macro: \indexsongsas{hid i}{\thepage} \sepindexestrue \sepindexesfalse \idxrefsfont where hid i is the same identifier used in the \newindex, \newauthorindex, or \newscripindex macro that created the index. The second argument must always be something that expands into raw text without any formatting, since this text gets output to auxiliary files that are lexographically sorted by the index-generation program. To go back to indexing songs by song number, use \thesongnum in place of \thepage in the above. Indexes are by default typeset on separate pages, and when an index is sufficiently small, it is centered on the page in one column. To disable these defaults, write \sepindexesfalse. This causes indexes to avoid using unnecessary vertical space or starting unnecessary new pages. To re-enable the defaults, use \sepindexestrue. To control the formatting of the list of references on the right-hand side of index entries, redefine \idxrefsfont. For example, to typeset each list in boldface, write \renewcommand{\idxrefsfont}{\bfseries} 34 \idxtitlefont \idxlyricfont Title indexes contain entries for song titles and also entries for notable lines of lyrics. The fonts for these entries are controlled by \idxtitlefont and \idxlyricfont, respectively. For example, to show title entries in boldface sansserif and lyric entries in regular roman font, one could define: \renewcommand{\idxtitlefont}{\sffamily\bfseries} \renewcommand{\idxlyricfont}{\rmfamily\mdseries} \idxheadfont To change the font used to typeset the capital letters that start each alphabetic section of a large title index, redefine \idxheadfont. For example, to typeset those letters in italics instead of boldface, type \renewcommand{\idxheadfont}{\sffamily\it\LARGE} \idxbgcolor To change the background color of the shaded boxes that contain the capital letters that start each alphabetic sectino of a large title index, redefine \idxbgcolor. For example: \renewcommand{\idxbgcolor}{red} \idxheadwidth The \idxheadwidth length defines the width of the shaded boxes that begin each alphabetic block of a large title index. Setting it to 0pt suppresses the boxes entirely. For example, to set the width of those boxes to 1 centimeter, you could define \setlength{\idxheadwidth}{1cm} \idxauthfont The font used to typeset entries of an author index is controlled by \idxauthfont. For example, to typeset such entries in italics instead of boldface, type \renewcommand{\idxauthfont}{\small\it} \idxscripfont The font used to typeset entries of a scripture index is controlled by \idxscripfont. For example, to typeset such entries in boldface instead of italics, type \renewcommand{\idxscripfont}{\sffamily\small\bfseries} \idxbook To control the formatting of the lines that start each new book of the bible in a scripture index, redefine \idxbook, which accepts the book name as its single argument. For example, to typeset each book name in a box, one could define \renewcommand{\idxbook}[1]{\framebox{\small\bfseries#1}} \idxcont In a scripture index, when a column break separates a block of entries devoted to a book of the bible, the new column is titled “hbooknamei (continued)” by default. You can change this default by redefining the \idxcont macro, which receives the hbooknamei as its single argument. For example, to typeset an index in German, one might define \renewcommand{\idxcont}[1]{\small\textbf{#1} (fortgefahren)} 35 \songtarget \songlink PDF bookmarks and links. Each song environment adds a PDF bookmark (if generating a PDF) and hyperlink target (if using the hyperref package) for the song by invoking \songtarget with two arguments: (1) a suggested PDF bookmark level, and (2) a link target name. Links in indexes to these targets are created by \songlink, which also gets two arguments: (1) the link target name (same as the second argument to \songtarget), and (2) the text to be linked. Redefine these macros to customize or suppress these bookmarks and targets. For example, to enable both bookmarks and links (the default behavior) use: \renewcommand{\songtarget}[2] {\pdfbookmark[#1]{\thesongnum. \songtitle}{#2}} \renewcommand{\songlink}[2]{\hyperlink{#1}{#2}} To enable links but not bookmarks, use: \renewcommand{\songtarget}[2]{\hypertarget{#2}{\relax}} \renewcommand{\songlink}[2]{\hyperlink{#1}{#2}} To disable both bookmarks and links, use: \renewcommand{\songtarget}[2]{} \renewcommand{\songlink}[2]{#2} \titleprefixword Alphabetization Options. In English, when a title begins with “The” or “A”, it is traditional to move these words to the end of the title and sort the entry by the following word. So for example, “The Song Title” is typically indexed as “Song Title, The”. To change this default behavior, you can use \titleprefixword in the document preamble to identify each word to be moved to the end whenever it appears as the first word of a title index entry. For example, to cause the word “I” to be moved to the end of title index entries, one could say, \titleprefixword{I} The first use of \titleprefixword overrides the defaults, so if you also want to continue to move “The” and “A” to the end of entries, you must also say \titleprefixword{The} and \titleprefixword{A} explicitly. This macro may only be used in the document preamble but may be used multiple times to declare multiple prefix words. \authsepword Special Words In Song Info. When parsing author index entries, the word “and” is recognized by the songidx program as a conjunctive that separates author names. To override this default and specify a different conjunctive, use the \authsepword macro one or more times in the document preamble. For example, to instead treat “und” as a conjunctive, you could say, \authsepword{und} 36 \authbyword The first use of \authsepword and each of the following macros overrides the default, so if you also want to continue to treat “and” as a conjunctive, you must also say \authsepword{and} explicitly. The \authsepword macro and each of the following macros may only be used in the document preamble but may be used multiple times to declare multiple special words. When parsing author index entries, the word “by” is recognized as a keyword signaling that the index entry should only include material in the current list item that follows the word “by”. So for example, “Music by J.S. Bach” is indexed as “Bach, J.S.” rather than “Bach, Music by J.S.” To recognize a different word instead of “by”, you can use \authbyword in the document preamble. For example, to recognize “durch” instead, you could say \authbyword{durch} \authignoreword When parsing author index entries, if a list item contains the word “unknown”, that item is ignored and is not indexed. This prevents items like “Composer unknown” from being indexed as names. To cause the indexer to recognize and ignore a different word, you can use the \authignoreword macro in the document preamble. For example, to ignore author index entries containing the word “unbekannt”, you could say, \authignoreword{unbekannt} 11.7 Page Headers and Footers In LATEX, page headers and footers are defined using a system of invisible marks that get inserted into the document at the beginning of each logical unit of the document (e.g., each section, song, verse, and chorus). The headers and footers are then defined so as to refer to the first and/or last invisible mark that ends up on each page once the document is divided into pages. This section describes the marks made available by the s ngs package. For more detailed information about the marks already provided by LATEX and how to use them, consult any LATEX user manual. To add song information to page headings and footers, redefine \songmark, \versemark, or \chorusmark to add the necessary TEX marks to the current page whenever a new song, verse, or chorus begins. These macros expect no arguments; to access the current song’s information including titles, use the macros documented in §12. To access the current song’s number or the current verse’s number, use \thesongnum or \theversenum (see §11.1). For example, to include the song number in the page headings produced by LATEX’s \pagestyle{myheadings} feature, you could redefine \songmark as follows: ¯ \songmark \versemark \chorusmark \renewcommand{\songmark}{\markboth{\thesongnum}{\thesongnum}} 37 11.8 \newsongkey Defining New Beginsong Keyvals The \beginsong macro supports several optional keyval parameters for declaring song information, including by=, sr=, and cr=. Users can define their own additional keyvals as well. To do so, use the \newsongkey macro, which has the syntax \newsongkey{hkeynamei}{hinitcodei}[hdefaulti]{hsetcodei} Here, hkeynamei is the name of the new key for the keyval, hinitcodei is LATEX code that is executed at the start of each \beginsong line before the \beginsong arguments are processed, hdefaulti (if specified) is the default value used for the keyval when hkeynamei appears in \beginsong without a value, and hsetcodei is macro code that is executed whenever hkeyi is parsed as part of the \beginsong keyval arguments. In hsetcodei, #1 expands to the value given by the user for the keyval (or to hdefaulti if no value was given). For example, to define a new song key called arr which stores its value in a macro called \arranger, one could write: \newcommand{\arranger}{} \newsongkey{arr}{\def\arranger{}} {\def\arranger{Arranged by #1\par}} Then one could redefine \extendprelude to print the arranger below the other song header information: \renewcommand{\extendprelude}{ \showrefs\showauthors {\bfseries\arranger} } A \beginsong line could then specify the song’s arranger as follows: \beginsong{The Title}[arr={R. Ranger}] .. . \endsong This produces 1 The Title Arranged by R. Ranger For more detailed information about keyvals and how they work, consult the documentation for David Carlisle’s keyval package, which comes standard with most LATEX 2ε installations. 38 11.9 Font Kerning Corrections Chord Overstriking. In order to conserve space and keep songs readable, the s ngs package pushes chords down very close to the lyrics with which they are paired. Unfortunately, this can sometimes cause low-hanging characters in chord names to overstrike the lyrics they sit above. For example, ¯ (Gsus4/D) produces Overstrike \[(Gsus4/D)]Overstrike \chordlocals Note that the parentheses and slash symbols in the chord name have invaded the lyric that sits beneath them. The best solution to this problem is to use a font for chord names that minimizes low-hanging symbols; but if you lack such a font, then the following trick works pretty well. Somewhere in the preamble of your document, you can write the following LATEX code: \renewcommand{\chordlocals}{\catcode‘(\active \catcode‘)\active \catcode‘/\active} \newcommand{\smraise}[1]{\raise2pt\hbox{\small#1}} \newcommand{\myslash}{\smraise/} \newcommand{\myopenparen}{\smraise(} \newcommand{\mycloseparen}{\smraise)} {\chordlocals \global\let(\myopenparen \global\let)\mycloseparen \global\let/\myslash} This sets the /, (, and ) symbols as active characters whenever they appear within chord names. (See §16.2 for documentation of the \chordlocals hook.) Each active character is defined so that it produces a smaller, raised version of the original symbol. The result is as follows: (Gsus4/D) produces Overstrike (fixed) \[(Gsus4/D)]Overstrike (fixed) As you can see, the low-hanging symbols have been elevated so that they sit above the baseline, correcting the overstrike problem. \shiftdblquotes ¯ Scripture Font Quotation Marks. The s ngs package compensates for a kerning problem in the Zaph Chancery font (used to typeset scripture quotations) by redefining the ‘‘ and ’’ token sequences to be active characters that yield double-quotes shifted 1.1 points and 2 points left, respectively, of their normal positions. If you use a different font size for scripture quotations, then you can use the \shiftdblquotes macro when redefining \scripturefont to change this kerning correction. For example, \renewcommand{\scripturefont}{ \usefont{OT1}{pzc}{mb}{it} \shiftdblquotes{-1pt}{-2pt}{-3pt}{-4pt} } 39 removes 1 point of space to the left and 2 points of space to the right of leftdouble-quote characters, and 3 points to the left and 4 points to the right of right-double-quotes, within scripture quotations. 12 \songauthors \songrefs \songcopyright \songlicense \songtitle \resettitles \nexttitle \foreachtitle \songlist Informational Macros The macros described in this section can be used to retrieve information about the current song. This can be used when redefining \extendprelude, \extendpostlude, \makeprelude, \makepostlude, \songmark, \versemark, or \chorusmark, or any other macros that might typeset this information. To get the current song’s list of authors (if any) use \songauthors. This yields the value of the by= key used in the \beginsong line. To get the current song’s list of scripture references (if any) use \songrefs. This yields the value of the sr= key used in the \beginsong line, but modified with hyphens changed to en-dashes and spaces falling within a list of verse numbers changed to thin spaces for better typesetting. In addition, various penalties have been added to inhibit line breaks in strange places and encourage line breaks in others. To get the current song’s copyright info (if any), use \songcopyright. This yields the value of the cr= key used in the \beginsong line. To get the current song’s licensing information (if any), use \songlicense. This yields the value of the li= key used in the \beginsong line, or whatever text was declared with \setlicense. The \songtitle macro yields the current song’s title. By default this is the first title provided in the \beginsong line. The \nexttitle and \foreachtitle macros (see below) cause it to be set to the current song’s other titles, if any. To get the current song’s primary title (i.e., the first title specified in the song’s \beginsong line), execute \resettitles. This sets the \songtitle macro to be the song’s primary title. To get the song’s next title, execute \nexttitle, which sets \songtitle to be the next title in the song’s list of titles (or sets \songtitle to \relax if there are no more titles). The \foreachtitle macro accepts LATEX code as its single argument and executes it once for each (remaining) song title. Within the provided code, use \songtitle to get the current title. For example, the following code generates a comma-separated list of all of the current song’s titles: \resettitles \songtitle \nexttitle \foreachtitle{, \songtitle} When \includeonlysongs is used to extract a partial list of songs, the \songlist macro expands to the comma-separated list of songs that is being extracted. Redefining \songlist within the document preamble alters the list of songs to be extracted. Redefining it after the preamble may have unpredictable results. 40 13 Index Generation ¯ The material in this section describes macros provided by the s ngs package that are used during the automatic generation of the song book indexes. Since index generation is automatic, document authors should not normally need to use any of these macros directly. The documentation in this section is therefore provided purely for completeness and for informational purposes. For instructions on how to automatically generate indexes when compiling a song book, see §6. For info on how to customize the appearance of indexes, see §11.6. Automatic generation of song book indexes is a three stage process: 1. Each time a song book LATEX file is compiled, an auxiliary file named hfilenamei.sxd is written out for each hfilenamei defined using \newindex, \newauthorindex, or \newscripindex. These .sxd files are plain text files that can be viewed using any standard text editor. They begin with a line identifying the type of index (title, author, or scripture) and then contain triples of lines, one triple for each song to appear in the index. The first line of a triple has the information by which the song is to be indexed (a title, author, or scripture reference). The second line has the song’s number in the book (yielded by \thesongnum). The third line is an identifying label for the song used in hyperlinking. 2. Once the .sxd files have been generated, an external program is used to transform each .sxd file into a .sbx file. Since the standard makeindex program provided with LATEX is not powerful enough to sort scripture references, distributions of s ngs package come with a specialized songidx program to do this. ¯ 3. The .sbx files produced by the songidx program are then read in by the \showindex macro next time the source document is compiled using LATEX. These .sbx files consist of the macros and environments described below. idxblock In indexes that are blocked off into sections, one for each letter of the alphabet, the hfilenamei.sbx files generated for that index consist of a series of idxblock environments, one for each such section. An idxblock environment begins and ends with \begin{idxblock}{hletter i} .. . \end{idxblock} \idxentry \idxaltentry where hletter i is the letter of the alphabet for that block. The index entries themselves are created by lines of the form \idxentry{hleftsidei}{hrightsidei} \indexaltentry{hleftsidei}{hrightsidei} 41 each of which creates an index entry with hleftsidei on the left, followed by a series of dots, followed by hrightsidei on the right. The \indexentry macro is used for “normal” entries (e.g., titles in a title index), and \indexaltentry is used for “alternate” entries (e.g., lyric lines in a title index). Within hrightsidei, multiple items are separated with \\ macros instead of commas. When used in an index .sbx file, the \\ macro produces a comma followed by some complex spacing that allows index lines to be broken suitably if they are too long to fit in one physical line. 14 Other Resources There are a number of other LATEX packages available for typesetting songs, tablature diagrams, or song books. Probably the best of these is the Song[ook package by Christopher Rath (http://rath.ca/Misc/Songbook/). Most of the differences between other packages and this one are intentional; the following is a summary of where I’ve adopted various differing design decisions and why. ¯ Ease of Song Entry. Much of the s ngs package programming is devoted to easing the burden of typing chords. With most LATEX song book packages the user types chords using a standard LATEX macro syntax like \chord{hchord i}{hlyrici}. The s ngs package uses a less conventional \[hchord i]hlyrici syntax for several reasons detailed below. First, macros in the standard LATEX syntax require more key-presses than macros in the s ngs package’s syntax. This can become become very taxing when typing up a large book. Chords often appear as frequently as one per syllable, especially in hymns, so keeping the syntax as brief as possible is desirable. Second, the standard LATEX macro syntax requires the user to estimate how much of the hlyrici will lie below the chord (because the hlyrici part must be enclosed in braces) whereas the s ngs package’s syntax does not. Estimating this accurately can be quite difficult, since in many cases the hlyrici part must include punctuation or multiple words to get proper results. The s ngs package automates this for the user, significantly easing the task of chord-entry. Third, unlike the standard LATEX chord syntax, the s ngs package’s syntax handles all hyphenation of chorded lyrics fully automatically. Extra hyphenation must be introduced in chord books wherever a chord is wider than the syllable it sits above. With the standard LATEX chord syntax such hyphenation must be introduced manually by the user (usually via a special hyphenation macro), but the s ngs package does this automatically. Fourth and finally, some other packages allow the user to use “b” in a hchord i to produce a flat symbol, whereas the s ngs package requires an “&” instead. Using “b” is more intuitive but prevents the use of “b” for any other purpose within a hchord i, such as to produce a literal “b” or to type another macro name like \hbox that contains a “b”. Consequently, the s ngs package uses the less obvious “&” symbol to produce flat symbols. ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ 42 ¯ Song Structure. The s ngs package provides a relatively small number of macros for typesetting high-level song structure, including verses, choruses, textual comments, and conditional macros that indicate that certain sections should go in chord books but not lyric books. These can be combined to typeset more sophisticated structures such as intros, bridges, brackets, endings, and the like. This is done in lieu of providing a specific macro for each of these structures since it results in greater flexibility and fewer macros for users to learn. ¯ Multiple columns. The s ngs package was designed from the ground up to produce song books with many songs per page, arranged in multiple columns. As a result, it includes elaborate support for many features not found in most other packages, such as automatic column balancing, completely customizable song header and song footer blocks, and facilities for adding beautiful scripture quotations to fill in gaps between songs. ¯ Indexes. Another major feature of the s ngs package is its support for a variety of different index types, most notably indexes arranged by scripture reference. Scripture indexes can be invaluable for planning services around particular sermons or topics. The s ngs package allows book authors to specify the names and preferred ordering of books of the bible, and automatically handles complex issues like overlapping verse ranges to produce an easy-to-read, compact, and wellordered index. Other supported indexes include those sorted by author, by title, and by notable lines of lyrics. ¯ ¯ Automatic Transposition. The s ngs package has a facility for automatically transposing songs, and even generating chord books that print the chords in multiple keys (e.g., so that a pianist and guitarist using a capo can play together from the same book). ¯ The s ngs package was developed entirely independently of all other LATEX song book packages. I originally developed the set of LATEX macros that eventually became the s ngs package in order to typeset a song book for the Graduate Christian Fellowship (GCF) at Cornell University, and the Cornell International Christian Fellowship (CICF). Once I had fine-tuned my package to be sufficiently versatile, I decided to release it for public use. At that time I noticed the Song[ook package and others, and wrote this summary of the most prominent differences. For information on more song-typesetting resources for LATEX, I recommend consulting the documentation provided with the Song[ook package. It includes an excellent list of other resources that might be of interest to creators of song books. ¯ 15 GNU General Public License Terms and Conditions For Copying, Distribution and Modification 43 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The “Program”, below, refers to any such program or work, and a “work based on the Program” means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term “modification”.) Each licensee is addressed as “you”. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program’s source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: (a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. (b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. (c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. 44 Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: (a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, (b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, (c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 45 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients’ exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and “any later version”, you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free 46 Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. No Warranty 11. Because the program is licensed free of charge, there is no warranty for the program, to the extent permitted by applicable law. Except when otherwise stated in writing the copyright holders and/or other parties provide the program “as is” without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of the program is with you. Should the program prove defective, you assume the cost of all necessary servicing, repair or correction. 12. In no event unless required by applicable law or agreed to in writing will any copyright holder, or any other party who may modify and/or redistribute the program as permitted above, be liable to you for damages, including any general, special, incidental or consequential damages arising out of the use or inability to use the program (including but not limited to loss of data or data being rendered inaccurate or losses sustained by you or third parties or a failure of the program to operate with any other programs), even if such holder or other party has been advised of the possibility of such damages. 47 16 Implementation ¯ The following provides the verbatim implementation of the s ngs LATEX package, along with commentary on how it works. In general, macro names that contain a @ symbol are not intended to be directly accessible by the outside world; they are for purely internal use. All other macros are intended to be used or redefined by document authors. Most of the macros likely to be of real interest to song book authors can be found in §16.2. To find the implementation of any particular macro, the index at the end of this document should prove helpful. The unwary TEXer may wonder at the rather large size of the implementation. The volume and complexity of the code stems mainly from the following challenging features: • Putting chords above lyrics fully automatically requires building an entire lyric-parser in LATEX (see §16.10). • Avoiding page-turns within songs without prohibiting column-breaks requires building a completely new page-breaking algorithm (see §16.4). • The package must be able to generate an astonishing number of document variants from a common source: lyric-only books, chorded books, digital slides, transparency slides, selected song subsets, transposed songs, and combinations of the above. This is like putting six or more packages into one. • Song book indexes are far more complex than those for a prose book. See §16.15 for some of the difficulties involved. 16.1 Initialization The code in this section detects any TEX versioning or configuration settings that are relevant to the rest of the song book code. \ifSB@etex Numerous enhancements are possible when using an ε-TEX compatible version of LATEX. We start by checking to see whether ε-TEX primitives are available. \newif\ifSB@etex \ifx\eTeXversion\undefined\else 3 \ifx\eTeXversion\relax\else 4 \SB@etextrue 5 \IfFileExists{etex.sty}{\RequirePackage{etex}}{} 6 \fi 7 \fi 1 2 \ifSB@pdf Detect whether we’re generating a pdf file, since this affects the treatment of hyperlinks and bookmark indexes. \newif\ifSB@pdf\SB@pdffalse \ifx\pdfoutput\undefined\else 10 \ifx\pdfoutput\relax\else 8 9 48 \ifnum\pdfoutput<\@ne\else \SB@pdftrue 13 \fi 14 \fi 15 \fi 11 12 \ifSB@preamble Some macros have different effects depending on when they’re used in the preamble or in the document body, so we need a conditional that remembers whether we’re still in the preamble. It gets initialized to true and later changed to false once the body begins. 16 17 \newif\ifSB@preamble \SB@preambletrue \ifSB@test \ifSB@testii \SB@temp \SB@tempii \SB@tempiii \SB@tempiv \SB@tempv Reserve some control sequence names for scratch use. \SB@newcount \SB@newdimen \SB@newbox \SB@newtoks \SB@newwrite Create macros for safely allocating count, dimen, box, token, and write registers with detection for name-clashes. (Unfortunately, LATEX’s failure to do this automatically means that we can only protect against overwriting someone else’s registers, not against someone else overwriting ours.) \newif\ifSB@test \newif\ifSB@testii 20 \newcommand\SB@temp{} 21 \newcommand\SB@tempii{} 22 \newcommand\SB@tempiii{} 23 \newcommand\SB@tempiv{} 24 \newcommand\SB@tempv{} 18 19 \newcommand\SB@newcount[1]{\@ifdefinable#1{\newcount#1}} \newcommand\SB@newdimen[1]{\@ifdefinable#1{\newdimen#1}} 27 \newcommand\SB@newbox[1]{\@ifdefinable#1{\newbox#1}} 28 \newcommand\SB@newtoks[1]{\@ifdefinable#1{\newtoks#1}} 29 \newcommand\SB@newwrite[1]{\@ifdefinable#1{\newwrite#1}} 25 26 \SB@dimen \SB@dimenii \SB@dimeniii \SB@dimeniv \SB@box \SB@boxii \SB@boxiii \SB@toks \SB@cnt \SB@cntii \SB@skip \SB@envbox Reserve some temp registers for various purposes. \SB@newdimen\SB@dimen \SB@newdimen\SB@dimenii 32 \SB@newdimen\SB@dimeniii 33 \SB@newdimen\SB@dimeniv 34 \SB@newbox\SB@box 35 \SB@newbox\SB@boxii 36 \SB@newbox\SB@boxiii 37 \SB@newtoks\SB@toks 38 \SB@newcount\SB@cnt 39 \SB@newcount\SB@cntii 40 \newlength\SB@skip 30 31 Also reserve a slightly less volatile box register for per-environment use. In scripture environments it holds the scripture citation. In indexes it holds the index title text. 41 \SB@newbox\SB@envbox 49 Load David Carlisle’s keyval package for processing hkeyi=hvaluei style macro arguments. 42 \RequirePackage{keyval} 16.2 Default Parameters This section defines macros and lengths that will typically be executed or redefined by the user in the document preamble to initialize the document. (Not all of these are restricted to preamble usage, however. Many can be used throughout the document to switch styles for different sections or different songs.) \lyricfont Define the font style to use for formatting song lyrics. 43 \stitlefont \newcommand\lyricfont{\normalfont\normalsize} Define the font style to use for formatting song titles. \newcommand\stitlefont{% \sffamily\ifslides\Huge\else\slshape\Large\fi% 46 } 44 45 \versefont \chorusfont \notefont By default, verses, choruses, and textual notes just allow the \lyricfont style to continue. \newcommand\versefont{} \newcommand\chorusfont{} 49 \newcommand\notefont{} 47 48 \scripturefont Define the font style to use for formatting scripture quotations (defaults to Zapf Chancery). \newcommand\scripturefont{% \usefont{OT1}{pzc}{mb}{it}% 52 \shiftdblquotes{-1.1\p@}\z@{-2\p@}\z@% 53 } 50 51 \printscrcite Define the printing style for the citation at the end of a scripture quotation. 54 \snumbgcolor \notebgcolor \idxbgcolor \newcommand\printscrcite[1]{\sffamily\small#1} Define the background color used for shaded boxes containing song numbers, textual notes, and index section headers, respectively. To turn off all shading for a box type, use \defhmacronamei{}. \newcommand\snumbgcolor{SongbookShade} \newcommand\notebgcolor{SongbookShade} 57 \newcommand\idxbgcolor{SongbookShade} 55 56 \versejustify \chorusjustify Verses and choruses are both left-justified with hanging indentation equal to \parindent, 58 59 \newcommand\versejustify{\justifyleft} \newcommand\chorusjustify{\justifyleft} 50 \notejustify Textual notes are fully justified when they are too long to fit in a single line. \newcommand\notejustify{% \advance\baselineskip\p@\relax% 62 \leftskip\z@skip\rightskip\z@skip% 63 \parfillskip\@flushglue\parindent\z@% 64 } 60 61 \placenote Textual notes are placed flush-left. The single argument to this macro is horizontal material that comprises the note. Usually it will consist of various hboxes and specials that were produced by \colorbox. \newcommand\placenote[1]{% \leftskip\z@skip\rightskip\@flushglue\SB@cbarshift% 67 \noindent#1\par% 68 } 65 66 These counters define the current song number and verse number. They can be redefined by the user at any time. 69 70 \thesongnum \songnumstyle \newcounter{songnum} \newcounter{versenum} By default, the song numbering style will simply be an arabic number. Redefine \thesongnum to change it. (The \songnumstyle macro is obsolete and exists only for backward compatibility.) \renewcommand\thesongnum{\songnumstyle{songnum}} \newcommand\songnumstyle{} 73 \let\songnumstyle\arabic 71 72 \theversenum \versenumstyle By default, the verse numbering style will simply be an arabic number. Redefine \theversenum to change it. (The \versenumstyle macro is obsolete and exists only for backward compatibility.) \renewcommand\theversenum{\versenumstyle{versenum}} \newcommand\versenumstyle{} 76 \let\versenumstyle\arabic 74 75 \printsongnum Define the printing style for the large, boxed song numbers starting each song. 77 \printversenum Define the printing style for the verse numbers to the left of each verse. 78 \placeversenum \newcommand\printsongnum[1]{\sffamily\bfseries\LARGE#1} \newcommand\printversenum[1]{\lyricfont#1.\ } Verse numbers are placed flush-left. This is achieved by inserting horizontal glue that reverses both the \leftskip and the \parindent. The single argument to this macro is an hbox containing the verse number. \newcommand\placeversenum[1]{% \hskip-\leftskip\hskip-\parindent\relax% 81 \box#1% 82 } 79 80 51 \everyverse \everychorus The following hooks allow users to insert material at the head of each verse or chorus. 83 84 \printchord Define the printing style for chords. 85 \chordlocals \newcommand\chordlocals{} Specify the vertical distance between song verses. This gets set to a sentinel value by default; if the user doesn’t redefine it by the end of the document preamble, it gets redefined to something sensible based on other settings. 87 88 \afterpreludeskip \beforepostludeskip \newcommand\printchord[1]{\sffamily\slshape\large#1} This hook is expanded at the start of the scoping group that surrounds every chord name. Thus, it can be used to set any catcodes or definitions that should be local to chord names. 86 \versesep \newcommand\everyverse{} \newcommand\everychorus{} \newlength\versesep \versesep123456789sp\relax Users can specify the amount of vertical space that separates song prelude and postlude material from the body of the song by adjusting the following two macros. \newlength\afterpreludeskip \afterpreludeskip=2\p@\@plus4\p@ 91 \newlength\beforepostludeskip 92 \beforepostludeskip=2\p@\@plus4\p@ 89 90 \baselineadj Define an adjustment factor for the vertical distance between consecutive lyric baselines. Setting this to zero accepts the default baseline distance computed by the songs package. 93 94 \clineparams \newlength\baselineadj \baselineadj\z@skip The spacing between chords and the lyrics below them can be adjusted by changing the values of \baselineskip, \lineskiplimit, and \lineskip within the following macro. By default, \baselineskip is set to 2 points smaller than the height of the current (lyric) font, and \lineskiplimit and \lineskip are set so that chords intrude at most 2 points into the lyric below them. This helps to keep chords tight with lyrics. \newcommand\clineparams{% \baselineskip\f@size\p@% 97 \advance\baselineskip-2\p@% 98 \lineskiplimit-2\p@% 99 \lineskip-2\p@% 100 } 95 96 \parindent The \parindent length controls how far broken lyric lines are indented from the left margin. 101 \parindent.25in 52 \idxheadwidth Specify the width of the head-boxes in a large index. 102 103 \songnumwidth Set the width of the song number boxes that begin each song. We guess a suitable width by typesetting the text “999.” 104 105 \versenumwidth 107 \newlength\versenumwidth \settowidth\versenumwidth{\printversenum{9\kern1em}} This dictates the width of the vertical line placed to the left of choruses. Setting it to 0pt eliminates the line entirely. 108 109 \sbarheight \newlength\songnumwidth \settowidth\songnumwidth{\printsongnum{999.}} Set the width that is reserved for normal-sized verse numbers. (Verse numbers wider than this will indent the first line of lyrics.) 106 \cbarwidth \newlength\idxheadwidth \setlength\idxheadwidth{1.5cm} \newlength\cbarwidth \setlength\cbarwidth\p@ This dictates the height of the horizontal line placed between each pair of songs. Setting it to 0pt eliminates the line entirely. 110 111 \newlength\sbarheight \setlength\sbarheight\p@ Column- and page-breaks should typically not occur within a verse or chorus unless they are unavoidable. Thus, we set the \interlinepenalty to a high number (1000). 112 \vvpenalty \ccpenalty \vcpenalty \cvpenalty \brkpenalty \interlinepenalty\@m The following count registers define the line-breaking penalties inserted between verses, between choruses, after a verse followed by a chorus, after a chorus followed by a verse, and at \brk macros, respectively. The default value of 200 was chosen based on the following logic: Chord books should not yield underfull vbox warnings no matter how short their columns are. However, we still want to put as much material in each column as possible while avoiding intra-song column-breaks when they can be avoided. Chorded mode therefore sets \colbotglue with glue whose stretchability is half of the \textheight. Such glue will stretch at most twice its stretchability, yielding a badness of 800 in the worst case. The default \vbadness setting starts issuing warnings at badness 1000, so we set the penalties below to 1000 − 800 = 200. \SB@newcount\vvpenalty\vvpenalty200 \SB@newcount\ccpenalty\ccpenalty200 115 \SB@newcount\vcpenalty\vcpenalty200 116 \SB@newcount\cvpenalty\cvpenalty200 117 \SB@newcount\brkpenalty\brkpenalty200 113 114 53 \spenalty The following penalty gets inserted between songs. Setting it to a proper value is a somewhat delicate balancing act. It should typically be something between 0 and the default penalties above, so for now it defaults to 100. To start each song on a fresh column/page, set it to −10000 or below. 118 \songmark \versemark \chorusmark \SB@newcount\spenalty\spenalty100 The user can redefine the following macros to add TEX marks for each song, each verse, or each chorus. Such marks are used by LATEX to define page headers and footers. \newcommand\songmark{} \newcommand\versemark{} 121 \newcommand\chorusmark{} 119 120 \extendprelude \extendpostlude To just add some fields to the existing \makeprelude or \makepostlude without having to redefine them entirely, users can redefine \extendprelude or \extendpostlude. By default, the prelude has the scripture references followed by the authors, and the postlude has the copyright info followed by the licensing info. 122 123 \idxheadfont Users can redefine \idxheadfont to affect the font in which each capital letter that heads a section of a title index is rendered. 124 \idxtitlefont \newcommand\idxauthfont{\small\bfseries} Users can redefine \idxrefsfont to affect the font in which the list of song references on the right-hand-side of an index entry is typeset. 129 \idxbook \newcommand\idxscripfont{\sffamily\small\slshape} Users can redefine \idxauthfont to affect the font in which contributor names are rendered in an author index. 128 \idxrefsfont \newcommand\idxlyricfont{\rmfamily} Users can redefine \idxscripfont to affect the font in which scripture references are rendered in a scripture index. 127 \idxauthfont \newcommand\idxtitlefont{\sffamily\slshape} Users can redefine \idxlyricfont to affect the font in which notable lines of lyrics are rendered in a title index. 126 \idxscripfont \newcommand\idxheadfont{\sffamily\bfseries\LARGE} Users can redefine \idxtitlefont to affect the font in which song title index entries are rendered. 125 \idxlyricfont \newcommand\extendprelude{\showrefs\showauthors} \newcommand\extendpostlude{\songcopyright\ \songlicense\unskip} \newcommand\idxrefsfont{\normalfont\normalsize} Users can redefine \idxbook to dictate the book name header in a scripture index that begins each book of the bible. 130 \newcommand\idxbook[1]{\small\bfseries#1} 54 \idxcont Users can redefine \idxcont to dictate the column header in a scripture index after a column break falls within a book of the bible. 131 \colbotglue Glue of size \colbotglue is inserted at the bottom of each column. We use a macro instead of a glue register so that this can be redefined in terms of variable quantities such as \textheight. 132 133 \lastcolglue 135 \newcommand\lastcolglue{} \let\lastcolglue\@flushglue Define the minimum number of fret rows that should appear in tablature diagrams. 136 \SB@colwidth \newcommand\colbotglue{} \let\colbotglue\z@skip Glue of size \lastcolglue is inserted at the bottom of the last column. 134 \minfrets \newcommand\idxcont[1]{\small\textbf{#1} (continued)} \SB@newcount\minfrets\minfrets4 Define a length to store the computed width of each column in a multi-column song page. The user shouldn’t set this one directly, but some users might want to refer to it in calculations. 137 \SB@newdimen\SB@colwidth 16.3 Package Options This section defines code associated with the various option settings that can be specified on the \usepackage line. Many of these options can also be turned on or off subsequent to the \usepackage line, so macros for doing that are also located here. The options are not actually processed until §16.17 because some of the macros defined here refer to macros that have not yet been defined. slides \slides (Default: off ) Turning this option on generates a book of overhead slides—one for each song. It really just amounts to changing various parameter settings. Elsewhere in the code we also consult \ifslides to determine a few default parameter settings and to use a different song preamble structure. All the parameter changes below are local to the current scope; so to undo slides mode, just put \slides within a group and end the group wherever you want the slides settings to end. \DeclareOption{slides}{\slides} \newcommand\slides{% 140 \slidestrue% 141 \def\lyricfont{\normalfont\huge}% 142 \def\chorusfont{\slshape}% 143 \def\versejustify{\justifycenter}% 144 \let\chorusjustify\versejustify 145 \def\placenote##1{\justifycenter\noindent##1\par}% 146 \scriptureoff% 147 \onesongcolumn% 148 \ifSB@preamble\ifSB@chordedspec\else\SB@chordsoff\fi\fi% 138 139 55 \spenalty-\@M% \let\colbotglue\@flushglue% \setlength\cbarwidth\z@% \setlength\sbarheight\z@% 149 150 151 152 153 \justifyleft } The \justifyleft macro sets up an environment in which lyrics are left-justified with hanging indentation equal to \parindent. It reserves spaces for verse numbers if used in a verse, and reserves space for the vertical bar left of choruses if used in a chorus. \newcommand\justifyleft{% \leftskip\parindent% 156 \ifSB@inverse\advance\leftskip\versenumwidth\fi% 157 \SB@cbarshift% 158 \parindent-\parindent% 159 } 154 155 \justifycenter The \justifycenter macro sets up an environment in which lyrics are centered on each line. Verse numbers continue to be placed flush-left, but \placeversenum is temporarily redefined to keep the rest of the line containing a verse number centered. \newcommand\justifycenter{% \centering\SB@cbarshift\rightskip\leftskip% 162 \def\placeversenum##1{% 163 \hskip-\leftskip\hskip-\parindent\relax% 164 \hangindent-\wd##1\hangafter\m@ne% 165 \box##1\hfil% 166 }% 167 } 160 161 unouter \SB@outer ¯ (Default: off ) Several macros provided by the s ngs package are, by default, declared \outer to aid in debugging. However, unusual documents may need to use these macros within larger constructs. To do so, use the unouter option to prevent any of the macros supplied by this package from being declared \outer. 168 169 rawtext \newcommand\SB@outer{\outer} \DeclareOption{unouter}{\let\SB@outer\relax} (Default: off ) Instead of generating a document, this dumps a text version of the song book to a file. This option can only be set in the \usepackage line because it dictates many top-level macro definitions. Turning rawtext on turns off the indexes by default, but this can be overridden by explicitly setting index options. (Note: Using rawtext with indexes turned on doesn’t actually work yet, but might be added in a future revision.) 170 \DeclareOption{rawtext}{\rawtexttrue\indexesoff} 56 noshading (Default: off ) Inhibit all shaded boxes (e.g., if the color package is unavailable). This option can only be set in the \usepackage line because the color package must be loaded in the preamble if at all. (Note: In a future release this might be extended to be modifiable throughout the preamble.) 171 noindexes \indexeson \indexesoff \DeclareOption{noshading}{\SB@colorboxesfalse} (Default: off ) Suppress generation of index files and displaying of in-document indexes. The \indexeson and \indexesoff macros can be used elsewhere to toggle display of indexes. Index-regeneration will occur if indexes are turned on by the end of the document. \DeclareOption{noindexes}{\indexesoff} \newcommand\indexeson{\songindexestrue} 174 \newcommand\indexesoff{\songindexesfalse} 172 173 nopdfindex (Default: off ) Suppress creation of PDF bookmark entries and hyperlinks. \DeclareOption{nopdfindex}{% 176 \let\songtarget\@gobbletwo% 177 \let\songlink\@secondoftwo% 178 } 175 \ifSB@measurespec \ifSB@chordedspec The showmeasures and chorded options interact in the sense that by default, switching one of them on or off switches the other on or off as well. However, if the user explicitly says that one should be on or off, then switching the other shouldn’t affect it. To produce this behavior, we need two extra conditionals to remember whether each of these options has been explicitly specified by the user or whether it is still in a default state. 179 180 chorded lyric \chordson \chordsoff \SB@chordson \SB@chordsoff \newif\ifSB@measurespec \newif\ifSB@chordedspec (Default: chorded) Determines whether chords should be shown. This option can be set in the \usepackage line or toggled elsewhere with the \chordson and \chordsoff macros. Chords cannot be turned on in conjunction with the rawtext option. If chords are turned on by the end of the preamble, no attempt will be made to balance columns on each page. \DeclareOption{chorded}{\chordson} \DeclareOption{lyric}{\chordsoff} 183 \newcommand\chordson{\SB@chordedspectrue\SB@chordson} 184 \newcommand\chordsoff{\SB@chordedspectrue\SB@chordsoff} 185 \newcommand\SB@chordson{% 186 \ifrawtext% 187 \SB@errrtopt% 188 \else% 189 \chordedtrue\lyricfalse% 190 \let\SB@bracket\SB@chord% 191 \let\SB@rechord\SB@@rechord% 192 \let\SB@ch\SB@ch@on% 193 \ifSB@measurespec% 194 \ifmeasures\SB@measureson\else\SB@measuresoff\fi% 181 182 57 195 196 197 198 199 200 \else% \SB@measureson% \fi% \ifSB@preamble\def\colbotglue{\z@\@plus.5\textheight}\fi% \SB@setbaselineskip% \fi% } \newcommand\SB@chordsoff{% 203 \chordedfalse\lyrictrue% 204 \def\SB@bracket##1]{\ignorespaces}% 205 \let\SB@rechord\relax% 206 \let\SB@ch\SB@ch@off% 207 \ifSB@measurespec% 208 \ifmeasures\SB@measureson\else\SB@measuresoff\fi% 209 \else% 210 \SB@measuresoff% 211 \fi% 212 \ifSB@preamble\let\colbotglue\z@skip\fi% 213 \SB@setbaselineskip% 214 } 201 202 showmeasures nomeasures \measureson \measuresoff \SB@measureson \SB@measuresoff (Default: showmeasures if chorded, nomeasures otherwise) Determines whether measure bars and meter notes should be shown. Option can be set in the \usepackage line or toggled elsewhere with the \measureson and \measuresoff macros. \DeclareOption{showmeasures}{\measureson} \DeclareOption{nomeasures}{\measuresoff} 217 \newcommand\measureson{\SB@measurespectrue\SB@measureson} 218 \newcommand\measuresoff{\SB@measurespectrue\SB@measuresoff} 219 \newcommand\SB@measureson{% 220 \measurestrue% 221 \let\SB@mbar\SB@makembar% 222 \ifchorded% 223 \let\SB@mch\SB@mch@on% 224 \else% 225 \let\SB@mch\SB@mch@m% 226 \fi% 227 \ifSB@inverse\SB@loadactives\fi% 228 \ifSB@inchorus\SB@loadactives\fi% 229 } 230 \newcommand\SB@measuresoff{% 231 \measuresfalse% 232 \let\SB@mbar\@gobbletwo% 233 \ifchorded% 234 \let\SB@mch\SB@ch@on% 235 \else% 236 \let\SB@mch\SB@ch@off% 237 \fi% 238 \ifSB@inverse\SB@loadactives\fi% 239 \ifSB@inchorus\SB@loadactives\fi% 215 216 58 240 transposecapos (Default: off ) If set, the \capo macro transposes the song instead of printing a note to use a capo. Use this option to generate a chord book for pianists who have trouble transposing or guitarists who don’t have capos. 241 noscripture \scriptureon \scriptureoff } \DeclareOption{transposecapos}{\transcapostrue} (Default: off ) Inhibits the display of scripture quotes. This option can also be toggled on and off anywhere with the \sciptureon and \scriptureoff macros. \DeclareOption{noscripture}{\SB@omitscriptrue} \newcommand\scriptureon{\SB@omitscripfalse} 244 \newcommand\scriptureoff{\SB@omitscriptrue} 242 243 onesongcolumn twosongcolumns \onesongcolumn \twosongcolumns \songcolumns (Default: onesongcolumn is the default if generating slides or rawtext, twosongcolumns otherwise) The number of columns per page is specified using the following package options and macros. In rawtext mode it must remain set to one column per page. The entire page-making system can be turned off by setting the number of columns to zero. This will cause each song to be contributed to the current vertical list without any attempt to form columns; the enclosing environment must handle the page layout. Probably this means that \repchoruses will not work, since an external package won’t know to insert repeated choruses when building pages. \DeclareOption{twosongcolumns}{\SB@numcols\tw@} \DeclareOption{onesongcolumn}{\SB@numcols\@ne} 247 \newcommand\songcolumns[1]{% 248 \SB@cnt#1\relax% 249 \ifnum\SB@cnt=\SB@numcols\else% 250 \ifSB@preamble\else{\SB@clearpage}\fi% 251 \fi% 252 \SB@numcols\SB@cnt% 253 \ifnum\SB@numcols>\z@% 254 \SB@colwidth-\columnsep% 255 \multiply\SB@colwidth\SB@numcols% 256 \advance\SB@colwidth\columnsep% 257 \advance\SB@colwidth\textwidth% 258 \divide\SB@colwidth\SB@numcols% 259 \else% 260 \ifrepchorus\SB@warnrc\fi% 261 \fi% 262 } 263 \newcommand\onesongcolumn{\songcolumns\@ne} 264 \newcommand\twosongcolumns{\songcolumns\tw@} 245 246 \includeonlysongs \songlist Display only a select list of songs and ignore the rest. \newcommand\songlist{} \newcommand\includeonlysongs[1]{% 267 \ifSB@songsenv\SB@errpl\else% 268 \partiallisttrue% 265 266 59 \renewcommand\songlist{#1}% \fi% 269 270 271 \nosongnumbers The user can turn off song numbering with the following macro. 272 \noversenumbers } \newcommand\nosongnumbers{\setlength\songnumwidth\z@} The user can turn off verse numbering with the following macro. \newcommand\noversenumbers{% \renewcommand\printversenum[1]{}% 275 \setlength\versenumwidth\z@% 276 } 273 274 \repchoruses \norepchoruses Using \repchoruses causes choruses to be automatically repeated on subsequent pages of the song. The feature requires ε-TEX because the supporting code needs an extended mark register class. \ifSB@etex \newcommand\repchoruses{% 279 \ifnum\SB@numcols<\@ne\SB@warnrc\fi% 280 \repchorustrue% 281 } 282 \else 283 \newcommand\repchoruses{\SB@erretex} 284 \fi 285 \newcommand\norepchoruses{\repchorusfalse} 277 278 \sepverses The following penalty settings cause verses and choruses to be separated onto different slides when in slides mode, except that consecutive choruses remain together when they fit. \newcommand\sepverses{% \vvpenalty-\@M% 288 \ccpenalty100 % 289 \vcpenalty\vvpenalty% 290 \cvpenalty\vvpenalty% 291 \let\colbotglue\@flushglue% 292 } 286 287 Some option settings, margins, and other lengths are finalized at the end of the preamble. That code is below. 293 \AtBeginDocument{ If the user hasn’t set the \versesep, set it to the default. \SB@setversesep 294 Initialize page layout algorithm. \songcolumns\SB@numcols 295 Macros used after this point occur outside the preamble. \SB@preamblefalse 296 297 } 60 16.4 Page-builder The following macros handle the building of pages that contain songs. They compute where best to place each song (e.g., whether to place it in the current column or move to the next column or page). The output routines for generating a partial list of songs in a specified order also can be found here. \SB@songbox The most recently processed song (or scripture quotation) is stored in this box. 298 \SB@numcols \SB@colnum Reserve two count registers to hold the total number of columns and the current column number, respectively. 299 300 \SB@colbox \SB@newbox\SB@mrkbox The following helper macro takes the max or min of two dimensions. If harg2 i=“<”, it sets harg1 i to the maximum of harg1 i and harg3 i. If harg2 i=“>”, it sets harg1 i to the minimum of harg1 i and harg3 i. 304 \SB@mkpage \SB@newbox\SB@pgbox Reserve a box register to hold marks that migrate out of songs as they get split into columns and pages. 303 \SB@maxmin \SB@newbox\SB@colbox Reserve a box register to hold the current page in progress. 302 \SB@mrkbox \SB@newcount\SB@numcols\SB@numcols\tw@ \SB@newcount\SB@colnum Reserve a box register to hold the current column in progress. 301 \SB@colbox \SB@newbox\SB@songbox \newcommand\SB@maxmin[3]{\ifdim#1#2#3#1#3\fi} The following macro is the heart of the page-building engine. It splits the contents of a box into a page of columns. If \repchoruses is active, the contents of \SB@chorusbox are additionally inserted into fresh columns created during the spitting process. The macro arguments are: 1. an integer (positive or zero) indicating whether box b should be fully emptied and committed as columns (if positive), or whether its final less-thancolumn-height remainder should be reserved as an in-progress column (if zero); 2. the box b to split; 3. a count register i equaling the column index (zero or greater) where the content of b is to begin; and 4. the desired column height. 61 Box b is split and i is incremented until i reaches \SB@numcols or b is emptied. If b is emptied and the first argument is 0, the final column is not contributed; instead it is left in b and i is left equal to the index of the column that would have been added if b had been emptied. This allows the next call to reconsider whether to end the current column here or add some or all of the next contribution to it. Otherwise, if b is emptied and the first argument is positive, the final column is contributed and i is set to one greater than the index of that column. (If i reaches \SB@numcols before b is emptied, the first argument is ignored.) Box b and count register i are globally modified. If \SB@updatepage is not redefined, boxes \SB@pgbox and \SB@mrkbox are also globally modified based on the results of the split. The implementation takes two special steps to avoid pre-committing inprogress columns (when the first macro argument is zero): First, the final split that empties box b is “undone” by reverting to a backup copy made before each split. Second, any underfull box warnings for this final split are suppressed by temporarily adding infinite-stretch \vfil glue to the bottom of the box. This strategy preserves underfull and overfull box warnings for the columns that are actually committed, but suppresses faux warnings for the last split that is undone. \newcommand\SB@mkpage[4]{% \ifvoid#2\else\begingroup% 307 \edef\SB@temp{\ifnum#2=\SB@box\SB@boxii\else\SB@box\fi}% 308 \edef\SB@tempii{\ifnum#2=\SB@boxiii\SB@boxii\else\SB@boxiii\fi}% 309 \splitmaxdepth\maxdepth\splittopskip\z@skip% 310 \ifnum#1=\z@\global\setbox#2\vbox{\unvbox#2\vfil}\fi% 311 \loop\ifnum#3<\SB@numcols% 312 \ifnum#1=\z@\setbox\SB@tempii\copy#2\fi% 313 \setbox\SB@temp\vsplit#2to#4\relax% 314 \ifvoid#2% 315 \ifnum#1=\z@% 316 \global\setbox#2\vbox{\unvbox\SB@tempii\unskip}% 317 \else% 318 \SB@updatepage% 319 \global\advance#3\@ne% 320 \fi% 321 #3\SB@numcols% 322 \else% 323 \SB@updatepage% 324 \global\advance#3\@ne% 325 \ifrepchorus\ifvoid\SB@chorusbox\else% 326 \SB@insertchorus#2% 327 \fi\fi% 328 \fi% 329 \repeat% 330 \endgroup\fi% 331 } 305 306 \SB@migrate Migrate a mark out of a recently split vertical list, but do not insert superfluous empty marks that may override previous marks. 62 \newcommand\SB@migrate[1]{% \SB@toks\expandafter{#1}% 334 \edef\SB@temp{\the\SB@toks}% 335 \ifx\SB@temp\@empty\else\mark{\the\SB@toks}\fi% 336 } 332 333 \SB@updatepage Update boxes \SB@pgbox and \SB@mrkbox immediately after splitting the contents of \SB@colbox. \newcommand\SB@updatepage{% \global\setbox\SB@mrkbox\vbox{% 339 \unvbox\SB@mrkbox% 340 \SB@migrate\splitfirstmark% 341 \SB@migrate\splitbotmark% 342 }% 343 \global\setbox\SB@pgbox\hbox{% 344 \SB@dimen\SB@colwidth% 345 \advance\SB@dimen\columnsep% 346 \multiply\SB@dimen\SB@colnum% 347 \advance\SB@dimen-\wd\SB@pgbox% 348 \unhbox\SB@pgbox% 349 \ifdim\SB@dimen=\z@\else\hskip\SB@dimen\relax\fi% 350 \box\SB@temp% 351 }% 352 } 337 338 \SB@droppage This alternate definition of \SB@updatepage drops the just-created page instead of contributing it. This allows \SB@mkpage to be called by the song-positioning algorithm as a trial run without outputting anything. 353 \SB@output \newcommand\SB@droppage{\setbox\SB@temp\box\voidb@x} This is the main output routine for the page-builder. It repeatedly calls \SB@mkpage, emitting pages as they are completed, until the remaining content of box \SB@colbox is not enough to fill a column. If the macro argument is 0, this final, in-progress column is left unfinished, pending future contributions. If the argument is positive, the final material is committed as a column. If the argument is two or greater, the entire in-progress page is also committed and the column number reset. \newcommand\SB@output[1]{% \ifnum\SB@numcols>\z@\begingroup% 356 \loop% 357 \SB@dimen\textheight% 358 \ifinner\else\advance\SB@dimen-\pagetotal\fi% 359 \SB@mkpage#1\SB@colbox\SB@colnum\SB@dimen% 360 \SB@testfalse\SB@testiitrue% 361 \ifnum#1>\@ne\ifvoid\SB@colbox\ifnum\SB@colnum>\z@% 362 \SB@testtrue\SB@testiifalse% 363 \fi\fi\fi% 364 \ifnum\SB@colnum<\SB@numcols\SB@testiifalse\else\SB@testtrue\fi% 365 \ifSB@test% 354 355 63 \unvbox\SB@mrkbox% \ifinner\else\kern\z@\fi% \box\SB@pgbox% \ifinner\else\vfil\break\vskip\vsize\relax\fi% \global\SB@colnum\z@% \fi% \ifSB@testii\repeat% \endgroup\else% \unvbox\SB@colbox\unskip% \fi% 366 367 368 369 370 371 372 373 374 375 376 \SB@putboxes } Create a vertical list consisting of the already committed contents of the current column plus the most recently submitted song box. The LATEX primitive that should be used to contribute each box is specified in the first argument. \newcommand\SB@putboxes[1]{% \SB@dimen\ifnum\SB@numcols>\z@\ht\SB@colbox\else\p@\fi% 379 #1\SB@colbox% 380 \ifdim\SB@dimen>\z@% 381 \SB@breakpoint\spenalty% 382 \ifdim\sbarheight>\z@% 383 \vskip-\sbarheight\relax% 384 \fi% 385 \fi% 386 #1\SB@songbox% 387 } 377 378 \SB@nextcol Force n column breaks, where n is given by the first argument. The first created column is finished with the glue specified in the second argument. When the second argument is \@flushglue, this forces a break that leaves whitespace at the bottom of the column. When it’s \colbotglue, it acts like a natural column break chosen by the page-breaker. However, if the current column is empty, \@flushglue is always used so that an empty column will result. \newcommand\SB@nextcol[2]{% \ifnum#1>\z@% 390 \ifnum\SB@numcols>\z@% 391 \global\setbox\SB@colbox\vbox{% 392 \SB@cnt#1\relax% 393 \SB@dimen\ht\SB@colbox% 394 \unvbox\SB@colbox% 395 \unskip% 396 \ifdim\SB@dimen>\z@% 397 \vskip#2\relax% 398 \break% 399 \advance\SB@cnt\m@ne% 400 \fi% 401 \loop\ifnum\SB@cnt>\z@% 402 \nointerlineskip% 403 \null% 388 389 64 \vfil% \break% \advance\SB@cnt\m@ne% \repeat% 404 405 406 407 }% \SB@output1% \else% \ifnum\lastpenalty=-\@M\null\fi% \break% \fi% \fi% 408 409 410 411 412 413 414 415 \SB@selectcol This is the entrypoint to the song-positioning algorithm. It gets defined by \songpos to either \SB@@selectcol (below) or \relax (when song-positioning is turned off). 416 \SB@@selectcol } \newcommand\SB@selectcol{} Songs should be squeezed in wherever they fit, but breaking a column or page within a song should be avoided. The following macro outputs zero or more column breaks to select a good place for \SB@songbox to be contributed to the current (or the next) page. The number of column breaks is determined by temporarily setting \SB@updatepage to \SB@droppage and then calling the \SB@mkpage algorithm under various conditions to see how many columns it would contribute if we start the current song at various positions. \newcommand\SB@@selectcol{% \begingroup% 419 \SB@cnt\z@% 420 \vbadness\@M\vfuzz\maxdimen% 421 \let\SB@updatepage\SB@droppage% 422 \SB@dimen\textheight% 423 \ifinner\else\advance\SB@dimen-\pagetotal\fi% 424 \setbox\SB@boxii\vbox{\SB@putboxes\unvcopy}% 425 \SB@cntii\SB@colnum% 426 \SB@mkpage0\SB@boxii\SB@cntii\SB@dimen% 427 \SB@spos% 428 \global\SB@cnt\SB@cnt% 429 \endgroup% 430 \SB@nextcol\SB@cnt\colbotglue% 431 } 417 418 \SB@spbegnew Begin a trial typesetting of the current song on a fresh page to see if it fits within a page. \newcommand\SB@spbegnew{% \setbox\SB@boxiii\copy\SB@songbox% 434 \SB@cntii\z@% 435 \SB@mkpage0\SB@boxiii\SB@cntii\textheight% 436 } 432 433 65 \SB@spextold Tentatively extend the song previously typeset on the current even page to the next odd page to see whether it fits on a double-page. If the current page is oddnumbered, do nothing since extending the song to the next page would introduce a page-turn. \newcommand\SB@spextold{% \ifodd\c@page\else% 439 \SB@cntii\z@% 440 \SB@mkpage0\SB@boxii\SB@cntii\textheight% 441 \fi% 442 } 437 438 \SB@spextnew Extend the trial typesetting started with \SB@spbegnew to a second page to see whether the song fits on a fresh double-page. \newcommand\SB@spextnew{% \SB@cntii\z@% 445 \SB@mkpage0\SB@boxiii\SB@cntii\textheight% 446 } 443 444 \SB@spdblpg Compute the number of column breaks required to shift the current song to the next double-page if the result of the last test run fits within its page (as indicated by counter \SB@cntii). Otherwise leave the requested number of column breaks set to zero. \newcommand\SB@spdblpg{% \ifnum\SB@cntii<\SB@numcols% 449 \SB@cnt\SB@numcols% 450 \advance\SB@cnt-\SB@colnum% 451 \if@twoside\ifodd\c@page\else% 452 \advance\SB@cnt\SB@numcols% 453 \fi\fi% 454 \fi% 455 } 447 448 \SB@sposi This is the level-1 song positioning algorithm. It moves songs to the next doublepage only if doing so would avoid a page-turn that would otherwise appear within the song. \newcommand\SB@sposi{% \ifnum\SB@cntii<\SB@numcols\else\if@twoside% 458 \SB@spextold% 459 \fi\fi% 460 \ifnum\SB@cntii<\SB@numcols\else% 461 \SB@spbegnew% 462 \ifnum\SB@cntii<\SB@numcols\else\if@twoside% 463 \SB@spextnew% 464 \fi\fi% 465 \SB@spdblpg% 466 \fi% 467 } 456 457 66 \SB@sposii This is the level-2 song-positioning algorithm. It moves songs to the next page or double-page if doing so avoids a page-break or page-turn that would otherwise appear within the song. \newcommand\SB@sposii{% \ifnum\SB@cntii<\SB@numcols\else% 470 \SB@spbegnew% 471 \ifnum\SB@cntii<\SB@numcols% 472 \SB@cnt\SB@numcols% 473 \advance\SB@cnt-\SB@colnum% 474 \else% 475 \if@twoside% 476 \SB@spextold% 477 \ifnum\SB@cntii<\SB@numcols\else% 478 \SB@spextnew% 479 \SB@spdblpg% 480 \fi% 481 \fi% 482 \fi% 483 \fi% 484 } 468 469 \SB@sposiii This is the level-3 song-positioning algorithm. It moves songs to the next column, the next page, or the next double-page if doing so avoids a column-break, pagebreak, or page-turn that would otherwise appear within the song. \newcommand\SB@sposiii{% \ifnum\SB@cntii>\SB@colnum% 487 \SB@cnt\SB@colnum% 488 \advance\SB@cnt\@ne% 489 \ifnum\SB@cnt<\SB@numcols% 490 \setbox\SB@boxiii\copy\SB@songbox% 491 \SB@mkpage0\SB@boxiii\SB@cnt\SB@dimen% 492 \advance\SB@cnt\m@ne% 493 \fi% 494 \ifnum\SB@cnt>\SB@colnum% 495 \SB@cnt\z@% 496 \SB@sposii% 497 \else% 498 \SB@cnt\@ne% 499 \fi% 500 \fi% 501 } 485 486 \songpos This is the macro by which the user adjusts the aggressiveness level of the songpositioning algorithm. See the macros above for what each level does. \newcommand\songpos[1]{% \ifcase#1% 504 \let\SB@selectcol\relax% 505 \let\SB@spos\relax% 506 \or% 502 503 67 \let\SB@selectcol\SB@@selectcol% \let\SB@spos\SB@sposi% \or% \let\SB@selectcol\SB@@selectcol% \let\SB@spos\SB@sposii% \or% \let\SB@selectcol\SB@@selectcol% \let\SB@spos\SB@sposiii% \else% \SB@errspos% \fi% 507 508 509 510 511 512 513 514 515 516 517 518 \SB@spos The \SB@spos macro gets redefined by \songpos above depending on the current song-positioning aggressiveness level. By default it is set to level 3. 519 520 \SB@clearpage } \newcommand\SB@spos{} \songpos\thr@@ Output all contributed material as a new page unless there is no contributed material. In that case do nothing (i.e., don’t produce a blank page). The \SB@colbox is tested for zero height and depth rather than voidness, since sometimes it contains zero-length \splittopskip glue. \newcommand\SB@clearpage{% \SB@testtrue% 523 \ifvoid\SB@pgbox% 524 \ifdim\ht\SB@colbox=\z@\ifdim\dp\SB@colbox=\z@% 525 \SB@testfalse% 526 \fi\fi% 527 \fi% 528 \ifSB@test% 529 \SB@cnt\SB@numcols% 530 \advance\SB@cnt-\SB@colnum% 531 \SB@nextcol\SB@cnt\lastcolglue% 532 \SB@output2% 533 \fi% 534 } 521 522 \SB@cleardpage Like \SB@clearpage but shift to a fresh even-numbered page in two-sided documents. Note that this differs from LATEX’s \cleardoublepage, which shifts to odd-numbered pages. Song books prefer starting things on even-numbered pages because this maximizes the distance until the next page-turn. \newcommand\SB@cleardpage{% \SB@clearpage% 537 \if@twoside\ifodd\c@page% 538 \SB@nextcol\SB@numcols\@flushglue% 539 \fi\fi% 540 } 535 536 68 \SB@stype There are two song content submission types: column- and page-submissions. Page-submissions are page-width and go atop fresh pages unless the current page has only page-width material so far. Column-submissions are column-width and start a new page only when the current page is full. This macro gets set to the desired type for the current submission. Mostly it stays set to the default columnsubmission type. 541 \SB@stypcol \newcommand\SB@stype{\SB@stypcol} Column-submissions contribute the contents of \SB@songbox to either the current column or the next column or page, depending on where it best fits. \newcommand\SB@stypcol{% \ifnum\SB@numcols>\z@% 544 \SB@selectcol% 545 \global\setbox\SB@colbox\vbox{\SB@putboxes\unvbox}% 546 \SB@output0% 547 \else% 548 \unvbox\voidb@x% 549 \SB@breakpoint\spenalty% 550 \ifdim\sbarheight>\z@% 551 \vskip-\sbarheight\relax% 552 \fi% 553 \unvbox\SB@songbox% 554 \fi% 555 } 542 543 \SB@styppage Page-submissions go directly to the top of the nearest fresh page unless the current page has all page-width material so far. Implementation notes: The \null is needed because the page builder consults \pagetotal, which isn’t updated by TEX until a box is contributed (\unvbox doesn’t count). Both \nointerlineskips are needed because \unvbox fails to update \prevdepth, and it doesn’t make sense to inherit its value from whatever preceeded this contribution. Authors who want interline glue must therefore insert it explicitly at the bottom of their contributed text. \newcommand\SB@styppage{% \ifnum\SB@numcols>\z@% 558 \SB@clearpage% 559 \unvbox\SB@songbox% 560 \nointerlineskip\null% 561 \else% 562 \unvbox\SB@songbox% 563 \fi% 564 \nointerlineskip% 565 } 556 557 \SB@sgroup This macro controls whether songs submitted to the page-builder are actually contributed to the final document when using \includeonlysongs to generate a partial list. If \SB@sgroup is empty, then the song is silently dropped. Otherwise it is contributed only if \SB@sgroup is a member of \songlist. 69 566 567 \SB@groupcnt This counter assigns a unique integer to each item of a group. Environments that come before the group’s song are numbered decreasingly from −1. The song itself has number 0. Environments that come after the song are numbered increasingly from 1. 568 \SB@submitpart \newcommand\SB@sgroup{} \let\SB@sgroup\@empty \SB@newcount\SB@groupcnt When a song completes and we’re generating a partial list, save the song in a box so that it can be submitted at the end of the section in the order specified by \includeonlysongs. \newcommand\SB@submitpart{% \ifx\SB@sgroup\@empty\else% 571 \@for\SB@temp:=\songlist\do{% 572 \ifx\SB@temp\SB@sgroup% 573 \edef\SB@tempii{\SB@sgroup @\the\SB@groupcnt}% 574 \expandafter\SB@newbox\csname songbox@\SB@tempii\endcsname% 575 \global\expandafter\setbox 576 \csname songbox@\SB@tempii\endcsname\box\SB@songbox% 577 \global\expandafter\let% 578 \csname stype@\SB@tempii\endcsname\SB@stype% 579 \ifrepchorus\ifvoid\SB@chorusbox\else% 580 \expandafter\SB@newbox\csname chbox@\SB@tempii\endcsname% 581 \global\expandafter\setbox% 582 \csname chbox@\SB@tempii\endcsname\box\SB@chorusbox% 583 \fi\fi% 584 \fi% 585 }% 586 \global\advance\SB@groupcnt% 587 \ifnum\SB@groupcnt<\z@\m@ne\else\@ne\fi% 588 \fi% 589 \setbox\SB@songbox\box\voidb@x% 590 \setbox\SB@chorusbox\box\voidb@x% 591 } 569 570 \SB@submitsong Submit the most recently finished song (or block of other vertical material) for output. If we’re generating a partial list of songs, save it in a box instead of submitting it here. (The saved boxes will be submitted in the requested order at the end of the songs section.) \newcommand\SB@submitsong{% \ifpartiallist\SB@submitpart\else\SB@stype\fi% 594 } 592 593 \SB@submitenv Submit the \SB@envbox box as a page-width contribution. \newcommand\SB@submitenv{% \begingroup% 597 \let\SB@songbox\SB@envbox% 598 \SB@styppage% 595 596 70 \endgroup% 599 600 \SB@songlistbrk \SB@songlistnc \SB@songlistcp \SB@songlistcdp } These macros define the words that, when placed in a \songlist, force a column break at that point. Using brk produces a soft break (like \brk) that won’t leave whitespace at the bottom of the broken column in lyric books. Using nextcol produces a hard break (like \nextcol) that may insert whitespace to finish the column. Using sclearpage moves to the next page if the current page is nonempty. Using scleardpage moves to the next double-page if the current double-page is nonempty. \newcommand\SB@songlistbrk{} \def\SB@songlistbrk{brk} 603 \newcommand\SB@songlistnc{} 604 \def\SB@songlistnc{nextcol} 605 \newcommand\SB@songlistcp{} 606 \def\SB@songlistcp{sclearpage} 607 \newcommand\SB@songlistcdp{} 608 \def\SB@songlistcdp{scleardpage} 601 602 \commitsongs If we’re generating only a partial list, then wait until the end of the section and then output all the songs we saved in boxes in the order specified. \newcommand\commitsongs{% \ifpartiallist% 611 \ifnum\SB@numcols>\z@% 612 \@for\SB@temp:=\songlist\do{% 613 \ifx\SB@temp\SB@songlistnc\SB@nextcol\@ne\@flushglue\else% 614 \ifx\SB@temp\SB@songlistbrk\SB@nextcol\@ne\colbotglue\else% 615 \ifx\SB@temp\SB@songlistcp\SB@clearpage\else% 616 \ifx\SB@temp\SB@songlistcdp\SB@cleardpage\else% 617 \SB@groupcnt\m@ne\SB@finloop% 618 \SB@groupcnt\z@\SB@finloop% 619 \fi\fi\fi\fi% 620 }% 621 \else% 622 \@for\SB@temp:=\songlist\do{% 623 \ifx\SB@temp\SB@songlistnc\vfil\break\else% 624 \ifx\SB@temp\SB@songlistbrk\break\else% 625 \ifx\SB@temp\SB@songlistcp\clearpage\else% 626 \ifx\SB@temp\SB@songlistcdp% 627 \clearpage% 628 \ifodd\c@page\null\newpage\fi% 629 \else% 630 \SB@groupcnt\m@ne\SB@finloop% 631 \SB@groupcnt\z@\SB@finloop% 632 \fi\fi\fi\fi% 633 }% 634 \fi% 635 \fi% 636 \SB@clearpage% 609 610 71 637 \SB@finloop } While contributing saved material included by \includeonlysongs, this macro contributes each series of boxes grouped together as part of a songgroup environment. \newcommand\SB@finloop{% \loop\edef\SB@tempii{\SB@temp @\the\SB@groupcnt}% 640 \expandafter\ifx% 641 \csname songbox@\SB@tempii\endcsname\relax\else% 642 \setbox\SB@songbox\expandafter\box% 643 \csname songbox@\SB@tempii\endcsname% 644 \expandafter\ifx\csname chbox@\SB@tempii\endcsname\relax% 645 \repchorusfalse% 646 \else% 647 \repchorustrue% 648 \setbox\SB@chorusbox\expandafter\box% 649 \csname chbox@\SB@tempii\endcsname% 650 \fi% 651 \csname stype@\SB@tempii\endcsname% 652 \advance\SB@groupcnt\ifnum\SB@groupcnt<\z@\m@ne\else\@ne\fi% 653 \repeat% 654 } 638 639 \SB@insertchorus Insert a chorus into the first marked spot in the box given in the first argument. This is usually achieved by splitting the box at the first valid breakpoint after the first \SB@cmark in the box. The box is globally modified. \newcommand\SB@insertchorus[1]{{% \vbadness\@M\vfuzz\maxdimen% 657 \setbox\SB@box\copy#1% 658 \setbox\SB@box\vsplit\SB@box to\maxdimen% 659 \edef\SB@temp{\splitfirstmarks\SB@nocmarkclass}% 660 \ifx\SB@temp\SB@nocmark\else% 661 \edef\SB@temp{\splitfirstmarks\SB@cmarkclass}% 662 \ifx\SB@temp\SB@cmark% 663 \SB@dimen4096\p@% 664 \SB@dimenii\maxdimen% 665 \SB@dimeniii\SB@dimen% 666 \loop% 667 \SB@dimeniii.5\SB@dimeniii% 668 \setbox\SB@box\copy#1% 669 \setbox\SB@box\vsplit\SB@box to\SB@dimen% 670 \edef\SB@temp{\splitfirstmarks\SB@cmarkclass}% 671 \ifx\SB@temp\SB@cmark% 672 \SB@dimenii\SB@dimen% 673 \advance\SB@dimen-\SB@dimeniii% 674 \else% 675 \advance\SB@dimen\SB@dimeniii% 676 \fi% 677 \ifdim\SB@dimeniii>2\p@\repeat% 655 656 72 \setbox\SB@box\vsplit#1to\SB@dimenii% \global\setbox#1\vbox{% \unvbox\SB@box\unskip% \SB@inversefalse\SB@prevversetrue\SB@stanzabreak% \SB@putbox\unvcopy\SB@chorusbox% \SB@inversetrue\SB@prevversefalse\SB@stanzabreak% \unvbox#1% }% 678 679 680 681 682 683 684 685 However, if the first mark is a \SB@lastcmark, it means that this chorus should go after the last verse in the song. There is no valid breakpoint there, so to get a chorus into that spot, we have to do a rather ugly hack: We pull the bottom material off the box with \unskip, \unpenalty, and \lastbox, then insert the chorus, then put the bottom material back on. This works because the highlevel structure of the bottom material should be static. Even if the user redefines \makepostlude, the new definition gets put in a single box that can be manipulated with \lastbox. However, if we ever change the high-level structure, we need to remember to change this code accordingly. \else\ifx\SB@temp\SB@lastcmark% \global\setbox#1\vbox{% \unvbox#1% \unskip% \ifdim\sbarheight>\z@% \setbox\SB@box\lastbox% \unskip\unpenalty% \fi% \setbox\SB@box\lastbox% \unskip\unskip% \SB@inversefalse\SB@prevversetrue\SB@stanzabreak% \marks\SB@nocmarkclass{\SB@nocmark}% \unvcopy\SB@chorusbox% \vskip\versesep\vskip\beforepostludeskip\relax% \nointerlineskip\box\SB@box% \ifdim\sbarheight>\z@% \nobreak\vskip2\p@\@plus\p@% \hrule\@height\sbarheight\@width\SB@colwidth% \fi% }% \fi\fi% \fi% 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 \nextcol }} End the current column (inserting vertical space as needed). This differs from column breaks produced with \brk, which does not introduce any empty vertical space. \newcommand\nextcol{% \@ifstar{\SB@nextcol\@ne\@flushglue}% 711 {\ifpartiallist\else\SB@nextcol\@ne\@flushglue\fi}% 712 } 709 710 73 \sclearpage Move to the next page if the current page is nonempty. \newcommand\sclearpage{% \@ifstar\SB@clearpage{\ifpartiallist\else\SB@clearpage\fi}% 715 } 713 714 \scleardpage Move to the next even-numbered page if the current page is odd or nonempty. \newcommand\scleardpage{% \@ifstar\SB@cleardpage{\ifpartiallist\else\SB@cleardpage\fi}% 718 } 716 717 16.5 Songs The following macros handle the parsing and formatting of the material that begins and ends each song. \SB@lop \SB@@lop \SB@emptylist \SB@ifempty \SB@titlelist \SB@titletail The following macros were adapted from Donald Knuth’s The TEXbook, for manipulating lists of the form \\item1\\item2\\...\\itemN\\. \newcommand\SB@lop[1]{\expandafter\SB@@lop\the#1\SB@@lop#1} \newcommand\SB@@lop{} 721 \def\SB@@lop\\#1\\#2\SB@@lop#3#4{\global#3{\\#2}\global#4{#1}} 722 \newcommand\SB@emptylist{} 723 \def\SB@emptylist{\\} 724 \newcommand\SB@ifempty[3]{% 725 \edef\SB@temp{\the#1}% 726 \ifx\SB@temp\SB@emptylist#2\else#3\fi% 727 } 719 720 These registers hold the full list of titles for the current song and the tail list of titles that has not yet been iterated over. 728 729 \songtitle The \songtitle macro will initially hold the primary title of the current song. The user can iterate over titles using \nexttitle or \foreachtitle. 730 \resettitles \SB@newtoks\SB@titlelist \SB@newtoks\SB@titletail \newcommand\songtitle{} Initialize the title list iterator. \newcommand\resettitles{% \global\SB@titletail\SB@titlelist% 733 \nexttitle% 734 } 731 732 74 \nexttitle Advance the title list iterator to the next title. \newcommand\nexttitle{% \SB@ifempty\SB@titletail{% 737 \global\let\songtitle\relax% 738 }{% 739 \SB@lop\SB@titletail\SB@toks% 740 \edef\songtitle{\the\SB@toks}% 741 }% 742 } 735 736 \foreachtitle Execute a block of code for each remaining title in the title list. \newcommand\foreachtitle[1]{% \ifx\songtitle\relax\else% 745 \loop#1\nexttitle\ifx\songtitle\relax\else\repeat% 746 \fi% 747 } 743 744 \ifSB@insong \ifSB@intersong \ifSB@inverse \ifSB@inchorus To help the user locate errors, keep track of which environments we’re inside and immediately signal an error if someone tries to use a song command inside a scripture quotation, etc. \newif\ifSB@songsenv\SB@songsenvfalse \newif\ifSB@insong\SB@insongfalse 750 \newif\ifSB@intersong\SB@intersongfalse 751 \newif\ifSB@inverse\SB@inversefalse 752 \newif\ifSB@inchorus\SB@inchorusfalse 748 749 \SB@closeall If an error is detected using one of the above, the following macro will contain a macro sequence sufficient to end the unclosed environment, hopefully allowing processing to continue. 753 \SB@rawrefs \songauthors \songcopyright \songlicense \songrefs The current song’s scripture references, authors, copyright info, and copyright license information are stored in these macros. \newcommand\SB@rawrefs{} \newcommand\songauthors{} 756 \newcommand\songcopyright{} 757 \newcommand\songlicense{} 754 755 When the user asks for the song’s scripture references, rather than give them the raw token list that the author entered, we return a prettier version in which spaces, dashes, and penalties have been adjusted. The prettier version is stored in the following control sequence. 758 \setlicense \newcommand\SB@closeall{} \newcommand\songrefs{} The user sets the licensing info for the current song with this command. 759 \newcommand\setlicense{\gdef\songlicense} 75 \newsongkey \SB@clearbskeys Defining a new key for \beginsong is just like the keyval package’s \define@key macro except that we must also define some initializer code for each key. This provides an opportunity to clear registers before each song. (Otherwise when a key wasn’t specified, we’d inherit the old values from the previous song.) \newcommand\SB@clearbskeys{} \newcommand\newsongkey[2]{% 762 \expandafter\gdef\expandafter\SB@clearbskeys\expandafter% 763 {\SB@clearbskeys#2}% 764 \define@key{beginsong}{#1}% 765 } 760 761 Define keys sr, by, cr, li, index, and ititle for scripture references, authors, copyright info, licensing info, lyric index entries, and alternate title index entries, respectively. \newsongkey{sr}{\def\SB@rawrefs{}\gdef\songrefs{}} {\def\SB@rawrefs{#1}\SB@parsesrefs{#1}} 768 \newsongkey{by}{\def\songauthors{}}{\def\songauthors{#1}} 769 \newsongkey{cr}{\def\songcopyright{}}{\def\songcopyright{#1}} 770 \newsongkey{li}{\setlicense{}}{\setlicense{#1}} 771 \newsongkey{index}{}{\indexentry{#1}} 772 \newsongkey{ititle}{}{\indextitleentry{#1}} 766 767 song \beginsong \SB@@beginsong \SB@bsoldfmt \SB@@bskvfmt Parse the arguments of a \beginsong macro. The \beginsong macro supports two syntaxes. The preferred syntax takes the song title(s) as its first argument and an optional keyval list in brackets as its second argument. A legacy syntax supports four arguments, all enclosed in braces, which are: the title(s), scripture references, authors, and copyright info. \newenvironment{song}{\beginsong}{\SB@endsong} \newcommand\beginsong[1]{% 775 \ifSB@insong\SB@errboo\SB@closeall\fi% 776 \ifSB@intersong\SB@errbor\SB@closeall\fi% 777 \SB@insongtrue% 778 \def\SB@closeall{\endsong}% 779 \SB@parsetitles{#1}% 780 \global\setbox\SB@songwrites\box\voidb@x% 781 \SB@clearbskeys% 782 \@ifnextchar[\SB@bskvfmt\SB@@beginsong% 783 } 784 \newcommand\SB@@beginsong{% 785 \@ifnextchar\bgroup\SB@bsoldfmt\SB@@@beginsong% 786 } 787 \newcommand\SB@bsoldfmt[3]{% 788 \SB@bskvfmt[sr={#1},by={#2},cr={#3}]% 789 } 790 \newcommand\SB@bskvfmt{} 791 \def\SB@bskvfmt[#1]{% 792 \setkeys{beginsong}{#1}% 793 \SB@@@beginsong% 794 } 773 774 76 \SB@@@beginsong Begin typesetting a song. Beginning a song involves typesetting the title and other info, adding entries to the indexes, and setting up the environment in which verses and choruses reside. \newcommand\SB@@@beginsong{% \global\SB@stanzafalse% 797 \setbox\SB@chorusbox\box\voidb@x% 798 \SB@gotchorusfalse% 799 \setbox\SB@songbox\vbox\bgroup\begingroup% 800 \ifnum\SB@numcols>\z@\hsize\SB@colwidth\fi% 801 \leftskip\z@skip\rightskip\z@skip% 802 \parfillskip\@flushglue\parskip\z@skip% 803 \SB@raggedright% 804 \global\SB@transposefactor\z@% 805 \global\SB@cr@{\\}% 806 \protected@edef\@currentlabel{\p@songnum\thesongnum}% 807 \setcounter{versenum}{1}% 808 \SB@prevversetrue% 809 \meter44% 810 \resettitles% 811 \SB@addtoindexes\songtitle\SB@rawrefs\songauthors% 812 \nexttitle% 813 \foreachtitle{\expandafter\SB@addtotitles\expandafter{\songtitle}}% 814 \resettitles% 815 \lyricfont% 816 \SB@setbaselineskip% 817 } 795 796 \SB@endsong Ending a song involves creating the song header (with \makeprelude), creating the song footer (with \makepostlude), and then assembling everything together into the \SB@songbox. The box is then submitted to the page-builder via \SB@submitsong. We do things this way instead of just contributing material directly to the main vertical list because submitting material song by song allows for a more sophisticated page-breaking algorithm than is possible with TEX’s built-in algorithm. \newcommand\SB@endsong{% \ifSB@insong% 820 \ifSB@inverse\SB@erreov\endverse\fi% 821 \ifSB@inchorus\SB@erreoc\endchorus\fi% 822 \global\SB@skip\versesep% 823 \unskip% 824 \ifrepchorus\ifvoid\SB@chorusbox\else% 825 \ifSB@prevverse\ifvnumbered% 826 \marks\SB@cmarkclass{\SB@lastcmark}% 827 \fi\fi% 828 \fi\fi% 829 \endgroup\egroup% 830 \begingroup% 831 \ifnum\SB@numcols>\z@% 832 \hsize\ifpagepreludes\textwidth\else\SB@colwidth\fi% 818 819 77 \fi% \leftskip\z@skip\rightskip\z@skip% \parfillskip\@flushglue\parskip\z@skip\parindent\z@% \global\setbox\SB@envbox\vbox{% \songmark% \unvbox\SB@songwrites% \ifpagepreludes\else\ifdim\sbarheight>\z@% \hrule\@height\sbarheight\@width\hsize% \nobreak\vskip5\p@\relax% \fi\fi% \begingroup% \resettitles% \songtarget{\ifnum\c@section=\z@1\else2\fi}% {song\theSB@songsnum-\thesongnum}% \endgroup% \vbox{\makeprelude}% \nobreak\vskip\SB@skip% \vskip\afterpreludeskip\relax% }% \ifnum\SB@numcols>\z@\hsize\SB@colwidth\fi% \global\setbox\SB@songbox\vbox{% \ifpagepreludes\else\unvbox\SB@envbox\fi% \unvbox\SB@songbox% \nobreak\vskip\SB@skip% \vskip\beforepostludeskip\relax% \nointerlineskip% \vbox{\makepostlude}% \ifdim\sbarheight>\z@% \nobreak\vskip2\p@\@plus\p@% \nointerlineskip% \hbox{\vrule\@height\sbarheight\@width\hsize}% \fi% }% \endgroup% \SB@insongfalse% \edef\SB@sgroup{\thesongnum}% \global\SB@groupcnt\z@% \ifpagepreludes\SB@submitenv\fi% \SB@submitsong% \ifnum\SB@grouplvl=\z@\let\SB@sgroup\@empty\fi% \stepcounter{songnum}% \else% \ifSB@intersong\SB@erreor\SB@closeall% \else\SB@erreot\fi% \fi% 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 \SB@setbaselineskip } Set the \baselineskip to an appropriate line height. 879 880 \newcommand\SB@setbaselineskip{% \SB@dimen\f@size\p@% 78 \baselineskip\SB@dimen\relax% \ifchorded% \setbox\SB@box\hbox{{\printchord{ABCDEFG\shrp\flt/j7}}}% \advance\baselineskip\ht\SB@box% \advance\baselineskip2\p@% \fi% \ifslides% \advance\baselineskip.2\SB@dimen\@plus.5\SB@dimen% \@minus.2\SB@dimen% \else% \advance\baselineskip\z@\@plus.1\SB@dimen\relax% \fi% \advance\baselineskip\baselineadj% 881 882 883 884 885 886 887 888 889 890 891 892 893 894 \SB@setversesep } Set the \versesep to an appropriate amount if has not already been explicitly set by the user. \newcommand\SB@setversesep{% \SB@dimen123456789sp% 897 \edef\SB@temp{\the\SB@dimen}% 898 \edef\SB@tempii{\the\versesep}% 899 \ifx\SB@temp\SB@tempii% 900 \begingroup% 901 \lyricfont% 902 \SB@dimen\f@size\p@% 903 \ifchorded% 904 \setbox\SB@box\hbox{{\printchord{ABCDEFG\shrp\flt/j7}}}% 905 \advance\SB@dimen\ht\SB@box% 906 \fi% 907 \ifslides% 908 \global\versesep1.2\SB@dimen\@plus.3\SB@dimen% 909 \@minus.3\SB@dimen% 910 \else% 911 \global\versesep.75\SB@dimen\@plus.25\SB@dimen% 912 \@minus.13\SB@dimen% 913 \fi% 914 \endgroup% 915 \fi% 916 } 895 896 \makeprelude Generate the material that begins each song. This macro is invoked at \endsong so that its code can access song info defined throughout the song. \newcommand\makeprelude{% \resettitles% 919 \ifslides% 920 \hbox to\hsize{{% 921 \hfil\stitlefont\songtitle\hfil% 922 }}% 923 \vskip5\p@% 917 918 79 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 \hbox to\hsize{% \hfil% \vbox{% \divide\hsize\tw@\parskip\p@\relax% \centering\small\extendprelude% }% \hfil% }% \else% \ifdim\songnumwidth>\z@% \setbox\SB@boxii\hbox{{\SB@colorbox\snumbgcolor{% \hbox to\songnumwidth{% \printsongnum{\thesongnum}\hfil% }% }}}% \fi% \setbox\SB@box\vbox{% \ifdim\songnumwidth>\z@% \SB@dimen\wd\SB@boxii% \advance\SB@dimen3\p@% \ifpagepreludes\multiply\SB@dimen\tw@\fi% \advance\hsize-\SB@dimen% \fi% \ifpagepreludes\centering\else\SB@raggedright\fi% \offinterlineskip\lineskip\p@% {\stitlefont% \songtitle\par% \nexttitle% \foreachtitle{(\songtitle)\par}}% \ifdim\prevdepth=\z@\kern\p@\fi% \parskip\p@\relax\tiny% \extendprelude% \kern\z@% }% \ifdim\songnumwidth>\z@% \hbox{% \ifdim\ht\SB@boxii>\ht\SB@box% \box\SB@boxii% \kern3\p@% \vtop{\box\SB@box}% \else% \SB@colorbox\snumbgcolor{\vbox to\ht\SB@box{{% \hbox to\songnumwidth{% \printsongnum{\thesongnum}\hfil% }\vfil% }}}% \kern3\p@% \box\SB@box% \fi% }% 80 \else% \unvbox\SB@box% \fi% \fi% 974 975 976 977 978 \makepostlude } Generate the material that ends each song. \newcommand\makepostlude{% \SB@raggedright\baselineskip\z@skip\parskip\z@skip\parindent\z@% 981 \tiny\extendpostlude% 982 } 979 980 \showauthors Display the author line in the prelude. \newcommand\showauthors{% \setbox\SB@box\hbox{\bfseries\sfcode‘.\@m\songauthors}% 985 \ifdim\wd\SB@box>\z@\unhbox\SB@box\par\fi% 986 } 983 984 \showrefs Display the scripture references in the prelude. \newcommand\showrefs{% \setbox\SB@box\hbox{\slshape\songrefs\vphantom,}% 989 \ifdim\wd\SB@box>\z@\unhbox\SB@box\par\fi% 990 } 987 988 \SB@next \SB@donext \SB@dothis Several macros use \futurelet to look ahead in the input stream, and then take various actions depending on what is seen. In these macros, \SB@next is assigned the token seen, \SB@dothis is assigned the action to be taken on this loop iteration, and \SB@donext is assigned the action to be taken to continue (or terminate) the loop. \newcommand\SB@next{} \newcommand\SB@donext{} 993 \newcommand\SB@dothis{} 991 992 \SB@nextname Sometimes when scanning ahead we \stringify the name of the next token. When that happens, the name is stored in this macro for safekeeping. 994 \SB@appendsp \newcommand\SB@nextname{} Append an explicit space token (catcode 10) to a token register. This is a useful macro to have around because inlining this code directly into a larger macro is harder than it seems: If you write the following code but with an explicit control sequence instead of #1, then the space immediately following the name will get stripped by the TEX parser. But invoking the following macro with a control sequence as an argument works fine, because in that case the explicit space has already been tokenized when this macro was first defined and won’t be stripped as it is expanded. 995 \newcommand\SB@appendsp[1]{#1\expandafter{\the#1 }} 81 \SB@parsetitles Parse a list of song titles. This just involves removing leading and trailing spaces from around each title in the \\-separated list. \newcommand\SB@parsetitles[1]{% \begingroup% 998 \global\SB@titlelist{\\}% 999 \SB@toks{}% 1000 \let\\\SB@titlesep% 1001 \SB@pthead#1\SB@endparse% 1002 \endgroup% 1003 } 996 997 \SB@pthead While processing tokens at the head of a title, we skip over all spaces until we \SB@@pthead reach a non-space token. \SB@@@pthead 1004 \newcommand\SB@pthead{\futurelet\SB@next\SB@@pthead} 1005 \newcommand\SB@@pthead{% 1006 \ifcat\noexpand\SB@next\@sptoken% 1007 \expandafter\SB@@@pthead% 1008 \else% 1009 \expandafter\SB@ptmain% 1010 \fi% 1011 } 1012 \newcommand\SB@@@pthead{% 1013 \afterassignment\SB@pthead% 1014 \let\SB@next= } \SB@ptloop The iterator of the title parser loop just scans the next token. 1015 \SB@ptmain \newcommand\SB@ptloop{\futurelet\SB@next\SB@ptmain} Once we’ve reached a non-space token in the title, we consume the remainder of the title as-is, except that space tokens should be trimmed from the end of each title. \newcommand\SB@ptmain{% \ifcat\noexpand\SB@next\@sptoken% 1018 \let\SB@donext\SB@ptsp% 1019 \else\ifcat\noexpand\SB@next\bgroup% 1020 \let\SB@donext\SB@ptbg% 1021 \else\ifx\SB@next\SB@endparse% 1022 \global\SB@titlelist\expandafter{\the\SB@titlelist\\}% 1023 \let\SB@donext\@gobble% 1024 \else\ifx\SB@next\\% 1025 \SB@toks{}% 1026 \def\SB@donext{\SB@ptstep\SB@pthead}% 1027 \else% 1028 \def\SB@donext{\SB@ptstep\SB@ptloop}% 1029 \fi\fi\fi\fi% 1030 \SB@donext} 1016 1017 82 \SB@ptstep Consume a non-space, non-left-brace token and add it to the current song title. If any spaces preceded it, add those too. \newcommand\SB@ptstep[2]{% \global\SB@titlelist\expandafter\expandafter\expandafter{% 1033 \expandafter\the\expandafter\SB@titlelist\the\SB@toks#2}% 1034 \SB@toks{}% 1035 #1} 1031 1032 \SB@ptbg The next title token is a left-brace. It should be balanced, so consume the entire group and add it (along with its surrounding braces) as-is to the current title. 1036 \SB@ptsp \newcommand\SB@ptbg[1]{\SB@ptstep\SB@ptloop{{#1}}} The next title token is a space. We won’t know whether to include it in the title until we see what follows it. Strings of spaces followed by the \\ title-delimiter token, or that conclude a title argument, should be stripped. So rather than add the space token to the title, we remember it in a token register for possible later inclusion. \newcommand\SB@ptsp{ \SB@appendsp\SB@toks% 1039 \afterassignment\SB@ptloop% 1040 \let\SB@next= } 1037 1038 \SB@titlesep While parsing song titles, we temporarily assign \\ a non-trivial top-level expansion (\SB@titlesep) in order to distinguish it from other macros. 1041 \SB@endparse \newcommand\SB@titlesep{SB@titlesep} The \SB@endparse token marks the end of a token sequence being parsed. If parsing works as intended, the macro should never be expanded, so produce an error if it is. \newcommand\SB@endparse{% \SB@Error{Title parsing failed}{This error should not occur.}% 1044 } 1042 1043 \SB@parsesrefs Assign the \songrefs macro a processed version of a scripture reference in which the following adjustments have been made: (1) Spaces not preceded by a comma or semicolon are made non-breaking. For example, 2 John 1:1 and Song of Solomon 1:1 become 2~John~1:1 and Song~of~Solomon~1:1, respectively. (2) Spaces between a semicolon and a book name are lengthened to en-spaces. (3) Single hyphens are lengthened to en-dashes (--). (4) Nonbreaking, thin spaces are appended to commas not followed by a space. For example John 3:16,17 becomes John~3:16,\nobreak\thinspace17. (5) Everything within an explicit group is left unchanged, allowing the user to suppress all of the above as desired. 83 To achieve this, we must change all commas, hyphens, and spaces in the scripture reference into active characters. Unfortunately, the catcodes of everything in the text were set back when the full keyval list was digested as an argument to \beginsong, so we must unset and reset the catcodes. One obvious solution is to use \scantokens from ε-TEX to do this, but that doesn’t allow us to suppress the re-catcoding process within groups, and we’d like to avoid intoducing features that require ε-TEX anyway for compatibility reasons. Therefore, we build the following small scanner instead. The scanner walks through the text token by token, replacing each important token by its active equivalent. No character codes are modified during this process and no tokens are inserted because some of these tokens might end up being arguments to multi-byte unicode character macros rather than being expanded directly. The inputenc package only cares about the character codes, not the category codes, so modifying only the category codes should be safe. \newcommand\SB@parsesrefs[1]{% \begingroup% 1047 \SB@toks{\begingroup\SB@sractives}% 1048 \SB@prloop#1\SB@endparse% 1049 \xdef\songrefs{\the\SB@toks\endgroup}% 1050 \endgroup% 1051 } 1045 1046 \SB@prloop The main loop of the scripture reference scanner identifies each space, hyphen, \SB@prstep and comma for special treatment. \SB@@prstep 1052 \newcommand\SB@prloop{\futurelet\SB@next\SB@prstep} 1053 \newcommand\SB@prstep{% 1054 \ifcat\noexpand\SB@next A% 1055 \expandafter\SB@prcpy% 1056 \else% 1057 \expandafter\SB@@prstep% 1058 \fi% 1059 } 1060 \newcommand\SB@@prstep{% 1061 \ifcat\noexpand\SB@next\@sptoken% 1062 \let\SB@donext\SB@prspace% 1063 \else\ifx\SB@next-% 1064 \let\SB@donext\SB@prhyphen% 1065 \else\ifx\SB@next,% 1066 \let\SB@donext\SB@prcomma% 1067 \else\ifx\SB@next\SB@endparse 1068 \let\SB@donext\@gobble% 1069 \else\ifcat\noexpand\SB@next\bgroup% 1070 \let\SB@donext\SB@prgr% 1071 \else% 1072 \let\SB@donext\SB@prcpy% 1073 \fi\fi\fi\fi\fi% 1074 \SB@donext% 1075 } 84 \SB@prcpy \SB@prgr Anything that isn’t one of the special tokens above, and anything in a group, is copied without modification. 1076 1077 \newcommand\SB@prcpy[1]{\SB@toks\expandafter{\the\SB@toks#1}\SB@prloop} \newcommand\SB@prgr[1]{\SB@toks\expandafter{\the\SB@toks{#1}}\SB@prloop} \SB@prcomma Commas and hyphens are replaced with active equivalents. \SB@prhyphen 1078 \newcommand\SB@prcomma[1]{} 1079 {\catcode‘,\active 1080 \gdef\SB@prcomma#1{\SB@toks\expandafter{\the\SB@toks,}\SB@prloop}} 1081 \newcommand\SB@prhyphen[1]{} 1082 {\catcode‘-\active 1083 \gdef\SB@prhyphen#1{\SB@toks\expandafter{\the\SB@toks-}\SB@prloop}} \SB@prspace \SB@@prspace Spaces are made active as well, but doing so requires some specialized code since they cannot be consumed as implicit macro arguments. \newcommand\SB@prspace[1]{} {\obeyspaces 1086 \gdef\SB@prspace{\SB@toks\expandafter{\the\SB@toks }\SB@@prspace}} 1084 1085 1087 \SB@sractives \newcommand\SB@@prspace{\afterassignment\SB@prloop\let\SB@temp= } Assign macro definitions to active commas, hyphens, spaces, and returns when the token list generated by \SB@parsesrefs is used to typeset a scripture reference list. \newcommand\SB@sractives{} {\catcode‘,\active\catcode‘-\active\obeyspaces% 1090 \gdef\SB@sractives{% 1091 \let,\SB@srcomma\let-\SB@srhyphen\let \SB@srspace% 1092 \SB@srspacing}% 1093 } 1088 1089 \SB@srspacing The space factors of semicolons and commas are what the active spaces within a scripture reference text use to decide what came before. The following sets them to their default values in case they have been changed, but sets all other space factors to 1000. \newcommand\SB@srspacing{% \nonfrenchspacing\sfcode‘\;=1500\sfcode‘\,=1250\relax% 1096 } 1094 1095 \SB@srcomma \SB@@srcomma Commas not already followed by whitespace are appended with a thin, nonbreaking space. \newcommand\SB@srcomma{,\futurelet\SB@next\SB@@srcomma} \newcommand\SB@@srcomma{% 1099 \ifx\SB@next\SB@srspace\else% 1100 \nobreak\thinspace% 1101 \fi% 1102 } 1097 1098 85 \SB@srhyphen Hyphens that are not already part of a ligature (an en- or em-dash) become en\SB@@srhyphen dashes. \SB@srdash 1103 \newcommand\SB@srhyphen{\futurelet\SB@next\SB@@srhyphen} \SB@@srdash 1104 \newcommand\SB@@srhyphen{% 1105 \ifx\SB@next\SB@srhyphen\expandafter\SB@srdash\else--\fi% 1106 } 1107 \newcommand\SB@srdash[1]{\futurelet\SB@next\SB@@srdash} 1108 \newcommand\SB@@srdash{% 1109 \ifx\SB@next\SB@srhyphen---\expandafter\@gobble\else--\fi% 1110 } \SB@srspace \SB@@srspace To compress consecutive whitespace, we ignore spaces immediately followed by more whitespace. Spaces not preceded by a semicolon or comma become nonbreaking. Most spaces following a semicolon become en-spaces with favorable breakpoints, but a special case arises for spaces between a semicolon and a digit (see \SB@srcso below). \newcommand\SB@srspace{\futurelet\SB@next\SB@@srspace} \newcommand\SB@@srspace{% 1113 \let\SB@donext\relax% 1114 \ifx\SB@next\SB@srspace\else% 1115 \ifnum\spacefactor>\@m% 1116 \ifnum\spacefactor>1499 % 1117 \ifcat\noexpand\SB@next0% 1118 \let\SB@donext\SB@srcso% 1119 \else% 1120 \penalty-5\enskip% 1121 \fi% 1122 \else% 1123 \space% 1124 \fi% 1125 \else% 1126 \nobreak\space% 1127 \fi% 1128 \fi% 1129 \SB@donext% 1130 } 1111 1112 \SB@srcso \SB@@srcso A space between a semicolon and a digit could be within a list of verse references for a common book (e.g., Job 1:1; 2:2); or it could separate the previous book from a new book whose name starts with a number (e.g., Job 1:1; 1 John 1:1). In the former case, we should just use a regular space; but in the latter case we should be using an en-space with a favorable breakpoint. To distinguish between the two, we peek ahead at the next two tokens. If the second one is a space, assume the latter; otherwise assume the former. \newcommand\SB@srcso[1]{\futurelet\SB@temp\SB@@srcso} \newcommand\SB@@srcso{% 1133 \ifx\SB@temp\SB@srspace% 1134 \penalty-5\enskip% 1131 1132 86 \else% \space% \fi% \SB@next% 1135 1136 1137 1138 1139 } 16.6 Verses and Choruses The following programming typesets song contents, including verses, choruses, and textual notes. \ifSB@stanza The following conditional remembers if we’ve seen any stanzas yet in the current song. 1140 \SB@stanzabreak \newif\ifSB@stanza End this song stanza and start a new one. \newcommand\SB@stanzabreak{% \ifhmode\par\fi% 1143 \ifSB@stanza% 1144 \SB@breakpoint{% 1145 \ifSB@inverse% 1146 \ifSB@prevverse\vvpenalty\else\cvpenalty\fi% 1147 \else% 1148 \ifSB@prevverse\vcpenalty\else\ccpenalty\fi% 1149 \fi% 1150 }% 1151 \vskip\versesep% 1152 \fi% 1153 } 1141 1142 \SB@breakpoint Insert a valid breakpoint into the vertical list comprising a song. \newcommand\SB@breakpoint[1]{% \begingroup% 1156 \ifnum#1<\@M% 1157 \SB@skip\colbotglue\relax% 1158 \SB@skip-\SB@skip% 1159 \else% 1160 \SB@skip\z@skip% 1161 \fi% 1162 \advance\SB@skip\lastskip% 1163 \unskip% 1164 \nobreak% 1165 \ifnum#1<\@M% 1166 \vskip\colbotglue\relax% 1167 \penalty#1% 1168 \fi% 1169 \vskip\SB@skip% 1170 \endgroup% 1171 } 1154 1155 87 \SB@putbox Unbox a vbox and follow it by vertical glue if its depth is unusually shallow. This ensures that verses and choruses will look equally spaced even if one of them has a final line with no descenders. \newcommand\SB@putbox[2]{% \begingroup% 1174 \SB@dimen\dp#2% 1175 #1#2% 1176 \setbox\SB@box\hbox{{\lyricfont p}}% 1177 \ifdim\SB@dimen<\dp\SB@box% 1178 \advance\SB@dimen-\dp\SB@box% 1179 \vskip-\SB@dimen% 1180 \fi% 1181 \setbox\SB@box\box\voidb@x% 1182 \endgroup% 1183 } 1172 1173 \SB@obeylines Within verses and choruses we would like to use \obeylines so that each hreturni in the source file ends a paragraph without having to say \par explicitly. The LATEX base code establishes the convention that short-term changes to \par will restore \par by setting it equal to \@par. Long-term (i.e., environment-long) changes to \par should therefore redefine \@par to restore the desired long-term definition. The following code starts a long-term redefinition of \par adhering to these conventions, and extends that definition to hreturni as well. \newcommand\SB@obeylines{% \let\par\SB@par% 1186 \obeylines% 1187 \let\@par\SB@@par% 1188 } 1184 1185 \SB@par The following replacement definition of \par constructs paragraphs in which pagebreaks are disallowed, since no wrapped line in a song should span a page- or column-break. It then inserts an interlinepenalty after the paragraph so that such penalties will appear between consecutive lines in each verse. (Note: The \endgraf macro must not be uttered within a local group since this prevents parameters like \hangindent from being reset at the conclusion of each paragraph.) \newcommand\SB@par{% \ifhmode% 1191 \SB@cnt\interlinepenalty% 1192 \interlinepenalty\@M% 1193 \endgraf% 1194 \interlinepenalty\SB@cnt% 1195 \ifSB@inchorus% 1196 \ifdim\cbarwidth>\z@\nobreak\else\SB@ilpenalty\fi% 1197 \else% 1198 \SB@ilpenalty% 1199 \fi% 1200 \fi% 1201 } 1189 1190 88 \SB@ilpenalty By default, breaking a vertical list between paragraphs incurs a penalty of zero. Thus, we only insert an explicit penalty between lines if \interlinepenalty is non-zero. This avoids cluttering the vertical list with superfluous zero penalties. \newcommand\SB@ilpenalty{% \ifnum\interlinepenalty=\z@\else% 1204 \penalty\interlinepenalty% 1205 \fi% 1206 } 1202 1203 \SB@@par This replacement definition of \@par restores the \SB@par definition of \par and then ends the paragraph. 1207 \SB@parindent Reserve a length to remember the current \parindent. 1208 \SB@everypar \SB@newdimen\SB@parindent Reserve a control sequence to hold short-term changes to \everypar. 1209 \SB@raggedright \newcommand\SB@@par{\let\par\SB@par\par} \newcommand\SB@everypar{} Perform \raggedright except don’t nuke the \parindent. \newcommand\SB@raggedright{% \SB@parindent\parindent% 1212 \raggedright% 1213 \parindent\SB@parindent% 1214 } 1210 1211 \vnumbered The following conditional remembers whether this verse is being numbered or not (i.e., it distinguishes between \beginverse and \beginverse*). 1215 \ifSB@prevverse \newif\ifvnumbered Reserve a conditional to remember if the previous block in this song was a verse. 1216 \newif\ifSB@prevverse Before replacing the little-used verse environment with a new one, issue a warning if the current definition of \verse is not the LATEX-default one. This may indicate a package clash. \CheckCommand\verse{% \let\\\@centercr% 1219 \list{}{% 1220 \itemsep\z@% 1221 \itemindent-1.5em% 1222 \listparindent\itemindent% 1223 \rightmargin\leftmargin% 1224 \advance\leftmargin1.5em% 1225 }% 1226 \item\relax% 1227 } 1217 1218 89 verse verse* \beginverse Begin a new verse. This can be done by beginning a verse environment or by using the \beginverse macro. The latter must check for a trailing star to determine whether this verse should be numbered. We use \@ifstar to scan ahead for the star, but this needs to be done carefully because while scanning we might encounter tokens that should be assigned different catcodes once the verse really begins. Thus, we temporarily invoke \SB@loadactives for the duration of \@ifstar so that everything gets the right catcode. \renewenvironment{verse} {\vnumberedtrue\SB@beginverse} 1230 {\SB@endverse} 1231 \newenvironment{verse*} 1232 {\vnumberedfalse\SB@beginverse} 1233 {\SB@endverse} 1234 \newcommand\beginverse{% 1235 \begingroup% 1236 \SB@loadactives% 1237 \@ifstar{\endgroup\vnumberedfalse\SB@beginverse}% 1238 {\endgroup\vnumberedtrue\SB@beginverse}% 1239 } 1228 1229 \SB@beginverse Start the body of a verse. We begin by inserting a mark if \repchoruses is active and this verse was preceded by a numbered verse (making this an eligible place to insert a chorus later). Verse numbering is implemented using \everypar so that if there is any vertical material between the \beginverse and the first line of the verse, that material will come before the verse number. Intervening horizontal material (e.g., \textnote) can temporarily clear \everypar to defer the verse number until later. \newcommand\SB@beginverse{% \ifSB@insong% 1242 \ifSB@inverse\SB@errbvv\endverse\fi% 1243 \ifSB@inchorus\SB@errbvc\endchorus\fi% 1244 \else% 1245 \SB@errbvt\beginsong{Unknown Song}% 1246 \fi% 1247 \ifrepchorus\ifvoid\SB@chorusbox\else% 1248 \SB@gotchorustrue% 1249 \ifSB@prevverse\ifvnumbered% 1250 \marks\SB@cmarkclass{\SB@cmark}% 1251 \fi\fi% 1252 \fi\fi% 1253 \SB@inversetrue% 1254 \def\SB@closeall{\endverse\endsong}% 1255 \SB@stanzabreak% 1256 \versemark\nobreak% 1257 \global\SB@stanzatrue% 1258 \SB@ifempty\SB@cr@\memorize{\replay[]}% 1259 \setbox\SB@box\vbox\bgroup\begingroup% 1260 \ifvnumbered% 1240 1241 90 \protected@edef\@currentlabel{\p@versenum\theversenum}% \def\SB@everypar{% \setbox\SB@box\hbox{{\printversenum{\theversenum}}}% \ifdim\wd\SB@box<\versenumwidth% \setbox\SB@box% \hbox to\versenumwidth{\unhbox\SB@box\hfil}% \fi% \ifchorded\vrule\@height\baselineskip\@width\z@\@depth\z@\fi% \placeversenum\SB@box% \gdef\SB@everypar{}% }% \else% \def\SB@everypar{% \ifchorded\vrule\@height\baselineskip\@width\z@\@depth\z@\fi% \gdef\SB@everypar{}% }% \fi% \everypar{\SB@everypar\everypar{}}% \versefont\versejustify% \SB@loadactives% \SB@obeylines% \penalty12345 % \everyverse\relax% 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 \SB@endverse } End a verse. This involves unboxing the verse material with \SB@putbox, which corrects for last lines that are unusually shallow. \newcommand\SB@endverse{% \ifSB@insong% 1287 \ifSB@inverse% 1288 \unpenalty% 1289 \endgroup\egroup% 1290 \SB@putbox\unvbox\SB@box% 1291 \SB@inversefalse% 1292 \def\SB@closeall{\endsong}% 1293 \ifvnumbered\stepcounter{versenum}\fi% 1294 \SB@prevversetrue% 1295 \else\ifSB@inchorus\SB@errevc\endchorus% 1296 \else\SB@errevo\fi\fi% 1297 \else% 1298 \SB@errevt% 1299 \fi% 1300 } 1285 1286 \ifSB@chorustop When a chorus is broken in to several pieces by column-breaks (via \brk), the following conditional remembers whether the current piece is the topmost one for this chorus. 1301 \newif\ifSB@chorustop 91 \SB@chorusbox When \repchoruses is used, the first sequence of consecutive choruses is remembered in the following box register. 1302 \ifSB@gotchorus The following conditional remembers whether we’ve completed storing the first block of consecutive choruses. 1303 \SB@cmarkclass \SB@nocmarkclass \SB@newbox\SB@chorusbox \newif\ifSB@gotchorus The \repeatchoruses feature requires the use of two extended mark classes provided by ε-TEX. We use the \newmarks macro to allocate these classes, if it’s available. If \newmarks doesn’t exist, then that means the user has an ε-TEX compatible version of LATEX, but no etex style file to go with it; we just have to pick two mark classes and hope that nobody else is using them. \ifSB@etex \@ifundefined{newmarks}{ 1306 \@ifundefined{newmark}{ 1307 \mathchardef\SB@cmarkclass83 1308 \mathchardef\SB@nocmarkclass84 1309 }{ 1310 \newmark\SB@cmarkclass 1311 \newmark\SB@nocmarkclass 1312 } 1313 }{ 1314 \newmarks\SB@cmarkclass 1315 \newmarks\SB@nocmarkclass 1316 } 1317 \fi 1304 1305 \SB@cmark \SB@lastcmark \SB@nocmark To determine where choruses should be inserted when \repchoruses is active, three kinds of marks are inserted into song boxes: \SB@cmark is used to mark places where a chorus might be inserted between verses, and \SB@lastcmark marks a place where a chorus might be inserted after the last verse of the song. Both marks are ε-TEX marks of class \SB@cmarkclass, to avoid disrupting the use of standard TEX marks. Each time a chorus is automatically inserted, \SB@nocmark is inserted with mark class \SB@nocmarkclass just above it (and at the top of each additional page it spans). This inhibits future chorus inserts until the alreadyinserted chorus has been fully committed to the output file. Otherwise some choruses could get auto-inserted multiple times at the same spot, possibly even leading to an infinite loop! \newcommand\SB@cmark{} \def\SB@cmark{SB@cmark} 1320 \newcommand\SB@lastcmark{} 1321 \def\SB@lastcmark{SB@lastcmark} 1322 \newcommand\SB@nocmark{} 1323 \def\SB@nocmark{SB@nocmark} 1318 1319 92 chorus \beginchorus Start a new chorus. If \repchoruses is active and this is part of the first set of consecutive choruses in the song, then include it and its preceding vertical material in the \SB@chorusbox for possible later duplication elsewhere. \newenvironment{chorus}{\beginchorus}{\SB@endchorus} \newcommand\beginchorus{% 1326 \ifSB@insong 1327 \ifSB@inverse\SB@errbcv\endverse\fi% 1328 \ifSB@inchorus\SB@errbcc\endchorus\fi% 1329 \else% 1330 \SB@errbct\beginsong{Unknown Song}% 1331 \fi% 1332 \SB@inchorustrue% 1333 \def\SB@closeall{\endchorus\endsong}% 1334 \SB@chorustoptrue% 1335 \vnumberedfalse% 1336 \SB@stanzabreak% 1337 \chorusmark% 1338 \ifrepchorus% 1339 \ifSB@gotchorus\else\ifSB@prevverse\else% 1340 \global\setbox\SB@chorusbox\vbox{% 1341 \unvbox\SB@chorusbox% 1342 \SB@stanzabreak% 1343 \chorusmark% 1344 }% 1345 \fi\fi% 1346 \fi% 1347 \global\SB@stanzatrue% 1348 \replay[]% 1349 \SB@@beginchorus% 1350 \everychorus\relax% 1351 } 1324 1325 \SB@@beginchorus Begin the body of a chorus, or continue the body of a chorus after \brk has paused it to insert a valid breakpoint. We insert an empty class-\SB@cmarkclass mark here so that this chorus will not be duplicated elsewhere on the same page(s) where it initially appears. \newcommand\SB@@beginchorus{% \ifrepchorus\marks\SB@cmarkclass{}\fi% 1354 \setbox\SB@box\vbox\bgroup\begingroup% 1355 \ifchorded% 1356 \def\SB@everypar{% 1357 \vrule\@height\baselineskip\@width\z@\@depth\z@% 1358 \gdef\SB@everypar{}% 1359 }% 1360 \everypar{\SB@everypar\everypar{}}% 1361 \fi% 1362 \chorusfont\chorusjustify% 1363 \SB@loadactives% 1364 \SB@obeylines% 1352 1353 93 \penalty12345 % 1365 1366 \SB@endchorus } End a chorus. This involves creating the vertical line to the left of the chorus and then unboxing the chorus material that was previously accumulated. \newcommand\SB@endchorus{% \ifSB@insong% 1369 \ifSB@inchorus% 1370 \unpenalty% 1371 \endgroup\egroup% 1372 \SB@inchorusfalse% 1373 \def\SB@closeall{\endsong}% 1374 \setbox\SB@box\vbox{% 1375 \SB@chorusbar\SB@box% 1376 \SB@putbox\unvbox\SB@box% 1377 } 1378 \ifrepchorus\ifSB@gotchorus\else% 1379 \global\setbox\SB@chorusbox\vbox{% 1380 \unvbox\SB@chorusbox% 1381 \unvcopy\SB@box% 1382 }% 1383 \fi\fi% 1384 \unvbox\SB@box% 1385 \SB@prevversefalse% 1386 \else\ifSB@inverse\SB@errecv\endverse% 1387 \else\SB@erreco\fi\fi% 1388 \else% 1389 \SB@errect% 1390 \fi% 1391 } 1367 1368 \SB@cbarshift Increase \leftskip to accommodate the chorus bar, if any. \newcommand\SB@cbarshift{% \ifSB@inchorus\ifdim\cbarwidth>\z@% 1394 \advance\leftskip\cbarwidth% 1395 \advance\leftskip5\p@\relax% 1396 \fi\fi% 1397 } 1392 1393 \SB@chorusbar Create the vertical bar that goes to the left of a chorus. Rather than boxing up the chorus in order to put the bar to the left, the bar is introduced as leaders directly into the vertical list of the main song box. This allows it to stretch and shrink when a column is typeset by the page-builder. \newcommand\SB@chorusbar[1]{% \ifdim\cbarwidth>\z@% 1400 \SB@dimen\ht#1% 1401 \SB@dimenii\dp#1% 1402 \advance\SB@dimen% 1403 \ifSB@chorustop\ifchorded\else2\fi\fi\SB@dimenii% 1398 1399 94 \SB@skip\SB@dimen\relax% \SB@computess\SB@skip1\@plus#1% \SB@computess\SB@skip{-1}\@minus#1% \nointerlineskip\null\nobreak% \leaders\vrule\@width\cbarwidth\vskip\SB@skip% \ifSB@chorustop\ifchorded\else% \advance\SB@skip-\SB@dimenii% \fi\fi% \nobreak\vskip-\SB@skip% \fi% 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 \SB@computess } This computes the stretchability or shrinkability of a vbox and stores the result in the skip register given by harg1 i. If harg2 i = 1 and harg3 i is “plus”, then the stretchability of box harg4 i is added to the plus component of harg1 i. If harg2 i = −1 and harg3 i is “minus”, then the shrinkability of the box is added to the minus component of harg1 i. If the stretchability or shrinkability is infinite, then we guess 1fil for that component. \newcommand\SB@computess[4]{% \begingroup% 1417 \vbadness\@M\vfuzz\maxdimen% 1418 \SB@dimen4096\p@% 1419 \setbox\SB@box\vbox spread#2\SB@dimen{\unvcopy#4}% 1420 \ifnum\badness=\z@% 1421 \global\advance#1\z@#31fil\relax% 1422 \else% 1423 \SB@dimenii\SB@dimen% 1424 \loop% 1425 \SB@dimenii.5\SB@dimenii% 1426 \ifnum\badness<100 % 1427 \advance\SB@dimen\SB@dimenii% 1428 \else 1429 \advance\SB@dimen-\SB@dimenii% 1430 \fi% 1431 \setbox\SB@box\vbox spread#2\SB@dimen{\unvcopy#4}% 1432 \ifnum\badness=100 \SB@dimenii\z@\fi% 1433 \ifdim\SB@dimenii>.1\p@\repeat% 1434 \ifdim\SB@dimen<.1\p@\SB@dimen\z@\fi% 1435 \global\advance#1\z@#3\SB@dimen\relax% 1436 \fi% 1437 \endgroup% 1438 } 1415 1416 \brk Placing \brk within a line in a verse or chorus tells TEX to break the line at that point (if it needs to be broken at all). Placing \brk on a line by itself within a chorus stops the chorus (and its vertical bar), inserts a valid breakpoint, and then restarts the chorus with no intervening space so that if the breakpoint isn’t used, there will be no visible effect. Placing it on a line by itself within a verse just inserts a breakpoint. 95 Placing \brk between songs forces a column- or page-break, but only if generating a non-partial list of songs. When generating a partial list, \brk between songs is ignored. \newcommand\brk{% \ifSB@insong% 1441 \ifhmode\penalty-5 \else% 1442 \unpenalty% 1443 \ifSB@inchorus% 1444 \ifdim\cbarwidth=\z@% 1445 \ifrepchorus\marks\SB@cmarkclass{}\fi% 1446 \SB@breakpoint\brkpenalty% 1447 \else% 1448 \endgroup\egroup% 1449 \ifrepchorus\ifSB@gotchorus\else% 1450 \global\setbox\SB@chorusbox\vbox{% 1451 \unvbox\SB@chorusbox% 1452 \SB@chorusbar\SB@box% 1453 \unvcopy\SB@box% 1454 \SB@breakpoint\brkpenalty% 1455 }% 1456 \fi\fi% 1457 \SB@chorusbar\SB@box% 1458 \unvbox\SB@box% 1459 \SB@breakpoint\brkpenalty% 1460 \SB@chorustopfalse% 1461 \SB@@beginchorus% 1462 \fi% 1463 \else% 1464 \SB@breakpoint\brkpenalty% 1465 \fi% 1466 \fi% 1467 \else% 1468 \ifpartiallist\else\SB@nextcol\@ne\colbotglue\fi% 1469 \fi% 1470 } 1439 1440 \SB@boxup Typeset a shaded box containing a textual note to singers or musicians. We first try typesetting the note on a single line. If it’s too big, then we try again in paragraph mode with full justification. \newcommand\SB@boxup[1]{% \setbox\SB@box\hbox{{\notefont#1}}% 1473 \SB@dimen\wd\SB@box% 1474 \advance\SB@dimen6\p@% 1475 \advance\SB@dimen\leftskip% 1476 \advance\SB@dimen\rightskip% 1477 \ifdim\SB@dimen>\hsize% 1478 \vbox{{% 1479 \advance\hsize-6\p@% 1480 \advance\hsize-\leftskip% 1471 1472 96 \advance\hsize-\rightskip% \notejustify% \unhbox\SB@box\par% \kern\z@% }}% \else% \vbox{\box\SB@box\kern\z@}% \fi% 1481 1482 1483 1484 1485 1486 1487 1488 1489 \textnote } Create a textual note for singers and musicians. If the note begins a verse or chorus, it should not be preceded by any spacing. Verses and choruses begin with the sentinel penalty 12345, so we check \lastpenalty to identify this case. When typesetting the note, we must be sure to temporarily clear \everypar to inhibit any verse numbering that might be pending. We also readjust the \baselineskip as if we weren’t doing chords, since no chords go above a textual note. \newcommand\textnote[1]{% \ifhmode\par\fi% 1492 \ifnum\lastpenalty=12345\else% 1493 \ifSB@inverse% 1494 \vskip2\p@\relax% 1495 \else\ifSB@inchorus% 1496 \vskip2\p@\relax% 1497 \else\ifSB@stanza% 1498 \nobreak\vskip\versesep% 1499 \fi\fi\fi% 1500 \fi% 1501 \begingroup% 1502 \everypar{}% 1503 \ifchorded\chordedfalse\SB@setbaselineskip\chordedtrue\fi% 1504 \placenote{\SB@colorbox\notebgcolor{\SB@boxup{#1}}}% 1505 \endgroup% 1506 \nobreak% 1507 \ifSB@inverse% 1508 \vskip2\p@\relax% 1509 \else\ifSB@inchorus% 1510 \vskip2\p@\relax% 1511 \else\ifSB@stanza\else% 1512 \nobreak\vskip\versesep% 1513 \fi\fi\fi% 1514 } 1490 1491 \musicnote Create a textual note for musicians. 1515 \echo \SB@echo \SB@@echo \newcommand\musicnote[1]{\ifchorded\textnote{#1}\fi} Typeset an echo part in the lyrics. Echo parts will be oblique and parenthesized. We toggle between oblique and upright shapes like \emph, but we use \slshape instead of \itshape because it tends to look nicer with the larger fonts used in slides mode. 97 The \echo macro must be able to accept chords in its argument. This complicates the implementation because chord macros should change catcodes, but if we grab \echo’s argument in the usual way then all the catcodes will be set before the chord macros have a chance to change them. This would disallow chord name abbreviations like # and & within \echo parts. If we’re using ε-TEX then the solution is easy: we use \scantokens to rescan the argument and thereby re-assign the catcodes. (One subtlety: Whenever LATEX consumes an argument to a macro, it changes # to ## so that when the argument text is substituted into the body of the macro, the replacement text will not contain unsubstituted parameters (such as #1). If \scantokens is used on the replacement text and the scanned tokens assign a new catcode to #, that causes #’s to be doubled in the output, which was not the intent. To avoid this problem, we use \@sanitize before consuming the argument to \echo, which sets the catcodes of most special tokens (including #) to 12, so that LATEX will not recognize any of them as parameters and will therefore not double any of them.) \ifSB@etex \newcommand\echo{\begingroup\@sanitize\SB@echo} 1518 \newcommand\SB@echo[1]{% 1519 \endgroup% 1520 \begingroup% 1521 \ifdim\fontdimen\@ne\font>\z@\upshape\else\slshape\fi% 1522 \endlinechar\m@ne% 1523 \scantokens{(#1)}% 1524 \endgroup% 1525 } 1526 \else 1516 1517 If we’re not using ε-TEX, we must do something more complicated. We set up the appropriate font within a local group and finish with \hbox so that the argument to \echo is treated as the body of the box. Control is reacquired after the box using \aftergroup, whereupon we unbox the box and insert the closing parenthesis. This almost works except that if the last thing in an echo part is a long chord name atop a short lyric, the closing parenthesis will float out away from the lyric instead of being sucked under the chord. I can find no solution to this problem, so to avoid it users must find a version of LATEX that is ε-TEX compatible. \newcommand\echo{% \begingroup% 1529 \ifdim\fontdimen\@ne\font>\z@\upshape\else\slshape\fi% 1530 \afterassignment\SB@echo% 1531 \setbox\SB@box\hbox% 1532 } 1533 \newcommand\SB@echo{\aftergroup\SB@@echo(} 1534 \newcommand\SB@@echo{\unhbox\SB@box)\endgroup} 1535 \fi 1527 1528 \rep Place \rep{hni} at the end of a line to indicate that it should be sung hni times. 1536 1537 \newcommand\rep[1]{% (\raise.25ex\hbox{% 98 \fontencoding{OMS}\fontfamily{cmsy}\selectfont\char\tw@% }#1)% 1538 1539 1540 } 16.7 Scripture Quotations The macros in this section typeset scripture quotations and other between-songs environments. songgroup A songgroup environment associates all enclosed environments with the enclosed song. When generating a partial list, all the enclosed environments are contributed if and only if the enclosed song is contributed. \newenvironment{songgroup}{% \ifnum\SB@grouplvl=\z@% 1543 \edef\SB@sgroup{\thesongnum}% 1544 \global\SB@groupcnt\m@ne% 1545 \fi% 1546 \advance\SB@grouplvl\@ne% 1547 }{% 1548 \advance\SB@grouplvl\m@ne% 1549 \ifnum\SB@grouplvl=\z@\let\SB@sgroup\@empty\fi% 1550 } 1541 1542 \SB@grouplvl Count the songgroup environment nesting depth. 1551 intersong \SB@newcount\SB@grouplvl An intersong block contributes vertical material to a column between the songs of a songs section. It is subject to the same column-breaking algorithm as real songs, but receives none of the other formatting applied to songs. \newenvironment{intersong}{% \ifSB@insong\SB@errbro\SB@closeall\fi% 1554 \ifSB@intersong\SB@errbrr\SB@closeall\fi% 1555 \setbox\SB@chorusbox\box\voidb@x% 1556 \SB@intersongtrue% 1557 \def\SB@closeall{\end{intersong}}% 1558 \setbox\SB@songbox\vbox\bgroup\begingroup% 1559 \ifnum\SB@numcols>\z@\hsize\SB@colwidth\fi% 1560 \ifdim\sbarheight>\z@% 1561 \hrule\@height\sbarheight\@width\hsize% 1562 \nobreak% 1563 \fi% 1564 }{% 1565 \ifSB@intersong 1566 \ifdim\sbarheight>\z@% 1567 \ifhmode\par\fi% 1568 \SB@skip\lastskip% 1569 \unskip\nobreak\vskip\SB@skip% 1570 \hbox{\vrule\@height\sbarheight\@width\hsize}% 1571 \fi% 1552 1553 99 \endgroup\egroup% \ifSB@omitscrip% \setbox\SB@songbox\box\voidb@x% \else% \SB@submitsong% \fi% \SB@intersongfalse% \else% \ifSB@insong\SB@errero\SB@closeall\else\SB@errert\fi% \fi% 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 } The starred form contributes page-spanning vertical material directly to the top of the nearest fresh page. \newenvironment{intersong*}{% \ifSB@insong\SB@errbro\SB@closeall\fi% 1585 \ifSB@intersong\SB@errbrr\SB@closeall\fi% 1586 \setbox\SB@chorusbox\box\voidb@x% 1587 \SB@intersongtrue% 1588 \def\SB@closeall{\end{intersong*}}% 1589 \setbox\SB@songbox\vbox\bgroup\begingroup% 1590 }{% 1591 \ifSB@intersong% 1592 \endgroup\egroup% 1593 \ifSB@omitscrip% 1594 \setbox\SB@songbox\box\voidb@x% 1595 \else% 1596 \def\SB@stype{\SB@styppage}% 1597 \SB@submitsong% 1598 \def\SB@stype{\SB@stypcol}% 1599 \fi% 1600 \SB@intersongfalse% 1601 \else% 1602 \ifSB@insong\SB@errero\SB@closeall\else\SB@errert\fi% 1603 \fi% 1604 } 1583 1584 scripture \beginscripture Begin a scripture quotation. We first store the reference in a box for later use, and then set up a suitable environment for the quotation. Quotations cannot typically be reworded if line-breaking fails, so we set \emergencystretch to a relatively high value at the outset. \newenvironment{scripture}{\beginscripture}{\SB@endscripture} \newcommand\beginscripture[1]{% 1607 \begin{intersong}% 1608 \SB@parsesrefs{#1}% 1609 \setbox\SB@envbox\hbox{{\printscrcite\songrefs}}% 1610 \def\SB@closeall{\endscripture}% 1611 \nobreak\vskip5\p@% 1612 \SB@parindent\parindent\parindent\z@% 1613 \parskip\z@skip\parfillskip\@flushglue% 1605 1606 100 \leftskip\SB@parindent\rightskip\SB@parindent\relax% \scripturefont% \baselineskip\f@size\p@\@plus\p@\relax% \advance\baselineskip\p@\relax% \emergencystretch.3em% 1614 1615 1616 1617 1618 1619 \SB@endscripture } End a scripture quotation. \newcommand\SB@endscripture{% \ifSB@intersong 1622 \scitehere% 1623 \ifhmode\par\fi% 1624 \vskip-3\p@% 1625 \end{intersong}% 1626 \fi% 1627 } 1620 1621 \scitehere Usually the scripture citation should just come at the \endscripture line, but at times the user might want to invoke this macro explicitly at a more suitable point. A good example is when something near the end of the scripture quotation drops TEX into vertical mode. In such cases, it is often better to issue the citation before leaving horizontal mode. In any case, this macro should work decently whether in horizontal or vertical mode. In horizontal mode life is easy: we just append the reference to the current horizontal list using the classic code from p. 106 of The TEXbook. However, if we’re now in vertical mode, the problem is a little harder. We do the best we can by using \lastbox to remove the last line, then adding the reference and re-typesetting it. This isn’t as good as the horizontal mode solution because TEX only gets to reevaluate the last line instead of the whole paragraph, but usually the results are passable. \newcommand\scitehere{% \ifSB@intersong% 1630 \ifvoid\SB@envbox\else% 1631 \ifvmode% 1632 \setbox\SB@box\lastbox% 1633 \nointerlineskip\noindent\hskip-\leftskip% 1634 \unhbox\SB@box\unskip% 1635 \fi% 1636 \unskip\nobreak\hfil\penalty50\hskip.8em\null\nobreak\hfil% 1637 \box\SB@envbox\kern-\SB@parindent% 1638 {\parfillskip\z@\finalhyphendemerits2000\par}% 1639 \fi% 1640 \else% 1641 \SB@errscrip\scitehere% 1642 \fi% 1643 } 1628 1629 101 \Acolon Typeset a line of poetry in a scripture quotation. \Bcolon 1644 \newcommand\Acolon{\SB@colon2\Acolon} 1645 \newcommand\Bcolon{\SB@colon1\Bcolon} \SB@colon Begin a group of temporary definitions that will end at the next hreturni. The hreturni will end the paragraph and close the local scope. \newcommand\SB@colon[2]{% \ifSB@intersong\else% 1648 \SB@errscrip#2% 1649 \beginscripture{Unknown}% 1650 \fi% 1651 \ifhmode\par\fi% 1652 \begingroup% 1653 \rightskip\SB@parindent\@plus4em% 1654 \advance\leftskip2\SB@parindent% 1655 \advance\parindent-#1\SB@parindent% 1656 \def\par{\endgraf\endgroup}% 1657 \obeylines% 1658 } 1646 1647 \strophe Insert blank space indicative of a strophe division in a scripture quotation. \newcommand\strophe{% \ifSB@intersong\else% 1661 \SB@errscrip\strophe\beginscripture{Unknown}% 1662 \fi% 1663 \vskip.9ex\@plus.45ex\@minus.68ex\relax% 1664 } 1659 1660 \scripindent Create an indented sub-block within a scripture quotation. \scripoutdent 1665 \newcommand\SB@scripdent[2]{% \SB@scripdent 1666 \ifSB@intersong\else% 1667 \SB@errscrip#2\beginscripture{Unknown}% 1668 \fi% 1669 \ifhmode\par\fi% 1670 \advance\leftskip#1\SB@parindent\relax% 1671 } 1672 \newcommand\scripindent{\SB@scripdent1\scripindent} 1673 \newcommand\scripoutdent{\SB@scripdent-\scripoutdent} \shiftdblquotes The Zaph Chancery font used by default to typeset scripture quotations seems to \SB@ldqleft have some kerning problems with double-quote ligatures. The \shiftdblquotes \SB@ldqright macro allows one to modify the spacing around all double-quotes until the current \SB@rdqleft group ends. \SB@rdqright 1674 \newcommand\SB@quotesactive{% \SB@scanlq 1675 \catcode‘’\active% \SB@scanrq 1676 \catcode‘‘\active% \SB@dolq 1677 } \SB@dorq 1678 \newcommand\shiftdblquotes[4]{} 1679 \newcommand\SB@ldqleft{} 102 \newcommand\SB@ldqright{} \newcommand\SB@rdqleft{} 1682 \newcommand\SB@rdqright{} 1683 \newcommand\SB@scanlq{} 1684 \newcommand\SB@scanrq{} 1685 \newcommand\SB@dolq{} 1686 \newcommand\SB@dorq{} 1687 { 1688 \SB@quotesactive 1689 \gdef\shiftdblquotes#1#2#3#4{% 1690 \def\SB@ldqleft{\kern#1}% 1691 \def\SB@ldqright{\kern#2}% 1692 \def\SB@rdqleft{\kern#3}% 1693 \def\SB@rdqright{\kern#4}% 1694 \SB@quotesactive% 1695 \def‘{\futurelet\SB@next\SB@scanlq}% 1696 \def’{\futurelet\SB@next\SB@scanrq}% 1697 } 1698 \gdef\SB@scanlq{% 1699 \ifx\SB@next‘% 1700 \expandafter\SB@dolq% 1701 \else% 1702 \expandafter\lq% 1703 \fi% 1704 } 1705 \gdef\SB@scanrq{% 1706 \ifx\SB@next’% 1707 \expandafter\SB@dorq% 1708 \else% 1709 \expandafter\rq% 1710 \fi% 1711 } 1712 \gdef\SB@dolq‘{% 1713 \ifvmode\leavevmode\else\/\fi% 1714 \vadjust{}% 1715 \SB@ldqleft\lq\lq\SB@ldqright% 1716 \vadjust{}% 1717 } 1718 \gdef\SB@dorq’{% 1719 \ifvmode\leavevmode\else\/\fi% 1720 \vadjust{}% 1721 \SB@rdqleft\rq\rq\SB@rdqright% 1722 \vadjust{}% 1723 } 1724 } 1680 1681 16.8 Transposition The macros that transpose chords are contained in this section. 103 \SB@transposefactor This counter identifies the requested number of halfsteps by which chords are to be transposed (from −11 to +11). 1725 \ifSB@convertnotes \SB@newcount\SB@transposefactor Even when transposition is not requested, the transposition logic can be used to automatically convert note names to another form. The following conditional turns that feature on or off. 1726 \newif\ifSB@convertnotes \notenameA Reserve a control sequence for each note of the diatonic scale. These will be used \notenameB to identify which token sequences the input file uses to denote the seven scale \notenameC degrees. Their eventual definitions must consist entirely of uppercase letters, and \notenameD they must be assigned using \def, but that comes later. \notenameE 1727 \newcommand\notenameA{} \notenameF 1728 \newcommand\notenameB{} \notenameG 1729 \newcommand\notenameC{} 1730 \newcommand\notenameD{} 1731 \newcommand\notenameE{} 1732 \newcommand\notenameF{} 1733 \newcommand\notenameG{} \printnoteA These control sequences are what the transposition logic actually outputs to denote \printnoteB each scale degree. They can include any LATEX code that is legal in horizontal \printnoteC mode. \printnoteD 1734 \newcommand\printnoteA{} \printnoteE 1735 \newcommand\printnoteB{} \printnoteF 1736 \newcommand\printnoteC{} \printnoteG 1737 \newcommand\printnoteD{} 1738 \newcommand\printnoteE{} 1739 \newcommand\printnoteF{} 1740 \newcommand\printnoteG{} \notenamesin Set the note names used by the input file. \newcommand\notenamesin[7]{% \def\notenameA{#1}% 1743 \def\notenameB{#2}% 1744 \def\notenameC{#3}% 1745 \def\notenameD{#4}% 1746 \def\notenameE{#5}% 1747 \def\notenameF{#6}% 1748 \def\notenameG{#7}% 1749 \SB@convertnotestrue% 1750 } 1741 1742 104 \notenamesout Set the note names that are output by the transposition logic. \newcommand\notenamesout[7]{% \def\printnoteA{#1}% 1753 \def\printnoteB{#2}% 1754 \def\printnoteC{#3}% 1755 \def\printnoteD{#4}% 1756 \def\printnoteE{#5}% 1757 \def\printnoteF{#6}% 1758 \def\printnoteG{#7}% 1759 \SB@convertnotestrue% 1760 } 1751 1752 \notenames Set an identical input name and output name for each scale degree. \newcommand\notenames[7]{% \notenamesin{#1}{#2}{#3}{#4}{#5}{#6}{#7}% 1763 \notenamesout{#1}{#2}{#3}{#4}{#5}{#6}{#7}% 1764 \SB@convertnotesfalse% 1765 } 1761 1762 \alphascale \solfedge Predefine scales for alphabetic names and solfedge names, and set alphabetic scales to be the default. \newcommand\alphascale{\notenames ABCDEFG} \newcommand\solfedge{\notenames{LA}{SI}{DO}{RE}{MI}{FA}{SOL}} 1768 \alphascale 1766 1767 \ifSB@prefshrps When a transposed chord falls on a black key, the code must choose which enharmonically equivalent name to give the new chord. (For example, should C transposed by +1 be named C# or D[?) A heuristic is used to guess which name is most appropriate. The following conditional records whether the current key signature is sharped or flatted according to this heuristic guess. 1769 \ifSB@needkey The first chord seen is usually the best indicator of the key of the song. (Even when the first chord isn’t the tonic, it will often be the dominant or subdominant, which usually has the same kind of accidental in its key signatures as the actual key.) This conditional remembers whether the current chord is the first one seen in the song, and should therefore be used to guess the key of the song. 1770 \transpose \newif\ifSB@prefshrps \newif\ifSB@needkey The \transpose macro sets the transposition adjustment factor and informs the transposition logic that the next chord seen will be the first one in the new key. \newcommand\transpose[1]{% \advance\SB@transposefactor by#1\relax% 1773 \SB@cnt\SB@transposefactor% 1774 \divide\SB@cnt12 % 1775 \multiply\SB@cnt12 % 1776 \advance\SB@transposefactor-\SB@cnt% 1777 \SB@needkeytrue% 1778 } 1771 1772 105 \capo Specifying a \capo normally just causes a textual note to musicians to be typeset, but if the transposecapos option is active, it activates transposition of the chords. \newcommand\capo[1]{% \iftranscapos\transpose{#1}\else\musicnote{capo #1}\fi% 1781 } 1779 1780 \prefersharps \preferflats One of these macros is called after the first chord has been seen to register that we’re transposing to a key with a sharped or flatted key signature. 1782 1783 \transposehere \newcommand\prefersharps{\SB@prefshrpstrue\SB@needkeyfalse} \newcommand\preferflats{\SB@prefshrpsfalse\SB@needkeyfalse} If automatic transposition has been requested, yield the given chord transposed by the requested amount. Otherwise return the given chord verbatim. \newcommand\transposehere[1]{% \ifnum\SB@transposefactor=\z@% 1786 \ifSB@convertnotes% 1787 \SB@dotranspose{#1}% 1788 \the\SB@toks% 1789 \else% 1790 #1% 1791 \fi% 1792 \else% 1793 \ifSB@convertnotes% 1794 {\SB@transposefactor\z@% 1795 \SB@dotranspose{#1}% 1796 \xdef\SB@tempv{\the\SB@toks}}% 1797 \else% 1798 \def\SB@tempv{#1}% 1799 \fi% 1800 \SB@dotranspose{#1}% 1801 \expandafter\trchordformat\expandafter{\SB@tempv}{\the\SB@toks}% 1802 \fi% 1803 } 1784 1785 \notrans Suppress chord transposition without suppressing note name conversion. When a \notrans{htexti} macro appears within text undergoing transposition, the \notrans macro and the group will be preserved verbatim by the transposition parser. When it is then expanded after parsing, we must therefore re-invoke the transposition logic on the argument, but in an environment where the transposition factor has been temporarily set to zero. This causes note name conversion to occur without actually transposing. \newcommand\notrans[1]{% \begingroup% 1806 \SB@transposefactor\z@% 1807 \transposehere{#1}% 1808 \endgroup% 1809 } 1804 1805 106 \SB@dotranspose Parse the argument to a chord macro, yielding the transposed equivalent in the \SB@toks token register. \newcommand\SB@dotranspose[1]{% \SB@toks{}% 1812 \let\SB@dothis\SB@trmain% 1813 \SB@trscan#1\SB@trend% 1814 } 1810 1811 \trchordformat By default, transposing means replacing old chords with new chords in the new key. However, sometimes the user may want to typeset something more sophisticated, like old chords followed by new chords in parentheses so that musicians who use capos and those who don’t can play from the same piece of music. Such typesetting is possible by redefining the following macro to something like #1 (#2) instead of #2. 1815 \SB@trscan This is the entrypoint to the code that scans over the list of tokens comprising a chord and transposes note names as it goes. Start by peeking ahead at the next symbol without consuming it. 1816 \SB@trmain \newcommand\trchordformat[2]{#2} \newcommand\SB@trscan{\futurelet\SB@next\SB@dothis} Test to see whether the token was a begin-brace, end-brace, or space. These tokens require special treatment because they cannot be accepted as implicit arguments to macros. \newcommand\SB@trmain{% \ifx\SB@next\bgroup% 1819 \let\SB@donext\SB@trgroup% 1820 \else\ifx\SB@next\egroup% 1821 \SB@toks\expandafter{\the\SB@toks\egroup}% 1822 \let\SB@donext\SB@trskip% 1823 \else\ifcat\noexpand\SB@next\@sptoken% 1824 \SB@appendsp\SB@toks% 1825 \let\SB@donext\SB@trskip% 1826 \else% 1827 \let\SB@donext\SB@trstep% 1828 \fi\fi\fi% 1829 \SB@donext% 1830 } 1817 1818 \SB@trgroup A begin-group brace lies next in the input stream. Consume the entire group as an argument to this macro, and append it, including the begin- and end-group tokens, to the list of tokens processed so far. No transposition takes place within a group; they are copied verbatim because they probably contain macro code. \newcommand\SB@trgroup[1]{% \SB@toks\expandafter{\the\SB@toks{#1}}% 1833 \SB@trscan% 1834 } 1831 1832 107 \SB@trspace A space or end-brace lies next in the input stream. It has already been added to the token list, so skip over it. \newcommand\SB@trskip{% \afterassignment\SB@trscan% 1837 \let\SB@next= } 1835 1836 \SB@trstep A non-grouping token lies next in the input stream. Consume it as an argument to this macro, and then test it to see whether it’s a note letter or some other recognized item. If so, process it; otherwise just append it to the token list and continue scanning. \newcommand\SB@trstep[1]{% \let\SB@donext\SB@trscan% 1840 \ifcat\noexpand\SB@next A% 1841 \ifnum\uccode‘#1=‘#1% 1842 \def\SB@temp{#1}% 1843 \let\SB@dothis\SB@trnote% 1844 \else% 1845 \SB@toks\expandafter{\the\SB@toks#1}% 1846 \fi% 1847 \else\ifx\SB@next\SB@trend 1848 \let\SB@donext\relax% 1849 \else% 1850 \SB@toks\expandafter{\the\SB@toks#1}% 1851 \fi\fi% 1852 \SB@donext% 1853 } 1838 1839 \SB@trnote We’re in the midst of processing a sequence of uppercase letters that might comprise a note name. Check to see whether the next token is an accidental (sharp or flat), or yet another letter. \newcommand\SB@trnote{% \ifcat\noexpand\SB@next A% 1856 \let\SB@donext\SB@trnotestep% 1857 \else\ifnum\SB@transposefactor=\z@% 1858 \SB@cnt\z@% 1859 \let\SB@donext\SB@trtrans% 1860 \else\ifx\SB@next\flt% 1861 \SB@cnt\m@ne% 1862 \let\SB@donext\SB@tracc% 1863 \else\ifx\SB@next\shrp% 1864 \SB@cnt\@ne% 1865 \let\SB@donext\SB@tracc% 1866 \else% 1867 \SB@cnt\z@% 1868 \let\SB@donext\SB@trtrans% 1869 \fi\fi\fi\fi% 1870 \SB@donext% 1871 } 1854 1855 108 \SB@trnotestep The next token is a letter. Consume it and test to see whether it is an uppercase letter. If so, add it to the note name being assembled; otherwise reinsert it into the input stream and jump directly to the transposition logic. \newcommand\SB@trnotestep[1]{% \ifnum\uccode‘#1=‘#1% 1874 \expandafter\def\expandafter\SB@temp\expandafter{\SB@temp#1}% 1875 \expandafter\SB@trscan% 1876 \else% 1877 \SB@cnt\z@% 1878 \expandafter\SB@trtrans\expandafter#1% 1879 \fi% 1880 } 1872 1873 \SB@tracc We’ve encountered an accidental (sharp or flat) immediately following a note name. Peek ahead at the next token without consuming it, and then jump to the transposition logic. This is done because the transposition logic might need to infer the key signature of the song, and if the next token is an m (for minor), then that information can help. 1881 \SB@trtrans \newcommand\SB@tracc[1]{\futurelet\SB@next\SB@trtrans} We’ve assembled a sequence of capital letters (in \SB@temp) that might comprise a note name to be transposed. If the letters were followed by a \shrp then \SB@cnt is 1; if they were followed by a \flt then it is −1; otherwise it is 0. If the assembled letters turn out to not match any valid note name, then do nothing and return to scanning. Otherwise compute a new transposed name. \newcommand\SB@trtrans{% \advance\SB@cnt% 1884 \ifx\SB@temp\notenameA\z@% 1885 \else\ifx\SB@temp\notenameB\tw@% 1886 \else\ifx\SB@temp\notenameC\thr@@% 1887 \else\ifx\SB@temp\notenameD5 % 1888 \else\ifx\SB@temp\notenameE7 % 1889 \else\ifx\SB@temp\notenameF8 % 1890 \else\ifx\SB@temp\notenameG10 % 1891 \else-99 \fi\fi\fi\fi\fi\fi\fi% 1892 \ifnum\SB@cnt<\m@ne% 1893 \SB@toks\expandafter\expandafter\expandafter{% 1894 \expandafter\the\expandafter\SB@toks\SB@temp}% 1895 \else% 1896 \advance\SB@cnt\SB@transposefactor% 1897 \ifnum\SB@cnt<\z@\advance\SB@cnt12 \fi% 1898 \ifnum\SB@cnt>11 \advance\SB@cnt-12 \fi% 1899 \ifSB@needkey\ifnum\SB@transposefactor=\z@\else\SB@setkeysig\fi\fi% 1900 \edef\SB@temp{% 1901 \the\SB@toks% 1902 \ifSB@prefshrps% 1903 \ifcase\SB@cnt\printnoteA\or\printnoteA\noexpand\shrp\or% 1904 \printnoteB\or\printnoteC\or\printnoteC\noexpand\shrp\or% 1882 1883 109 \printnoteD\or\printnoteD\noexpand\shrp\or\printnoteE\or% \printnoteF\or\printnoteF\noexpand\shrp\or\printnoteG\or% \printnoteG\noexpand\shrp\fi% \else% \ifcase\SB@cnt\printnoteA\or\printnoteB\noexpand\flt\or% \printnoteB\or\printnoteC\or\printnoteD\noexpand\flt\or% \printnoteD\or\printnoteE\noexpand\flt\or\printnoteE\or% \printnoteF\or\printnoteG\noexpand\flt\or\printnoteG\or% \printnoteA\noexpand\flt\fi% \fi}% \SB@toks\expandafter{\SB@temp}% \fi% \let\SB@dothis\SB@trmain% \SB@trscan% 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 \SB@setkeysig } If this is the first chord of the song, assume that this is the tonic of the key, and select whether to use a sharped or flatted key signature for the rest of the song based on that. Even if this isn’t the tonic, it’s probably the dominant or sub-dominant, which almost always has a number of sharps or flats similar to the tonic. If the bottom note of the chord turns out to be a black key, we choose the enharmonic equivalent that is closest to C on the circle of fifths (i.e., the one that has fewest sharps or flats). \newcommand\SB@setkeysig{% \global\SB@needkeyfalse% 1922 \ifcase\SB@cnt% 1923 \global\SB@prefshrpstrue\or% A 1924 \global\SB@prefshrpsfalse\or% Bb 1925 \global\SB@prefshrpstrue\or% B 1926 \ifx\SB@next m% C 1927 \global\SB@prefshrpsfalse% 1928 \else% 1929 \global\SB@prefshrpstrue% 1930 \fi\or% 1931 \global\SB@prefshrpstrue\or% C# 1932 \ifx\SB@next m% D 1933 \global\SB@prefshrpsfalse% 1934 \else% 1935 \global\SB@prefshrpstrue% 1936 \fi\or% 1937 \global\SB@prefshrpsfalse\or% Eb 1938 \global\SB@prefshrpstrue\or% E 1939 \global\SB@prefshrpsfalse\or% F 1940 \global\SB@prefshrpstrue\or% F# 1941 \ifx\SB@next m% G 1942 \global\SB@prefshrpsfalse% 1943 \else% 1944 \global\SB@prefshrpstrue% 1945 \fi\or% 1920 1921 110 \global\SB@prefshrpsfalse\else% Ab \global\SB@needkeytrue% non-chord \fi% 1946 1947 1948 1949 \SB@trend } The following macro marks the end of chord text to be processed. It should always be consumed and discarded by the chord-scanning logic above, so generate an error if it is ever expanded. \newcommand\SB@trend{% \SB@Error{Internal Error: Transposition failed}% 1952 {This error should not occur.}% 1953 } 1950 1951 16.9 Measure Bars The following code handles the typesetting of measure bars. \SB@metertop These macros remember the current numerator and denominator of the meter. \SB@meterbot 1954 \newcommand\SB@metertop{} 1955 \newcommand\SB@meterbot{} \meter Set the current meter without producing an actual measure bar yet. 1956 \SB@measuremark Normally measure bar boxes should be as thin as possible so that they can be slipped into lyrics without making them hard to read. But when two measure bars appear consecutively, they need to be spaced apart more so that they look like two separate lines instead of one thick line. To achieve this, there needs to be a way to pull a vbox off the current list and determine whether or not it is a box that contains a measure bar. The solution is to insert a mark (\SB@measuremark) at the top of each measure bar vbox. We can then see whether this measure bar immediately follows another measure bar by using \vsplit on \lastbox. 1957 \SB@makembar \newcommand\meter[2]{\gdef\SB@metertop{#1}\gdef\SB@meterbot{#2}} \newcommand\SB@measuremark{SB@IsMeasure} Typeset a measure bar. If provided, harg1 i is the numerator and harg2 i is the denominator of the meter to be rendered above the bar. If those arguments are left blank, render a measure bar without a meter marking. \newcommand\SB@makembar[2]{% \ifSB@inverse\else% 1960 \ifSB@inchorus\else\SB@errmbar\fi% 1961 \fi% 1962 \ifhmode% 1963 \SB@skip\lastskip\unskip% 1964 \setbox\SB@box\lastbox% 1965 \copy\SB@box% 1966 \ifvbox\SB@box% 1967 \begingroup% 1968 \setbox\SB@boxii\copy\SB@box% 1958 1959 111 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 \vbadness\@M\vfuzz\maxdimen% \setbox\SB@boxii% \vsplit\SB@boxii to\maxdimen% \endgroup% \long\edef\SB@temp{\splitfirstmark}% \ifx\SB@temp\SB@measuremark% \penalty100\hskip1em% \else% \penalty100\hskip\SB@skip% \fi% \else% \penalty100\hskip\SB@skip% \fi% \fi% \ifvmode\leavevmode\fi% \setbox\SB@box\hbox{\tiny\sffamily{#1}}% \setbox\SB@boxii\hbox{\tiny\sffamily{#2}}% \ifdim\wd\SB@box>\wd\SB@boxii% \SB@dimen\wd\SB@box\relax% \else% \SB@dimen\wd\SB@boxii\relax% \fi% \ifdim\SB@dimen<.5\p@% \SB@dimen.5\p@% \fi% \SB@dimenii\baselineskip% \advance\SB@dimenii-2\p@% \advance\SB@dimenii-\ht\SB@box% \advance\SB@dimenii-\dp\SB@box% \advance\SB@dimenii-\ht\SB@boxii% \advance\SB@dimenii-\dp\SB@boxii% \vbox{% \mark{\SB@measuremark}% \hbox to\SB@dimen{% \hfil% \box\SB@box% \hfil% }% \nointerlineskip% \hbox to\SB@dimen{% \hfil% \box\SB@boxii% \hfil% }% \nointerlineskip% \hbox to\SB@dimen{% \hfil% \vrule\@width.5\p@\@height\SB@dimenii% \hfil% }% 112 }% \meter{}{}% 2019 2020 2021 \mbar The \mbar macro invokes \SB@mbar, which gets redefined by macros and options that turn measure bars on and off. 2022 \measurebar } \newcommand\mbar{\SB@mbar} Make a measure bar using the most recently defined meter. Then set the meter to nothing so that the next measure bar will not display any meter unless the meter changes. \newcommand\measurebar{% \mbar\SB@metertop\SB@meterbot% 2025 } 2023 2024 \SB@repcolon Create the colon that preceeds or follows a repeat sign. \newcommand\SB@repcolon{{% \usefont{OT1}{cmss}{m}{n}\selectfont% 2028 \ifchorded% 2029 \baselineskip.5\SB@dimen% 2030 \vbox{\hbox{:}\hbox{:}\kern.5\p@}% 2031 \else% 2032 \raise.5\p@\hbox{:}% 2033 \fi% 2034 }} 2026 2027 \lrep Create a begin-repeat sign. \newcommand\lrep{% \SB@dimen\baselineskip% 2037 \advance\SB@dimen-2\p@% 2038 \vrule\@width1.5\p@\@height\SB@dimen\@depth\p@% 2039 \kern1.5\p@% 2040 \vrule\@width.5\p@\@height\SB@dimen\@depth\p@% 2041 \SB@repcolon% 2042 } 2035 2036 \rrep Create an end-repeat sign. \newcommand\rrep{% \SB@dimen\baselineskip% 2045 \advance\SB@dimen-2\p@% 2046 \SB@repcolon% 2047 \vrule\@width.5\p@\@height\SB@dimen\@depth\p@% 2048 \kern1.5\p@% 2049 \vrule\@width1.5\p@\@height\SB@dimen\@depth\p@% 2050 } 2043 2044 113 16.10 Lyric Scanning The obvious way to create a chord macro is as a normal macro with two arguments, one for the chord name and one for the lyrics to go under the chord— e.g. \chord{hchordnamei{hlyrici}. However, in practice such a macro is extremely cumbersome and difficult to use. The problem is that in order to use such a macro properly, the user must remember a bunch of complex style rules that govern what part of the lyric text needs to go in the hlyrici parameter and what part should be typed after the closing brace. To avoid separating a word from its trailing punctuation, the hlyrici parameter must often include punctuation but not certain special punctuation like hyphens, should include the rest of the word but not if there’s another chord in the word, should omit measure bars but only if measure bars are being shown, etc. This is way too difficult for the average user. To avoid this problem, we define chords using a one-argument macro (the argument is the chord name), but with no explicit argument for the lyric part. Instead, the macro scans ahead in the input stream, automatically determining what portion of the lyric text that follows should be sucked in as an implicit second argument. The following code does this look-ahead scanning. \ifSB@wordends \ifSB@brokenword Chord macros must look ahead in the input stream to see whether this chord is immediately followed by whitespace or the remainder of a word. If the latter, hyphenation might need to be introduced. These macros keep track of the need for hyphenation, if any. 2051 2052 \SB@lyric Lyrics appearing after a chord are scanned into the following token list register. 2053 \SB@numhyps \SB@newtoks\SB@lyricnohyp The following two boxes hold the part of the lyric text that is to be typeset under the chord, and the chord text that is to be typeset above. 2056 2057 \SB@chbstok \SB@newcount\SB@numhyps When a lyric syllable under a chord ends in exactly one hyphen, the following token register is set to be the syllable without the hyphen. 2055 \SB@lyricbox \SB@chordbox \SB@newtoks\SB@lyric Hyphens appearing in lyrics require special treatment. The following counter counts the number of explicit hyphens ending the lyric syllable that follows the current chord. 2054 \SB@lyricnohyp \newif\ifSB@wordends \newif\ifSB@brokenword \SB@newbox\SB@lyricbox \SB@newbox\SB@chordbox When \MultiwordChords is active, the following reserved control sequence remembers the first (space) token not yet included into the \SB@lyricbox box. 2058 \newcommand\SB@chbstok{} 114 \SB@setchord The following macro typesets its argument as a chord and stores the result in box \SB@chordbox for later placement into the document. The hat token (^) is redefined so that outside of math mode it suppresses chord memorization, but inside of math mode it retains its usual superscript meaning. If memorization is active, the chord’s token sequence is stored in the current replay register. If \SB@chordbox is non-empty, the new chord is appended to it rather than replacing it. This allows consecutive chords not separated by whitespace to be typeset as a single chord sequence atop a common lyric. \newcommand\SB@setchord{} { 2061 \catcode‘^\active 2062 \catcode‘!7 2063 \gdef\SB@setchord#1{% 2064 \SB@gettabindtrue\SB@nohattrue% 2065 \setbox\SB@chordbox\hbox{% 2066 \unhbox\SB@chordbox% 2067 \begingroup% 2068 \ifSB@trackch% 2069 \def\SB@activehat{\ifmmode!\else\global\SB@nohatfalse\fi}% 2070 \else% 2071 \def\SB@activehat{% 2072 \ifmmode!\else\SB@lop\SB@ctail\SB@toks\the\SB@toks\fi% 2073 }% 2074 \fi% 2075 \let^\SB@activehat% 2076 \printchord{% 2077 \ifSB@firstchord\else\kern.15em\fi% 2078 \vphantom/% 2079 \transposehere{#1}% 2080 \kern.2em% 2081 }% 2082 \endgroup% 2083 }% 2084 \SB@gettabindfalse% 2085 \ifSB@trackch\ifSB@nohat% 2086 \global\SB@creg\expandafter{\the\SB@creg#1\\}% 2087 \fi\fi% 2088 \let\SB@noreplay\@firstofone% 2089 } 2090 } 2059 2060 \SB@outertest \SB@otesta \SB@otestb The lyric-scanning code must preemptively determine whether the next token is a macro declared \outer before it tries to accept that token as an argument. Otherwise TEX will abort with a parsing error. Macros declared \outer are not allowed in arguments, so determining whether a token is \outer is a delicate process. The following does so by consulting \meaning. A macro can be identified as \outer if its meaning has the word “\outer” before the first colon. 2091 \newcommand\SB@outertest{% 115 \expandafter\SB@otesta\meaning\SB@next:\SB@otesta% } 2094 \newcommand\SB@otesta{} 2095 \edef\SB@otesta#1:#2\SB@otesta{% 2096 \noexpand\SB@otestb% 2097 #1\string\outer% 2098 \noexpand\SB@otestb% 2099 } 2100 \newcommand\SB@otestb{} 2101 \expandafter\def\expandafter\SB@otestb% 2102 \expandafter#\expandafter1\string\outer#2\SB@otestb{% 2103 \def\SB@temp{#2}% 2104 \ifx\SB@temp\@empty\SB@testfalse\else\SB@testtrue\fi% 2105 } 2092 2093 \SB@UTFtest \SB@U@two \SB@U@three \SB@U@four \SB@@UTFtest To support UTF-8 encoded LATEX source files, we need to be able to identify multibyte characters during the lyric scanning process. Alas, the utf8.def file provides no clean way of identifying the macros it defines for this purpose. The best solution seems to be to look for any token named \UTFviii@. . .@octets in the top-level expansion of the macro. \newcommand\SB@UTFtest{} \edef\SB@UTFtest#1{% 2108 \noexpand\expandafter% 2109 \noexpand\SB@@UTFtest% 2110 \noexpand\meaning#1% 2111 \string\UTFviii@zero@octets% 2112 \noexpand\SB@@UTFtest% 2113 } 2114 \newcommand\SB@U@two{\global\SB@cnt\tw@} 2115 \newcommand\SB@U@three{\global\SB@cnt\thr@@} 2116 \newcommand\SB@U@four{\global\SB@cnt4\relax} 2117 \newcommand\SB@@UTFtest{} 2118 {\escapechar\m@ne 2119 \xdef\SB@temp{\string\@octets}} 2120 \edef\SB@temp{##1\string\UTFviii@##2\SB@temp} 2121 \expandafter\def\expandafter\SB@@UTFtest\SB@temp#3\SB@@UTFtest{% 2122 \SB@cnt\z@% 2123 {\csname SB@U@#2\endcsname}% 2124 } 2106 2107 \DeclareLyricChar \DeclareNonLyric \DeclareNoHyphen \SB@declare When scanning the lyric text that follows a chord, it is necessary to distinguish accents and other intra-word macros (which should be included in the under-chord lyric text) from other macros (which should be pushed out away from the text). The following macros allow users to declare a token to be lyric-continuing or lyricending. \newcommand\SB@declare[3]{% \afterassignment\iffalse\let\SB@next= #3\relax\fi% 2127 \SB@UTFtest\SB@next% 2128 \ifcase\SB@cnt% 2125 2126 116 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 \ifcat\noexpand#3\relax% \SB@addNtest\SB@macrotests#1#2#3% \else\ifcat\noexpand#3.% \SB@addDtest\SB@othertests#1#2% \else\ifcat\noexpand#3A% \SB@addDtest\SB@lettertests#1#2% \else% \SB@addDtest\relax0#2% \fi\fi\fi% \or% \SB@addNtest\SB@macrotests#1#2#3% \else% \SB@addMtest\SB@multitests#1#2#3\relax\relax\relax% \fi% } \newcommand\DeclareLyricChar{\SB@declare\SB@testtrue0} 2145 \newcommand\DeclareNonLyric{% 2146 \SB@declare\SB@testfalse\SB@testfalse% 2147 } 2148 \newcommand\DeclareNoHyphen{% 2149 \SB@declare\SB@testfalse\SB@testtrue% 2150 } 2143 2144 \SB@lettertests For speed, token tests introduced by \DeclareLyricChar and friends are broken \SB@macrotests out into separate macros based on category codes. \SB@multitests 2151 \newcommand\SB@lettertests{} \SB@othertests 2152 \newcommand\SB@macrotests{} 2153 \newcommand\SB@multitests{} 2154 \newcommand\SB@othertests{} The following macros add tests to the test macros defined above. In each, harg1 i is the test macro to which the test should be added, harg2 i and harg3 i is the code to be executed at scanning-time and at hyphenation-time if the test succeeds (or “0” if no action is to be performed), and harg4 i is the token to which the currently scanned token should be compared to determine whether it matches. \SB@addDtest A definition-test: The test succeeds if the next lyric token has the same meaning (at test-time) of the non-macro, non-active character token that was given to the \Declare macro. \newcommand\SB@addDtest[3]{% \ifx0#2\else% 2157 \def#1{{\csname SB@!\meaning\SB@next\endcsname}}% 2158 \expandafter\def\csname SB@!\meaning\SB@next\endcsname{\global#2}% 2159 \fi% 2160 \ifx0#3\else% 2161 \expandafter\def\csname SB@HT@\meaning\SB@next\endcsname{\global#3}% 2162 \fi% 2163 } 2155 2156 117 \SB@addNtest A name-test: The test succeeds if the next token is a non-\outer macro or active character and its \stringified name matches the \stringified name of the control sequence that was given to the \Declare macro. \newcommand\SB@addNtest[4]{% \ifx0#2\else% 2166 \def#1{{\csname SB@!\SB@nextname\endcsname}}% 2167 \expandafter\def\csname SB@!\string#4\endcsname{\global#2}% 2168 \fi% 2169 \ifx0#3\else% 2170 \expandafter\def\csname SB@HT@\string#4\endcsname{\global#3}% 2171 \fi% 2172 } 2164 2165 \SB@addMtest A multibyte-test: The test succeeds if the next lyric token is the beginning of a UTF-8 encoded multibyte character sequence that matches the multibyte sequence given to the \Declare macro. \newcommand\SB@addMtest[7]{% \edef\SB@temp{% 2175 \string#4% 2176 \ifx\relax#5\else\string#5\fi% 2177 \ifx\relax#6\else\string#6\fi% 2178 \ifx\relax#7\else\string#7\fi% 2179 }% 2180 \ifx0#2\else% 2181 \def#1{{\csname SB@!\SB@nextname\endcsname}}% 2182 \expandafter\def\csname SB@!\SB@temp\endcsname{\global#2}% 2183 \fi% 2184 \ifx0#3\else% 2185 \expandafter\def\csname SB@HT@\SB@temp\endcsname{\global#3}% 2186 \fi% 2187 } 2173 2174 The following code declares the common intra-word macros provided by TEX (as listed on p. 52 of The TEXbook) to be lyric-continuing. \DeclareLyricChar\‘ \DeclareLyricChar\’ 2190 \DeclareLyricChar\^ 2191 \DeclareLyricChar\" 2192 \DeclareLyricChar\~ 2193 \DeclareLyricChar\= 2194 \DeclareLyricChar\. 2195 \DeclareLyricChar\u 2196 \DeclareLyricChar\v 2197 \DeclareLyricChar\H 2198 \DeclareLyricChar\t 2199 \DeclareLyricChar\c 2200 \DeclareLyricChar\d 2201 \DeclareLyricChar\b 2202 \DeclareLyricChar\oe 2188 2189 118 \DeclareLyricChar\OE \DeclareLyricChar\ae 2205 \DeclareLyricChar\AE 2206 \DeclareLyricChar\aa 2207 \DeclareLyricChar\AA 2208 \DeclareLyricChar\o 2209 \DeclareLyricChar\O 2210 \DeclareLyricChar\l 2211 \DeclareLyricChar\L 2212 \DeclareLyricChar\ss 2213 \DeclareLyricChar\i 2214 \DeclareLyricChar\j 2215 \DeclareLyricChar\/ 2216 \DeclareLyricChar\2217 \DeclareLyricChar\discretionary 2203 2204 We declare \par to be lyric-ending without introducing hyphenation. The \par macro doesn’t actually appear in most verses because we use \obeylines, but we include a check for it in case the user says \par explicitly somewhere. 2218 \SB@bracket This macro gets invoked by the \[ macro whenever a chord begins. It gets redefined by code that turns chords on and off, so its initial definition doesn’t matter. 2219 \SB@chord \newcommand\SB@bracket{} Begin parsing a chord macro. While parsing the chord name argument, we set some special catcodes so that chord names can use # and & for sharps and flats. 2220 \SB@begincname \SB@endcname \DeclareNoHyphen\par \newcommand\SB@chord{\SB@begincname\SB@@chord} While parsing a chord name, certain characters such as # and & are temporarily set active so that they can be used as abbreviations for sharps and flats. To accomplish this, \SB@begincname must always be invoked before any macro whose argument is a chord name, and \SB@endcname must be invoked at the start of the body of any macro whose argument is a chord name. To aid in debugging, we also temporarily set hreturni characters and chord macros \outer. This will cause TEX to halt with a runaway argument error on the correct source line if the user forgets to type a closing end-brace (a common typo). Colon characters are also set non-active to avoid a conflict between the Babel French package and the \gtab macro. \newcommand\SB@begincname{} {\catcode‘\^^M\active 2223 \gdef\SB@begincname{% 2224 \begingroup% 2225 \catcode‘##\active\catcode‘&\active% 2226 \catcode‘:12\relax% 2227 \catcode‘\^^M\active\SB@outer\def^^M{}% 2228 \SB@outer\def\[{}% 2229 \chordlocals\relax% 2230 } 2221 2222 119 } \newcommand\SB@endcname{} 2233 \let\SB@endcname\endgroup 2231 2232 \SB@nbsp Non-breaking spaces (~) should be treated as spaces by the lyric-scanner code that follows. Although ~ is usually an active character that creates a non-breaking space, some packages (e.g., the Babel package) redefine it to produce accents, which are typically not lyric-ending. To distinguish the real ~ from redefined ~, we need to create a macro whose definition is the non-breaking space definition normally assigned to ~. 2234 2235 \SB@firstchord The following conditional is true when the current chord is the first chord in a sequence of one or more chord macros. 2236 \SB@@chord \newcommand\SB@nbsp{} \def\SB@nbsp{\nobreakspace{}} \newif\ifSB@firstchord\SB@firstchordtrue Finish processing the chord name and then begin scanning the implicit lyric argument that follows it. This is the main entrypoint to the lyric-scanner code. \newcommand*\SB@@chord{} \def\SB@@chord#1]{% 2239 \SB@endcname% 2240 \ifSB@firstchord% 2241 \setbox\SB@lyricbox\hbox{\kern\SB@tabindent}% 2242 \global\SB@tabindent\z@% 2243 \SB@lyric{}% 2244 \SB@numhyps\z@% 2245 \SB@spcinit% 2246 \setbox\SB@chordbox\box\voidb@x% 2247 \fi% 2248 \SB@setchord{#1}% 2249 \SB@firstchordfalse% 2250 \let\SB@dothis\SB@chstart% 2251 \SB@chscan% 2252 } 2237 2238 \MultiwordChords \SB@spcinit The \SB@spcinit macro is invoked at the beginning of the lyric scanning process. By default it does nothing, but if \MultiwordChords is invoked, it initializes the lyric-scanner state to process spaces as part of lyrics. \newcommand\SB@spcinit{} \newcommand\MultiwordChords{% 2255 \def\SB@spcinit{% 2256 \let\SB@chdone\SB@chlyrdone% 2257 \let\SB@chimpspace\SB@chnxtdone% 2258 \let\SB@chexpspace\SB@chnxtdone% 2259 \let\SB@chespace\SB@chendspace% 2260 }% 2261 } 2253 2254 120 \SB@chscan \SB@chmain This is the main loop of the lyric-scanner. Peek ahead at the next token without consuming it, then execute a loop body based on the current state (\SB@dothis), and finally go to the next iteration (\SB@donext). \newcommand\SB@chscan{% \let\SB@nextname\relax% 2264 \futurelet\SB@next\SB@chmain% 2265 } 2266 \newcommand\SB@chmain{\SB@dothis\SB@donext} 2262 2263 \SB@chnxtrelax To shorten the lyric parser macros that follow and thereby improve their speed, \SB@chnxtstep we here define some abbreviations for common logic in untaken branches. \SB@chnxtdone 2267 \newcommand\SB@chnxtrelax{\let\SB@donext\relax} 2268 \newcommand\SB@chnxtstep{\let\SB@donext\SB@chstep} 2269 \newcommand\SB@chnxtdone{\let\SB@donext\SB@chdone} Warning: In the lyric-scanner macros that follow, \SB@next might be a macro declared \outer. This means that it must never be passed as an argument to a macro and it must never explicitly appear in any untaken branch of a conditional. If it does, the TEX parser will complain of a runaway argument when it tries to skip over an \outer macro while consuming tokens at high speed. \SB@chstart We begin lyric-scanning with two special cases: (1) If the chord macro is immediately followed by another chord macro with no intervening whitespace, drop out of the lyric scanner and reenter it when the second macro is parsed. The chord texts will get concatenated together above the lyric that follows. (2) If the chord macro is immediately followed by one or more quote tokens, then consume them all and output them before the chord. This causes the chord to sit above the actual word instead of the left-quote or left-double-quote symbol, which looks better. \newcommand\SB@chstart{% \ifx\SB@next\[\SB@chnxtrelax% 2272 \else\ifx\SB@next\SB@activehat\SB@chnxtrelax% 2273 \else\ifx\SB@next\ch\SB@chnxtrelax% 2274 \else\ifx\SB@next\mch\SB@chnxtrelax% 2275 \else\ifx\SB@next‘\SB@chnxtstep% 2276 \else\ifx\SB@next’\SB@chnxtstep% 2277 \else\ifx\SB@next"\SB@chnxtstep% 2278 \else% 2279 \the\SB@lyric% 2280 \SB@lyric{}% 2281 \SB@firstchordtrue% 2282 \let\SB@dothis\SB@chnorm% 2283 \SB@chnorm% 2284 \fi\fi\fi\fi\fi\fi\fi% 2285 } 2270 2271 121 \SB@chnorm First, check to see whether the lyric token is a letter. Since that’s the most common case, we do this check first for speed. \newcommand\SB@chnorm{% \ifcat\noexpand\SB@next A% 2288 \SB@testtrue\SB@lettertests% 2289 \ifSB@test% 2290 \SB@chespace\SB@chnxtstep% 2291 \else% 2292 \SB@chnxtdone% 2293 \fi% 2294 \else% 2295 \SB@chtrymacro% 2296 \fi% 2297 } 2286 2287 \SB@chtrymacro Next, check to see whether it’s a macro or active character. We do these checks next because these are the only cases when the token might be \outer. Once we eliminate that ugly possibility, we can write the rest of the code without having to worry about putting \SB@next in places where \outer tokens are illegal. \newcommand\SB@chtrymacro{% \ifcat\noexpand\SB@next\relax% 2300 \SB@chmacro% 2301 \else% 2302 \SB@chother% 2303 \fi% 2304 } 2298 2299 \SB@chother The token is not a letter, macro, or active character. The only other cases of interest are spaces, braces, and hyphens. If it’s one of those, take the appropriate action; otherwise end the lyric here. Since we’ve eliminated the possibility of macros and active characters, we can be sure that the token isn’t \outer at this point. \newcommand\SB@chother{% \ifcat\noexpand\SB@next\@sptoken% 2307 \SB@chexpspace% 2308 \else\ifcat\noexpand\SB@next\bgroup% 2309 \SB@chespace\let\SB@donext\SB@chbgroup% 2310 \else\ifcat\noexpand\SB@next\egroup% 2311 \SB@chespace\let\SB@donext\SB@chegroup% 2312 \else\ifx\SB@next-% 2313 \SB@numhyps\@ne\relax% 2314 \SB@lyricnohyp\expandafter{\the\SB@lyric}% 2315 \let\SB@dothis\SB@chhyph% 2316 \SB@chespace\SB@chnxtstep% 2317 \else\ifcat\noexpand\SB@next.% 2318 \SB@testtrue\SB@othertests% 2319 \ifSB@test% 2320 \SB@chespace\SB@chnxtstep% 2321 \else% 2305 2306 122 \SB@chnxtdone% \fi% \else% \SB@chespace\SB@chnxtstep% \fi\fi\fi\fi\fi% 2322 2323 2324 2325 2326 2327 \SB@chmacro } The lyric-scanner has encountered a macro or active character. If it’s \outer, it should never be used in an argument, so stop here. \newcommand\SB@chmacro{% \SB@outertest% 2330 \ifSB@test% 2331 \SB@chnxtdone% 2332 \else% 2333 \let\SB@donext\SB@chgetname% 2334 \fi% 2335 } 2328 2329 \SB@chgetname We’ve encountered a non-\outer macro or active character. Use \string to get its name, but insert the token back into the input stream since we haven’t decided whether to consume it yet. \newcommand\SB@chgetname[1]{% \edef\SB@nextname{\string#1}% 2338 \SB@@chmacro\SB@donext#1% 2339 } 2336 2337 \SB@@chmacro The lyric-scanner has encountered a non-\outer macro or active character. Its \stringified name has been stored in \SB@nextname. Test to see whether it’s a known macro or the beginning of a multibyte-encoded international character. If the former, dispatch some macro-specific code to handle it. If the latter, grab the full multibyte sequence and include it in the lyric. \newcommand\SB@@chmacro{% \ifx\SB@next\SB@activehat% 2342 \SB@chnxtdone% 2343 \else\ifx\SB@next\SB@par% 2344 \SB@chnxtdone% 2345 \else\ifx\SB@next\measurebar% 2346 \SB@chmbar% 2347 \else\ifx\SB@next\mbar% 2348 \SB@chmbar% 2349 \else\ifx\SB@next\ch% 2350 \SB@chespace\let\SB@donext\SB@chlig% 2351 \else\ifx\SB@next\mch% 2352 \SB@chespace\let\SB@donext\SB@mchlig% 2353 \else\ifx\SB@next\ % 2354 \SB@chimpspace% 2355 \else\ifx\SB@next\SB@nbsp% 2356 \SB@chimpspace% 2357 \else% 2340 2341 123 \SB@UTFtest\SB@next% \ifcase\SB@cnt\SB@chothermac% \or\or\SB@chespace\let\SB@donext\SB@chsteptwo% \or\SB@chespace\let\SB@donext\SB@chstepthree% \or\SB@chespace\let\SB@donext\SB@chstepfour\fi% \fi\fi\fi\fi\fi\fi\fi\fi% 2358 2359 2360 2361 2362 2363 2364 \SB@chothermac } The lyric-scanner has encountered a macro or active character that is not \outer, not a known macro that requires special treatment, and not a multibyte international character. First, check the macro’s name (stored in \SB@nextname) to see whether it begins with a non-escape character. If so, it’s probably an accenting or punctuation character made active by the inputenc or babel packages. Most such characters should be included in the lyric, so include it by default; otherwise exclude it by default. The user can override the defaults using \DeclareLyricChar and friends. \newcommand\SB@chothermac{% \SB@testfalse% 2367 \afterassignment\iffalse% 2368 \SB@cnt\expandafter‘\SB@nextname x\fi% 2369 \ifnum\the\catcode\SB@cnt=\z@\else\SB@testtrue\fi% 2370 \SB@macrotests% 2371 \ifSB@test% 2372 \SB@chespace\SB@chnxtstep% 2373 \else% 2374 \SB@chnxtdone% 2375 \fi% 2376 } 2365 2366 \SB@chstep We’ve encountered one or more tokens that should be included in the lyric text. \SB@chsteptwo (More than one means we’ve encountered a multibyte encoding of an international \SB@chstepthree character.) Consume them (as arguments to this macro) and add them to the list \SB@chstepfour of tokens we’ve already consumed. \SB@chmulti 2377 \newcommand\SB@chstep[1]{% \SB@chmstop 2378 \SB@lyric\expandafter{\the\SB@lyric#1}% 2379 \SB@chscan% 2380 } 2381 \newcommand\SB@chsteptwo[2]{\SB@chmulti{#1#2}{\string#1\string#2}} 2382 \newcommand\SB@chstepthree[3]{% 2383 \SB@chmulti{#1#2#3}{\string#1\string#2\string#3}% 2384 } 2385 \newcommand\SB@chstepfour[4]{% 2386 \SB@chmulti{#1#2#3#4}{\string#1\string#2\string#3\string#4}% 2387 } 2388 \newcommand\SB@chmulti[2]{% 2389 \def\SB@next{#1}% 2390 \edef\SB@nextname{#2}% 2391 \SB@testtrue\SB@multitests% 2392 \ifSB@test% 124 2393 2394 2395 2396 2397 2398 2399 \SB@chhyph \SB@lyric\expandafter{\the\SB@lyric#1}% \expandafter\SB@chscan% \else% \expandafter\SB@chmstop% \fi% } \newcommand\SB@chmstop{\expandafter\SB@chdone\SB@next} We’ve encountered a hyphen. Continue to digest hyphens, but terminate as soon as we see anything else. \newcommand\SB@chhyph{% \ifx\SB@next-% 2402 \advance\SB@numhyps\@ne\relax% 2403 \SB@chnxtstep% 2404 \else% 2405 \SB@chnxtdone% 2406 \fi% 2407 } 2400 2401 \SB@chimpspace \SB@chexpspace We’ve encountered an implicit or explicit space. Normally this just ends the lyric, but if \MultiwordChords is active, these macros both get redefined to process the space. \newcommand\SB@chimpspace{} \let\SB@chimpspace\SB@chnxtdone 2410 \newcommand\SB@chexpspace{} 2411 \let\SB@chexpspace\SB@chnxtdone 2408 2409 \SB@chespace \SB@chendspace The \SB@chespace macro gets invoked by the lyric-scanner just before a nonspace token is about to be accepted as part of an under-chord lyric. Normally it does nothing; however, if \MultiwordChords is active, it gets redefined to do one of three things: (1) Initially it is set equal to \SB@chendspace so that if the very first token following the chord macro is not a space, the lyric-scanner macros are redefined to process any future spaces encountered. Otherwise the very first token is a space, and the lyric ends immediately. (2) While scanning non-space lyric tokens, it is set to nothing, since no special action needs to be taken until we encounter a sequence of one or more spaces. (3) When a space token is encountered (but not the very first token after the chord macro), it is set equal to \SB@chendspace again so that \SB@chendspace is invoked once the sequence of one or more space tokens is finished. \newcommand\SB@chespace{} \newcommand\SB@chendspace{% 2414 \let\SB@chdone\SB@chlyrdone% 2415 \def\SB@chexpspace{\SB@chbspace\SB@chexpspace}% 2416 \def\SB@chimpspace{\SB@chbspace\SB@chimpspace}% 2417 \def\SB@chespace{}% 2418 } 2412 2413 125 \SB@chbspace \SB@chgetspace The \SB@chbspace macro gets invoked when \MultiwordChords is active and the lyric-scanner has encountered a space token that was immediately preceded by a non-space token. Before processing the space, we add all lyrics seen so far to the \SB@lyricbox and check its width. If we’ve seen enough lyrics to match or exceed the width of the chord, a space stops the lyric-scanning process. (This is important because it minimizes the size of the chord box, providing as many line breakpoints as possible to the paragraph-formatter.) Otherwise we begin scanning space tokens without adding them to the lyric until we see what the next non-space token is. If the next non-space token would have ended the lyric anyway, roll back and end the lyric here, reinserting the space tokens back into the token stream. If the next non-space token would have been included in the lyric, the lyric-scanner proceeds as normal. \newcommand\SB@chbspace{% \setbox\SB@lyricbox\hbox{% 2421 \unhbox\SB@lyricbox% 2422 \the\SB@lyric% 2423 }% 2424 \SB@lyric{}% 2425 \ifdim\wd\SB@lyricbox<\wd\SB@chordbox% 2426 \let\SB@chbstok= \SB@next% 2427 \def\SB@chexpspace{\let\SB@donext\SB@chgetspace}% 2428 \let\SB@chimpspace\SB@chnxtstep% 2429 \let\SB@chespace\SB@chendspace% 2430 \let\SB@chdone\SB@chspcdone% 2431 \else% 2432 \let\SB@chimpspace\SB@chnxtdone% 2433 \let\SB@chexpspace\SB@chnxtdone% 2434 \fi% 2435 } 2436 \newcommand\SB@chgetspace{% 2437 \SB@appendsp\SB@lyric% 2438 \let\SB@nextname\relax% 2439 \afterassignment\SB@chscan% 2440 \let\SB@next= } 2419 2420 \SB@chmbar We’ve encountered a measure bar. Either ignore it or end the lyric text, depending on whether measure bars are being displayed. \newcommand\SB@chmbar{% \ifmeasures% 2443 \SB@chnxtdone% 2444 \else% 2445 \SB@chespace\SB@chnxtstep% 2446 \fi% 2447 } 2441 2442 \SB@chbgroup We’ve encountered a begin-group brace. Consume the entire group that it begins, and add it to the list of tokens including the begin and end group tokens. 2448 \newcommand\SB@chbgroup[1]{% 126 \SB@lyric\expandafter{\the\SB@lyric{#1}}% \SB@chscan% 2449 2450 2451 \SB@chegroup \SB@chegrpscan \SB@chegrpmacro \SB@chegrpouter \SB@chegrpname \SB@chegrpdone } We’ve encountered an end-group brace whose matching begin-group brace must have come before the chord macro itself. This forcibly ends the lyric text. Before stopping, we must set \SB@next to the token following the brace and \SB@nextname to its \stringified name so that \SB@emitchord will know whether to add hyphenation. Therefore, we temporarily consume the end-group brace, then scan the next token without consuming it, and finally reinsert the end-group brace and stop. \newcommand\SB@chegroup{% \let\SB@nextname\relax% 2454 \afterassignment\SB@chegrpscan% 2455 \let\SB@next= } 2456 \newcommand\SB@chegrpscan{% 2457 \futurelet\SB@next\SB@chegrpmacro% 2458 } 2459 \newcommand\SB@chegrpmacro{% 2460 \ifcat\noexpand\SB@next\relax% 2461 \expandafter\SB@chegrpouter% 2462 \else% 2463 \expandafter\SB@chegrpdone% 2464 \fi% 2465 } 2466 \newcommand\SB@chegrpouter{% 2467 \SB@outertest% 2468 \ifSB@test% 2469 \expandafter\SB@chegrpdone% 2470 \else% 2471 \expandafter\SB@chegrpname% 2472 \fi% 2473 } 2474 \newcommand\SB@chegrpname[1]{% 2475 \edef\SB@nextname{\string#1}% 2476 \SB@chegrpdone#1% 2477 } 2478 \newcommand\SB@chegrpdone{\SB@chdone\egroup} 2452 2453 \SB@chlig \SB@mchlig We’ve encountered a \ch chord-over-ligature macro, or an \mch measurebar-andchord-over-ligature macro. Consume it and all of its arguments, and load them into some registers for future processing. (Part of the ligature might fall into this lyric text or might not, depending on whether we decide to add hyphenation.) Then end the lyric text here. \newcommand\SB@chlig[5]{% \gdef\SB@ligpre{{#3}}% 2481 \gdef\SB@ligpost{\[#2]{#4}}% 2482 \gdef\SB@ligfull{\[\SB@noreplay{\hphantom{{\lyricfont#3}}}#2]{#5}}% 2483 \SB@chdone% 2479 2480 127 } \newcommand\SB@mchlig[5]{% 2486 \SB@lyric\expandafter{\the\SB@lyric#3}% 2487 \let\SB@next\measurebar% 2488 \edef\SB@nextname{\string\measurebar}% 2489 \gdef\SB@ligpost{\measurebar\[#2]{#4}}% 2490 \gdef\SB@ligfull{\measurebar\[#2]{#4}}% 2491 \SB@chdone% 2492 } 2484 2485 \SB@chdone \SB@chlyrdone \SB@chspcdone The \SB@chdone macro is invoked when we’ve decided to end the lyric text (usually because we’ve encountered a non-lyric token). Normally this expands to \SB@chlyrdone, which adds any uncontributed lyric material to the \SB@lyricbox and jumps to the main chord formatting macro. However, if \MultiwordChords is active and if the lyric ended with a sequence of one or more space tokens, then we instead reinsert the space tokens into the token stream without contributing them to the \SB@lyricbox. \newcommand\SB@chlyrdone{% \setbox\SB@lyricbox\hbox{% 2495 \unhbox\SB@lyricbox% 2496 \ifnum\SB@numhyps=\@ne% 2497 \the\SB@lyricnohyp% 2498 \else% 2499 \the\SB@lyric% 2500 \fi% 2501 }% 2502 \SB@emitchord% 2503 } 2504 \newcommand\SB@chspcdone{% 2505 \let\SB@nextname\relax% 2506 \let\SB@next= \SB@chbstok% 2507 \expandafter\SB@emitchord\the\SB@lyric% 2508 } 2509 \newcommand\SB@chdone{} 2510 \let\SB@chdone\SB@chlyrdone 2493 2494 \SB@ligpre The following three macros record arguments passed to a \ch macro that concludes \SB@ligpost the lyric text of the \[] macro currently being processed. \SB@ligfull 2511 \newcommand\SB@ligpre{} 2512 \newcommand\SB@ligpost{} 2513 \newcommand\SB@ligfull{} \SB@clearlig Clear all ligature-chord registers. \newcommand\SB@clearlig{% \gdef\SB@ligpre{}% 2516 \gdef\SB@ligpost{}% 2517 \gdef\SB@ligfull{}% 2518 } 2514 2515 128 16.11 \SB@emitchord Chords The \SB@emitchord macro does the actual work of typesetting chord text over lyric text, introducing appropriate hyphenation when necessary. We begin by consulting \SB@next, which should have been set by the lyric-scanning code in §16.10 to the token that immediately follows the lyric under this chord, to determine whether the lyric text ends on a word boundary. \newcommand\SB@emitchord{% \ifSB@inverse\else\ifSB@inchorus\else\SB@errchord\fi\fi% 2521 \SB@testfalse% 2522 \ifcat\noexpand\SB@next\@sptoken\SB@testtrue\fi% 2523 \ifcat\noexpand\SB@next.\SB@testtrue\fi% 2524 \ifx\SB@next\SB@par\SB@testtrue\fi% 2525 \ifx\SB@next\egroup\SB@testtrue\fi% 2526 \ifx\SB@next\endgroup\SB@testtrue\fi% 2527 {\csname% 2528 SB@HT@\ifx\SB@nextname\relax\meaning\SB@next\else\SB@nextname\fi% 2529 \endcsname}% 2530 \ifSB@test\SB@wordendstrue\else\SB@wordendsfalse\fi% 2519 2520 Next, compare the width of the lyric to the width of the chord to determine whether hyphenation might be necessary. The original lyric text might have ended in a string of one or more explicit hyphens, enumerated by \SB@numhyps. If it ended in exactly one, the lyric-scanning code suppresses that hyphen so that we can here add a new hyphen that floats out away from the word when the chord above it is long. If it ended in more than one (e.g., the encoding of an en- or em-dash) then the lyric-scanner leaves it alone; we must not add any hyphenation or float the dash away from the word. There is also code here to insert a penalty that discourages linebreaking immediately before lyricless chords. Beginning a wrapped line with a lyricless chord is undesirable because it makes it look as though the wrapped line is extra-indented (due to the empty lyric space below the chord). It should therefore happen only as a last resort. 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 \SB@dimen\wd\SB@chordbox% \ifvmode\leavevmode\fi% \SB@brokenwordfalse% \ifdim\wd\SB@lyricbox>\z@% \ifdim\SB@dimen>\wd\SB@lyricbox% \ifSB@wordends\else\SB@brokenwordtrue\fi% \fi% \else% \SB@skip\lastskip% \unskip\penalty200\hskip\SB@skip% \fi% \ifnum\SB@numhyps>\z@% \ifnum\SB@numhyps>\@ne% \SB@brokenwordfalse% \else% \SB@brokenwordtrue% 129 2547 2548 \fi% \fi% If lyrics are suppressed on this line (e.g., by using \nolyrics), then just typeset the chord text on the natural baseline. 2549 2550 2551 2552 2553 2554 \SB@testfalse% \ifnolyrics\ifdim\wd\SB@lyricbox=\z@\SB@testtrue\fi\fi% \ifSB@test% \unhbox\SB@chordbox% \gdef\SB@temp{\expandafter\SB@clearlig\SB@ligfull}% \else% Otherwise, typeset the chord above the lyric on a double-height line. 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 \vbox{\clineparams\relax% \ifSB@brokenword% \global\setbox\SB@lyricbox\hbox{% \unhbox\SB@lyricbox% \SB@ligpre% }% \SB@maxmin\SB@dimen<{\wd\SB@lyricbox}% \advance\SB@dimen.5em% \hbox to\SB@dimen{\unhbox\SB@chordbox\hfil}% \hbox to\SB@dimen{% \unhcopy\SB@lyricbox\hfil\char\hyphenchar\font\hfil% }% \global\SB@cnt\@m% \gdef\SB@temp{\expandafter\SB@clearlig\SB@ligpost}% \else% \box\SB@chordbox% \hbox{% \unhcopy\SB@lyricbox% \global\SB@cnt\spacefactor% \hfil% }% \gdef\SB@temp{\expandafter\SB@clearlig\SB@ligfull}% \fi% }% If the chord is lyricless, inhibit a linebreak immediately following it. This prevents sequences of lyricless chords (which often end lines) from being wrapped in the middle, which looks very unsightly and makes them difficult to read. If the chord has a lyric but it doesn’t end on a word boundary, insert an appropriate penalty to prevent linebreaking without hyphenation. Also preserve the spacefactor in this case, which allows LATEX to fine-tune the spacing between consecutive characters in the word that contains the chord. 2579 2580 2581 2582 2583 \ifSB@wordends% \ifdim\wd\SB@lyricbox>\z@\else\nobreak\fi% \else% \penalty% \ifnum\SB@numhyps>\z@\exhyphenpenalty% 130 \else\ifSB@brokenword\hyphenpenalty% \else\@M\fi\fi% \spacefactor\SB@cnt% \fi% \fi% 2584 2585 2586 2587 2588 Finally, end the macro with some code that handles the special case that this chord is immediately followed by a chord-over-ligature macro. The code above sets \SB@temp to the portion of the ligature that should come after this chord but before the chord that tops the ligature. This text must be inserted here. \SB@temp% 2589 2590 \SB@accidental } Typeset an accidental symbol as a superscript within a chord. Since chord names are often in italics but math symbols like sharp and flat are not, we need to do some kerning adjustments before and after the accidental to position it as if it were italicized. The pre-adjustment is just a simple italic correction using \/. The post-adjustment is based on the current font’s slant-per-point metric. \newcommand\SB@accidental[1]{{% \/% 2593 \m@th#1% 2594 \SB@dimen-\fontdimen\@ne\font% 2595 \advance\SB@dimen.088142\p@% 2596 \ifdim\SB@dimen<\z@% 2597 \kern\f@size\SB@dimen% 2598 \fi% 2599 }} 2591 2592 \sharpsymbol \flatsymbol When changing the sharp or flat symbol, change these macros rather than changing \shrp or \flt. This will ensure that other shortcuts like # and & will reflect your change. 2600 2601 \newcommand\sharpsymbol{\ensuremath{^\#}} \newcommand\flatsymbol{\raise.5ex\hbox{{\SB@flatsize$\flat$}}} \shrp These macros typeset sharp and flat symbols. \flt 2602 \newcommand\shrp{\SB@accidental\sharpsymbol} 2603 \newcommand\flt{\SB@accidental\flatsymbol} \DeclareFlatSize The \flat math symbol is too small for properly typesetting chord names. (Its size was designed for staff notation not textual chord names.) The correct size for the symbol should be approximately 30% larger than the current superscript size, or 90% of the base font size b. However, simply computing 0.9b does not work well because most fonts do not render well in arbitrary sizes. To solve the problem, we must therefore choose an appropriate size individually for each possible base font size b. This is the solution adopted by the rest of LATEX for such things. For example, LATEX’s \DeclareMathSizes macro defines an appropriate superscript size for each possible base font size. The macro below creates a similar macro that that defines an appropriate flat-symbol size for each possible base font size. 131 \newcommand\DeclareFlatSize[2]{% \expandafter\xdef\csname SB@flatsize@#1\endcsname{#2}% 2606 } 2607 \DeclareFlatSize\@vpt\@vpt 2608 \DeclareFlatSize\@vipt\@vipt 2609 \DeclareFlatSize\@viipt\@vipt 2610 \DeclareFlatSize\@viiipt\@viipt 2611 \DeclareFlatSize\@ixpt\@viiipt 2612 \DeclareFlatSize\@xpt\@ixpt 2613 \DeclareFlatSize\@xipt\@xpt 2614 \DeclareFlatSize\@xiipt\@xipt 2615 \DeclareFlatSize\@xivpt\@xiipt 2616 \DeclareFlatSize\@xviipt\@xivpt 2617 \DeclareFlatSize\@xxpt\@xviipt 2618 \DeclareFlatSize\@xxvpt\@xxpt 2604 2605 \SB@flatsize Select the correct flat symbol size based on the current font size. \newcommand\SB@flatsize{% \@ifundefined{SB@flatsize@\f@size}{}{% 2621 \expandafter\fontsize% 2622 \csname SB@flatsize@\f@size\endcsname\f@baselineskip% 2623 \selectfont% 2624 }% 2625 } 2619 2620 In the following code, the \ch, \mch, \[, and ^ macros are each defined to be a single macro that then expands to the real definition. This is necessary because the top-level definitions of each must stay the same in order to allow the lyricscanning code to uniquely identify them, yet their internal definitions must be redefined by code that turns chords and/or measure bars on and off. Such code redefines \SB@ch, \SB@mch, \SB@bracket, and \SB@rechord to effect a change of mode without touching the top-level definitions. \ch \SB@ch \SB@ch@on \SB@@ch \SB@@@ch \SB@ch@off The \ch macro puts a chord atop a ligature without breaking the ligature. Normally this just means placing the chord midway over the unbroken ligature (ignoring the third argument completely). However, when a previous chord macro encounters it while scanning ahead in the input stream to parse its lyric, the \ch macro itself is not actually expanded at all. Instead, the chord macro scans ahead, spots the \ch macro, gobbles it, and then steals its arguments, breaking the ligature with hyphenation. Thus, the \ch macro is only actually expanded when the ligature shouldn’t be broken. \newcommand\ch{\SB@ch} \newcommand\SB@ch{} 2628 \newcommand\SB@ch@on{\SB@begincname\SB@@ch} 2629 \newcommand*\SB@@ch[1]{\SB@endcname\SB@@@ch{#1}} 2630 \newcommand*\SB@@@ch[4]{\[\SB@noreplay{\hphantom{#2}}#1]#4} 2631 \newcommand*\SB@ch@off[4]{#4} 2626 2627 132 \mch The \mch macro is like \ch except that it also introduces a measure bar. \SB@mch 2632 \newcommand\mch{\SB@mch} \SB@mch@m 2633 \newcommand\SB@mch{} \SB@mch@on 2634 \newcommand*\SB@mch@m[4]{#2\measurebar#3} \SB@@mch 2635 \newcommand\SB@mch@on{\SB@begincname\SB@@mch} \SB@@@mch 2636 \newcommand*\SB@@mch[1]{\SB@endcname\SB@@@mch{#1}} 2637 \newcommand*\SB@@@mch[4]{#2\measurebar\[#1]#3} \SB@activehat This macro must always contain the current definition of the ^ chord-replay active character, in order for the lyric scanner to properly identify it and insert proper hyphenation when necessary. \newcommand\SB@activehat{% \ifmmode^\else\expandafter\SB@rechord\fi% 2640 } 2638 2639 \SB@loadactives It’s cumbersome to have to type \shrp, \flt, and \mbar every time you want a sharp, flat, or measure bar, so within verses and choruses we allow the hash, ampersand, and pipe symbols to perform the those functions too. It’s also cumbersome to have to type something like \chord{Am}{lyric} to produce each chord. As an easier alternative, we here define \[Am] to typeset chords. \newcommand\SB@loadactives{} { 2643 \catcode‘&\active 2644 \catcode‘#\active 2645 \catcode‘|\active 2646 \catcode‘^\active 2647 \global\let&\flt 2648 \global\let#\shrp 2649 \global\let|\measurebar 2650 \global\let^\SB@activehat 2651 \gdef\SB@loadactives{% 2652 \catcode‘^\ifchorded\active\else9 \fi% 2653 \catcode‘|\ifmeasures\active\else9 \fi% 2654 \def\[{\SB@bracket}% 2655 } 2656 } 2641 2642 16.12 \SB@trackch While inside a verse where the chord history is being remembered for future verses, \SB@trackch is true. 2657 \SB@cr@ Chord Replaying \newif\ifSB@trackch Reserve token registers to record a history of the chords seen in a verse. 2658 2659 \SB@newtoks\SB@cr@ \SB@newtoks\SB@ctail 133 \SB@creg The following control sequence equals the token register being memorized into or replayed from. 2660 \newchords \newcommand\SB@creg{} Allocate a new chord-replay register to hold memorized chords. \newcommand\newchords[1]{% \@ifundefined{SB@cr@#1}{% 2663 \expandafter\SB@newtoks\csname SB@cr@#1\endcsname% 2664 \global\csname SB@cr@#1\endcsname{\\}% 2665 }{\SB@errdup{#1}}% 2666 } 2661 2662 \memorize \SB@memorize Saying \memorize throws out any previously memorized list of chords and starts memorizing chords until the end of the current verse or chorus. \newcommand\memorize{% \@ifnextchar[\SB@memorize{\SB@memorize[]}% 2669 } 2670 \newcommand\SB@memorize{} 2671 \def\SB@memorize[#1]{% 2672 \@ifundefined{SB@cr@#1}{\SB@errreg{#1}}{% 2673 \SB@trackchtrue% 2674 \global\expandafter\let\expandafter\SB@creg% 2675 \csname SB@cr@#1\endcsname% 2676 \global\SB@creg{\\}% 2677 }% 2678 } 2667 2668 \replay Saying \replay stops any memorization and begins replaying memorized chords. \SB@replay 2679 \newcommand\replay{\@ifnextchar[\SB@replay\SB@@replay} \SB@@replay 2680 \newcommand\SB@replay{} 2681 \def\SB@replay[#1]{% 2682 \@ifundefined{SB@cr@#1}{\SB@errreg{#1}}{% 2683 \SB@trackchfalse% 2684 \global\expandafter\let\expandafter\SB@creg% 2685 \csname SB@cr@#1\endcsname% 2686 \global\SB@ctail\SB@creg% 2687 }% 2688 } 2689 \newcommand\SB@@replay{% 2690 \SB@trackchfalse% 2691 \global\SB@ctail\SB@creg% 2692 } \SB@rechord Replay the same chord that was in a previous verse. \SB@@rechord 2693 \newcommand\SB@rechord{} 2694 \newcommand\SB@@rechord{% 2695 \SB@ifempty\SB@ctail{% 2696 \SB@errreplay% 2697 \SB@toks{}% 134 \let\SB@donext\@gobble% }{% \SB@lop\SB@ctail\SB@toks% \let\SB@donext\SB@chord% \let\SB@noreplay\@gobble% }% \expandafter\SB@donext\the\SB@toks]% 2698 2699 2700 2701 2702 2703 2704 2705 \ifSB@nohat The \ifSB@nohat conditional is set to false when a chord macro contains a ^ in its argument. This suppresses the recording mechanism momentarily so that replays will skip this chord. 2706 \SB@noreplay } \newif\ifSB@nohat Sometimes material must be added to a chord but omitted when the chord is replayed. We accomplish this by enclosing such material in \SB@noreplay macros, which are set to \@gobble just before a replay and reset to \@firstofone at other times. 2707 2708 \newcommand\SB@noreplay{} \let\SB@noreplay\@firstofone 16.13 Guitar Tablatures The song book software not only supports chord names alone, but can also typeset guitar tablature diagrams. The macros for producing these diagrams are found here. \SB@fretwidth Set the width of each vertical string in the tablature diagram. 2709 2710 \SB@fretnum \newlength\SB@fretwidth \setlength\SB@fretwidth{6\p@} Typeset a fret number to appear to the left of the diagram. \newcommand\SB@fretnum[1]{{% \sffamily\fontsize\@xpt\@xpt\selectfont#1% 2713 }} 2711 2712 \SB@onfret Typeset one string of one fret with harg1 i typeset overtop of it (usually a dot or nothing at all). \newcommand\SB@onfret[1]{% \rlap{\hbox to\SB@fretwidth{\hfil\vrule\@height6\p@\hfil}}% 2716 \hbox to\SB@fretwidth{\hfil#1\hfil}% 2717 } 2714 2715 \SB@atopfret Typeset material (given by harg1 i) to be placed above a string in the tablature diagram. \newcommand\SB@atopfret[1]{% \hbox to\SB@fretwidth{\hfil#1\hfil}% 2720 } 2718 2719 135 \SB@fretbar Typeset a horizontal fret bar of width \SB@dimen. \newcommand\SB@fretbar{% \nointerlineskip% 2723 \hbox to\SB@dimen{% 2724 \advance\SB@dimen-\SB@fretwidth% 2725 \advance\SB@dimen.4\p@% 2726 \hfil% 2727 \vrule\@width\SB@dimen\@height.4\p@\@depth\z@% 2728 \hfil% 2729 }% 2730 \nointerlineskip% 2731 } 2721 2722 \SB@topempty Above a string in a tablature diagram there can be nothing, an ×, or an ◦. \SB@topX 2732 \newcommand\SB@topempty{\SB@atopfret\relax} \SB@topO 2733 \newcommand\SB@topX{\SB@atopfret{% 2734 \hbox{% 2735 \kern-.2\p@% 2736 \fontencoding{OMS}\fontfamily{cmsy}% 2737 \fontseries{m}\fontshape{n}% 2738 \fontsize\@viipt\@viipt\selectfont\char\tw@% 2739 \kern-.2\p@% 2740 }% 2741 }} 2742 \newcommand\SB@topO{\SB@atopfret{% 2743 \vrule\@width\z@\@height4.3333\p@\@depth.8333\p@% 2744 \lower.74\p@\hbox{% 2745 \fontencoding{OMS}\fontfamily{cmsy}% 2746 \fontseries{m}\fontshape{n}% 2747 \fontsize\@xpt\@xpt\selectfont\char14% 2748 }% 2749 }} \SB@fretempty On a string in a fret diagram there can be nothing or a filled circle. \SB@frethit 2750 \newcommand\SB@fretempty{\SB@onfret\relax} 2751 \newcommand\SB@frethit{\SB@onfret{% 2752 \hbox{% 2753 \fontencoding{OMS}\fontfamily{cmsy}% 2754 \fontseries{m}\fontshape{n}% 2755 \fontsize\@xiipt\@xiipt\selectfont\char15% 2756 }% 2757 }} \SB@finger If we’re including fingering info in the tablature diagram, then below each string there might be a number. \newcommand\SB@finger[1]{% \SB@atopfret{\sffamily\fontsize\@vipt\@vipt\selectfont#1}% 2760 } 2758 2759 136 \ifSB@gettabind \SB@tabindent Lyrics under tablature diagrams look odd if they aren’t aligned with the leftmost string of the diagram. To accomplish this, the following two macros record the amount by which a lyric under this tablature diagram must be indented to position it properly. 2761 2762 \SB@targfret \SB@targstr \SB@targfing \newif\ifSB@gettabind\SB@gettabindfalse \SB@newdimen\SB@tabindent Reserve some macro names in which to store the three pieces of the second argument to the \gtab macro. The first is for the fret number, the second is for the hstringsi info, and the last is for the hfingeringi info. \newcommand\SB@targfret{} \newcommand\SB@targstr{} 2765 \newcommand\SB@targfing{} 2763 2764 In general \gtab macros often appear inside chord macros, which means that their arguments have already been scanned by the time the \gtab macro itself is expanded. This means that catcodes cannot be reassigned (without resorting to ε-TEX). We therefore adopt the alternative strategy of converting each token in the hstringsi and hfingeringi arguments of a \gtab macro into a control sequence (using \csname). We can then temporarily assign meanings to those control sequences and replay the arguments to achieve various effects. \SB@csify \SB@@csify Convert all tokens in the first argument to control sequences and store the resulting sequence into the macro given by the first argument. Store the length in tokens into counter register \SB@cnt. \newcommand\SB@csify[2]{% \SB@toks{}% 2768 \SB@cnt\z@% 2769 \SB@@csify#2\SB@@csify% 2770 \edef#1{\the\SB@toks}% 2771 } 2772 \newcommand\SB@@csify[1]{% 2773 \ifx#1\SB@@csify\else% 2774 \advance\SB@cnt\@ne% 2775 \SB@toks\expandafter{\the\SB@toks\csname#1\endcsname}% 2776 \expandafter\SB@@csify% 2777 \fi% 2778 } 2766 2767 \SB@gttop \SB@gtinit \SB@gtinc \SB@gtset Different meanings are assigned to digits, X’s, and O’s depending on whether we are currently typesetting the material overtop the diagram, the interior of the diagram, or the fingering numbers below the diagram. These meanings are set by \SB@gttop, \SB@gtinit & \SB@gtinc, and \SB@gtset, respectively. \newcommand\SB@gttop{% \let\X\SB@topX\let\0\SB@topO\let\O\0\let\1\SB@topempty% 2781 \let\2\1\let\3\1\let\4\1\let\5\1% 2782 \let\6\1\let\7\1\let\8\1\let\9\1% 2779 2780 137 } \newcommand\SB@gtinit{% 2785 \let\X\SB@fretempty\let\0\X\let\O\X\let\1\SB@frethit% 2786 \let\2\X\let\3\X\let\4\X\let\5\X% 2787 \let\6\X\let\7\X\let\8\X\let\9\X% 2788 } 2789 \newcommand\SB@gtinc{% 2790 \let\9\8\let\8\7\let\7\6\let\6\5\let\5\4% 2791 \let\4\3\let\3\2\let\2\1\let\1\0% 2792 } 2793 \newcommand\SB@gtset[2]{% 2794 \let\X#1\let\0\X\let\O\X% 2795 \def\1{#21}\def\2{#22}\def\3{#23}% 2796 \def\4{#24}\def\5{#25}\def\6{#26}% 2797 \def\7{#27}\def\8{#28}\def\9{#29}% 2798 } 2783 2784 \SB@gtmax To compute the height of the tablature diagram, we must identify the maximum fret number in the hstringsi argument. This is accomplished by using the following macro in combination with \SB@gtset above. 2799 \gtab \SB@gtab \newcommand\SB@gtmax[1]{\ifnum\SB@cnt<#1\SB@cnt#1\fi} A \gtab macro begins by setting catcodes suitable for parsing a chord name as its first argument. This allows tokens like # and & to be used for sharp and flat even when \gtab is used outside a chord macro. Colon is reset to a non-active character while processing the second argument to avoid a potential conflict with Babel French. \newcommand\gtab{\SB@begincname\SB@gtab} \newcommand*\SB@gtab[1]{% 2802 \SB@endcname% 2803 \begingroup% 2804 \catcode‘:12\relax% 2805 \SB@@gtab{#1}% 2806 } 2800 2801 \SB@@gtab If transposition is currently taking place, allow the user to customize the behavior by redefining \gtabtrans. Using \gtab within \gtabtrans should go directly to \SB@@@gtab (otherwise an infinite loop would result!). \newcommand*\SB@@gtab[2]{% \endgroup% 2809 \ifnum\SB@transposefactor=\z@% 2810 \SB@@@gtab{#1}{#2}% 2811 \else% 2812 \begingroup% 2813 \let\gtab\SB@@@gtab% 2814 \gtabtrans{#1}{#2}% 2815 \endgroup% 2816 \fi% 2817 } 2807 2808 138 \gtabtrans By default, transposed guitar tablatures just display the transposed chord name and omit the diagram. Transposing a tablature diagram requires manual judgment calls for most stringed instruments, so we can’t do it automatically. 2818 \SB@@@gtab \newcommand\gtabtrans[2]{\transposehere{#1}} Typeset a full tablature diagram. Text harg1 i is a chord name placed above the diagram. Text harg2 i consists of a colon-separated list of: (1) an optional fret number placed to the left of the diagram; (2) a sequence of tokens, each of which can be X (to place an × above the string), 0 or O (to place an ◦ above the string), or one of 1 through 9 (to place a filled circle on that string at the fret of the given number); and (3) an optional sequence of tokens, each of which is either 0 (no fingering information for that string), or one of 1 through 4 (to place the given number under that string). \newcommand\SB@@@gtab[2]{% \let\SB@targfret\@empty% 2821 \let\SB@targstr\@empty% 2822 \let\SB@targfing\@empty% 2823 \SB@tabargs#2:::\SB@tabargs% 2824 \ifx\SB@targstr\@empty% 2825 \def\SB@targstr{\0\0\0\0\0\0}% 2826 \fi% 2827 \ifvmode\leavevmode\fi% 2828 \vbox{% 2829 \normalfont\normalsize% 2830 \setbox\SB@box\hbox{% 2831 \thinspace{\printchord{\transposehere{#1}\strut}}\thinspace% 2832 }% 2833 \setbox\SB@boxii\hbox{\SB@fretnum{\SB@targfret}}% 2834 \setbox\SB@boxiii\hbox{{\SB@gttop\SB@targstr}}% 2835 \hsize\wd\SB@box% 2836 \ifSB@gettabind% 2837 \global\SB@tabindent\wd\SB@boxii% 2838 \global\advance\SB@tabindent.5\SB@fretwidth% 2839 \global\advance\SB@tabindent-.5\p@% 2840 \fi% 2841 \SB@dimen\wd\SB@boxii% 2842 \advance\SB@dimen\wd\SB@boxiii% 2843 \ifdim\hsize<\SB@dimen% 2844 \hsize\SB@dimen% 2845 \else\ifSB@gettabind% 2846 \SB@dimenii\hsize% 2847 \advance\SB@dimenii-\SB@dimen% 2848 \divide\SB@dimenii\tw@% 2849 \global\advance\SB@tabindent\SB@dimenii% 2850 \fi\fi% 2851 \hbox to\hsize{\hfil\unhbox\SB@box\hfil}% 2852 \kern-\p@\nointerlineskip% 2853 \hbox to\hsize{% 2854 \hfil% 2819 2820 139 \vtop{\kern\p@\kern2\p@\box\SB@boxii}% \vtop{% \SB@dimen\wd\SB@boxiii% \box\SB@boxiii% \SB@cnt\minfrets% \SB@gtset\relax\SB@gtmax\SB@targstr% \SB@gtinit% \loop% \SB@fretbar\hbox{\SB@targstr}% \advance\SB@cnt\m@ne% \ifnum\SB@cnt>\z@\SB@gtinc\repeat% \SB@fretbar% \ifx\SB@targsfing\@empty\else% \kern1.5\p@% \SB@gtset\SB@topempty\SB@finger% \hbox{\SB@targfing}% \fi% }% \hfil% }% \kern3\p@% 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 }% \SB@gettabindfalse% 2876 2877 2878 \SB@tabargs \SB@ctoken } Break the second argument to a \gtab macro into three sub-arguments. The possible forms are: (a) hstringsi, (b) hfreti:hstringsi, (c) hstringsi:hfingeringi, or (d) hfreti:hstringsi:hfingeringi. To distinguish forms (b) and (c), we count the number of tokens before the first colon. If there is only one token, we assume it must be form (b), since frets larger than 9 and 1-stringed instruments are both rare. Otherwise we assume form (c). \newcommand\SB@ctoken{} \def\SB@ctoken{:} \newcommand\SB@tabargs{} 2881 \def\SB@tabargs#1:#2:#3:#4\SB@tabargs{% 2882 \def\SB@temp{#4}% 2883 \ifx\SB@temp\@empty% 2884 \SB@csify\SB@targstr{#1}% 2885 \else\ifx\SB@temp\SB@ctoken% 2886 \SB@csify\SB@targstr{#1}% 2887 \ifnum\SB@cnt>\@ne% 2888 \SB@cntii\SB@cnt% 2889 \SB@csify\SB@targfing{#2}% 2890 \SB@cnt\SB@cntii% 2891 \else% 2892 \def\SB@targfret{#1}% 2893 \SB@csify\SB@targstr{#2}% 2894 \fi% 2895 \else% 2896 \def\SB@targfret{#1}% 2879 2880 140 \SB@csify\SB@targfing{#3}% \SB@csify\SB@targstr{#2}% \fi\fi% 2897 2898 2899 2900 } 16.14 Book Sectioning The following macros divide the song book into distinct sections, each with different headers, different song numbering styles, different indexes, etc. \songchapter Format the chapter header for a chapter in a song book. By default, chapter headers on a song book omit the chapter number, but do include an entry in the pdf index or table of contents. Thus, the chapter has a number; it’s just not displayed at the start of the chapter. \newcommand\songchapter{% \let\SB@temp\@seccntformat% 2903 \def\@seccntformat##1{}% 2904 \@startsection{chapter}{0}{\z@}% 2905 {3.5ex\@plus1ex\@minus.2ex}% 2906 {.4ex\let\@seccntformat\SB@temp}% 2907 {\sffamily\bfseries\LARGE\centering}% 2908 } 2901 2902 \songsection Format the section header for a section in a song book. This is the same as for chapter headers except at the section level. \newcommand\songsection{% \let\SB@temp\@seccntformat% 2911 \def\@seccntformat##1{}% 2912 \@startsection{section}{1}{\z@}% 2913 {3.5ex\@plus1ex\@minus.2ex}% 2914 {.4ex\let\@seccntformat\SB@temp}% 2915 {\sffamily\bfseries\LARGE\centering}% 2916 } 2909 2910 songs Begin and end a book section. The argument is a list of indexes with which to associate songs in this section. \newenvironment{songs}[1]{% \ifSB@songsenv\SB@errnse\fi% 2919 \gdef\SB@indexlist{#1}% 2920 \SB@chkidxlst% 2921 \stepcounter{SB@songsnum}% 2922 \setcounter{songnum}{1}% 2923 \let\SB@sgroup\@empty% 2924 \ifinner\else\ifdim\pagetotal>\z@% 2925 \null\nointerlineskip% 2926 \fi\fi% 2927 \songcolumns\SB@numcols% 2928 \SB@songsenvtrue% 2929 }{% 2917 2918 141 \commitsongs% \global\let\SB@indexlist\@empty% \ifinner\else\clearpage\fi% \SB@songsenvfalse% 2930 2931 2932 2933 2934 } Each songs section needs a unique number to aid in hyperlinking. 2935 \newcounter{SB@songsnum} 16.15 Index Generation The following macros generate the various types of indexes. At present there are four types: 1. A “large” index has a separate section for each capital letter and is printed in two columns. 2. A “small” index has only a single column, centered, and has no sections. 3. A “scripture” index has three columns and each entry has a commaseparated list of references. 4. An “author” index is like a large index except in bold and without the sectioning. “Large” and “small” indexes will be chosen automatically based on the number of index entries when building a song index. The other two types are designated by the user. As is typical of LATEX indexes, generation of song book indexes requires two passes of document compilation. During the first pass, data files are generated with song titles, authors, and scripture references. An external program is then used to produce LATEX source files from those data files. During the second pass of document compilation, those source files are imported to typeset all the indexes and display them in the document. Internally, this package code uses a four step process to move the index data from the source .tex file to the .sxd data files. 1. While the current song box is in the midst of construction, the data is stored in a box of non-immediate write whatsit nodes. 2. The whatsits are migrated out to the top of the song box when it is finalized at \endsong. 3. When the song box is shipped out to the output file, TEX expands the whatsits, causing the data to be written to the .sxc auxiliary file. 4. At the \end{document} line, the .sxc is processed multiple times—once for each index—to split the data into the respective .sxd files. 142 The first and second steps allow index references to point to the beginning of the song no matter where the indexing commands appear within the song. The third step allows TEX to drop index entries that refer to songs that do not actually appear in the output (e.g., because of \includeonlysongs). It also allows index entries to refer to information that is only decided at shipout time, such as page numbers. The fourth step allows all indexing to be accomplished with at most one write register. LATEX provides extremely few write registers, so using as few as possible is essential for supporting books with many indexes. \songtarget This macro is invoked by each song environment with two arguments: (1) a suggested pdf bookmark index level, and (2) a target name to which hyperlinks for this song in the index will refer. The macro is expected to produce a suitable pdf bookmark entry and/or link target. The default definition tries to use \pdfbookmark if generating a PDF, and resorts to \hypertarget (if it exists) otherwise. The user can redefine the macro to customize how and whether bookmarks and/or links are created. \newcommand\songtarget[2]{% \ifnum\@ne=0\ifSB@pdf\ifx\pdfbookmark\undefined\else% 2938 \ifx\pdfbookmark\relax\else1\fi\fi\fi\relax% 2939 \pdfbookmark[#1]{\thesongnum. \songtitle}{#2}% 2940 \else\ifx\hypertarget\undefined% 2941 \else\ifx\hypertarget\relax\else% 2942 \hypertarget{#2}{\relax}% 2943 \fi\fi\fi% 2944 } 2936 2937 \songlink This macro is invoked by the index code to produce a link to a song target created by \songtarget. Its two arguments are: (1) the target name (same as the second argument to \songtarget, and (2) the text that is to be linked. The default implementation uses \hyperlink if it exists; otherwise it just leaves the text unlinked. \newcommand\songlink{% \ifnum\@ne=0\ifx\hyperlink\undefined\else% 2947 \ifx\hyperlink\relax\else1\fi\fi\relax% 2948 \expandafter\hyperlink% 2949 \else% 2950 \expandafter\@gobble% 2951 \fi% 2952 } 2945 2946 \SB@indexlist This macro records the comma-separated list of the identifiers of indexes associated with the current book section. 2953 \SB@allindexes \newcommand\SB@indexlist{} This macro records a comma-separated list of all the index identifiers for the entire document. 2954 2955 \newcommand\SB@allindexes{} \let\SB@allindexes\@empty 143 \SB@out The \SB@out control sequence is reserved for the write register allocated by the package code, if one is needed. (It is allocated at the first index declaration.) 2956 2957 \SB@newindex \newcommand\SB@out{} \let\SB@out\relax Initialize a new title, author, or scripture index. \newcommand\SB@newindex[4]{% \expandafter\newcommand\csname SB@idxfilename@#3\endcsname{#4}% 2960 \expandafter\newcommand\csname SB@idxsel@#3\endcsname[3]{###1}% 2961 \expandafter\newcommand\csname SB@idxref@#3\endcsname{\thesongnum}% 2962 \xdef\SB@allindexes{% 2963 \ifx\SB@allindexes\@empty\else\SB@allindexes,\fi#3% 2964 }% 2965 \if@filesw% 2966 \ifx\SB@out\relax% 2967 \SB@newwrite\SB@out% 2968 \immediate\openout\SB@out=\jobname.sxc\relax% 2969 \fi% 2970 \immediate\write\SB@out{\noexpand\SB@iwrite{#3}{#2}}% 2971 \fi% 2972 } 2958 2959 \newindex Define a new title index. The first argument is an identifier for the index (used in constructing index-specific control sequence names). The second argument is a filename root; auxiliary file harg2 i.sxd is where the index data is stored at the end of processing. 2973 2974 \newscripindex Define a new scripture index. This is exactly like \newindex except that scripture references are added to the auxiliary file instead of titles. 2975 2976 \newauthorindex \newcommand\newscripindex{\SB@newindex2{SCRIPTURE INDEX DATA FILE}} \@onlypreamble\newscripindex Define a new author index. This is exactly like \newindex except that author info is added to the auxiliary file instead of titles. 2977 2978 \SB@cwrite \newcommand\newindex{\SB@newindex1{TITLE INDEX DATA FILE}} \@onlypreamble\newindex \newcommand\newauthorindex{\SB@newindex3{AUTHOR INDEX DATA FILE}} \@onlypreamble\newauthorindex Write index data to a Song indeX Combined (.sxc) auxiliary file. The first argument is the identifier for the index to which the data ultimately belongs. The second argument is the data itself. The write is non-immediate so that it is only output if its enclosing song is ultimately shipped to the output file. \newcommand\SB@cwrite[2]{% \ifx\SB@out\relax\else% 2981 \protected@write\SB@out\SB@keepactive{\protect\SB@iwrite{#1}{#2}}% 2982 \fi% 2983 } 2979 2980 144 \SB@keepactive By default, the inputenc package expands Unicode characters into macro names when writing them to files. This behavior must be inhibited when writing to the .sxc file, since songidx needs the original Unicode characters for sorting. To achieve this, we temporarily redefine most active characters so that they expand to an unexpandable string version of themselves. \newcommand\SB@keepactive{} {\catcode‘\~\active 2986 \catcode‘\.12 2987 \def\\#1#2{% 2988 \endgroup 2989 \expandafter\gdef\expandafter\SB@keepactive 2990 \expandafter{\SB@keepactive\def#1{#2}}% 2991 } 2992 \def\SB@temp#1#2{% 2993 \SB@cnt#1\relax 2994 \loop 2995 \begingroup 2996 \uccode‘\~\SB@cnt 2997 \uccode‘\.\SB@cnt 2998 \uppercase{\\~.} 2999 \ifnum\SB@cnt<#2\relax 3000 \advance\SB@cnt\@ne 3001 \repeat 3002 } 3003 \SB@temp{1}{8} 3004 \SB@temp{11}{11} 3005 \SB@temp{14}{91} 3006 \SB@temp{93}{255} 3007 } 2984 2985 \SB@iwrite The line contributed by \SB@cwrite to the .sxc file is an \SB@iwrite macro that re-outputs the data to an appropriate .sxd file. \newcommand\SB@iwrite[2]{% \def\SB@tempii{#1}% 3010 \ifx\SB@temp\SB@tempii% 3011 \SB@toks{#2}% 3012 \immediate\write\SB@out{\the\SB@toks}% 3013 \fi% 3014 } 3008 3009 \SB@uncombine At the end of the document, the .sxc file can be processed multiple times to produce all the .sxd files without resorting to multiple write registers. Each pass activates the subset of the \SB@iwrite commands that apply to one index. \newcommand\SB@uncombine{% \ifx\SB@out\relax\else% 3017 \immediate\closeout\SB@out% 3018 \ifsongindexes% 3019 \@for\SB@temp:=\SB@allindexes\do{% 3020 \immediate\openout\SB@out=% 3015 3016 145 3021 3022 3023 3024 3025 3026 3027 3028 3029 \SB@songwrites }% \fi% \fi% } \AtEndDocument{\SB@uncombine} The following box register stores index data until it can be migrated to the top of the song box currently under construction. 3030 \SB@addtoindex \csname SB@idxfilename@\SB@temp\endcsname.sxd\relax% \begingroup\makeatletter\catcode‘\%12\relax% \input{\jobname.sxc}\endgroup% \immediate\closeout\SB@out% \SB@newbox\SB@songwrites Queue data harg2 i associated with the current song for eventual writing to the index whose identifier is given by harg1 i. \newcommand\SB@addtoindex[2]{% \protected@edef\SB@tempii{#2}% 3033 \ifx\SB@tempii\@empty\else% 3034 \global\setbox\SB@songwrites\vbox{% 3035 \unvbox\SB@songwrites% 3036 \SB@cwrite{#1}{#2}% 3037 \SB@cwrite{#1}{\csname SB@idxref@#1\endcsname}% 3038 \SB@cwrite{#1}{song\theSB@songsnum-\thesongnum.% 3039 \ifnum\c@section=\z@1\else2\fi}% 3040 }% 3041 \fi% 3042 } 3031 3032 \SB@addtoindexes Add harg1 i to all title indexes, harg2 i to all scripture indexes, and harg3 i to all author indexes. \newcommand\SB@addtoindexes[3]{% \@for\SB@temp:=\SB@indexlist\do{% 3045 \SB@addtoindex\SB@temp% 3046 {\csname SB@idxsel@\SB@temp\endcsname{#1}{#2}{#3}}% 3047 }% 3048 } 3043 3044 \SB@addtotitles Add harg1 i to all title indexes, but leave other indexes unaffected. \newcommand\SB@addtotitles[1]{% \@for\SB@temp:=\SB@indexlist\do{% 3051 \csname SB@idxsel@\SB@temp\endcsname% 3052 {\SB@addtoindex\SB@temp{#1}}{}{}% 3053 }% 3054 } 3049 3050 146 \SB@chkidxlst Check the current list of indexes and flag an error if any are undefined. \newcommand\SB@chkidxlst{% \let\SB@temp\SB@indexlist% 3057 \let\SB@indexlist\@empty% 3058 \@for\SB@tempii:=\SB@temp\do{% 3059 \@ifundefined{SB@idxsel@\SB@tempii}{\SB@errnoidx\SB@tempii}{% 3060 \ifx\SB@indexlist\@empty% 3061 \SB@toks\expandafter{\SB@tempii}% 3062 \else% 3063 \SB@toks\expandafter\expandafter\expandafter{% 3064 \expandafter\SB@indexlist\expandafter,\SB@tempii}% 3065 \fi% 3066 \edef\SB@indexlist{\the\SB@toks}% 3067 }% 3068 }% 3069 } 3055 3056 \indexentry \SB@idxentry \SB@@idxentry \SB@addtoindexes will be called automatically for each song in a section. However, \indexentry may be called by the user in order to add an alternative index entry for the given song. Usually this is done to index the song by its first line or some other memorable line in a chorus or verse somewhere. \newcommand\indexentry{\@ifnextchar[{\SB@idxentry*}{\SB@@idxentry*}} \newcommand\SB@idxentry{} 3072 \def\SB@idxentry#1[#2]#3{{% 3073 \def\SB@indexlist{#2}% 3074 \SB@chkidxlst% 3075 \SB@addtoindexes{#1#3}{#3}{#3}% 3076 }} 3077 \newcommand\SB@@idxentry[2]{\SB@addtotitles{#1#2}} 3070 3071 \indextitleentry \indextitleentry may be used to add an alternate title for the song to the index. (The only difference between the effects of \indexentry and \indextitleentry is that the latter are italicized in the rendered index and the former are not.) \newcommand\indextitleentry{% \@ifnextchar[{\SB@idxentry{}}{\SB@@idxentry{}}% 3080 } 3078 3079 \indexsongsas The following macro allows the user to change how songs are indexed on the right side of index entries. By default, the song’s number is listed. \newcommand\indexsongsas[1]{% \@ifundefined{SB@idxref@#1}% 3083 {\SB@errnoidx{#1}\@gobble}% 3084 {\expandafter\renewcommand\csname SB@idxref@#1\endcsname}% 3085 } 3081 3082 147 \SB@idxcmd The songidx index-generation program understands several different directives \SB@@idxcmd that each dictate various aspects of how index entries are parsed, sorted, and \authsepword displayed. Such directives should typically appear at the start of the .sxd file just \authbyword after the header line that identifies the type of index. \authignoreword 3086 \newcommand\SB@idxcmd[3]{% \titleprefixword 3087 \ifx\SB@out\relax\else% 3088 \@for\SB@temp:=\SB@allindexes\do{% 3089 \csname SB@idxsel@\SB@temp\endcsname% 3090 {\SB@@idxcmd{#1}}{\SB@@idxcmd{#2}}{\SB@@idxcmd{#3}}% 3091 }% 3092 \fi% 3093 } 3094 \newcommand\SB@@idxcmd[1]{% 3095 \def\SB@tempii{#1}% 3096 \ifx\SB@tempii\@empty\else% 3097 \immediate\write\SB@out{% 3098 \noexpand\SB@iwrite{\SB@temp}{#1}% 3099 }% 3100 \fi% 3101 } 3102 \newcommand\authsepword[1]{} 3103 \newcommand\authbyword[1]{} 3104 \newcommand\authignoreword[1]{} 3105 \newcommand\titleprefixword[1]{} 3106 {\catcode‘\%=12 3107 \gdef\authsepword#1{\SB@idxcmd{}{}{%sep #1}} 3108 \gdef\authbyword#1{\SB@idxcmd{}{}{%after #1}} 3109 \gdef\authignoreword#1{\SB@idxcmd{}{}{%ignore #1}} 3110 \gdef\titleprefixword#1{\SB@idxcmd{%prefix #1}{}{}}} 3111 \@onlypreamble\authsepword 3112 \@onlypreamble\authbyword 3113 \@onlypreamble\authignoreword 3114 \@onlypreamble\titleprefixword \SB@idxlineskip Set the spacing between lines in an index. \newcommand\SB@idxlineskip[1]{% \vskip#1\p@\@plus#1\p@\@minus#1\p@% 3117 } 3115 3116 When rendering an index entry X . . . Y that is too long to fit on one physical line, we must break text X and/or Y up into multiple lines. Text X should be typeset as a left-justified paragraph with a right margin of about 2em; however, it’s final line must not be so long that it cannot fit even the first item of list Y . Text Y should be typeset as a right-justified paragraph whose first line begins on the last line of X. However, breaking Y up the way paragraphs are normally broken up doesn’t work well because that causes most of Y to be crammed into the first few lines, leaving the last line very short. This looks strange and is hard to read. It looks much better to instead break Y up in such a way that the portion of Y that is placed on each line is of approximately equal width (subject to the 148 constraint that we don’t want to introduce any more lines than are necessary). This makes it visually clear that all of these lines are associated with X. The following code performs the width computations that do this horizontal-balancing of text. \SB@ellipspread Typeset an index entry of the form X . . . Y . In the common case, the entire entry fits on one line so we just typeset it in the usual way. If it doesn’t fit on one line, we call \SB@balancerows for a more sophisticated treatment. \newcommand\SB@ellipspread[2]{% \begingroup% 3120 \SB@dimen\z@% 3121 \def\SB@temp{#1}% 3122 \SB@toks{#2}% 3123 \setbox\SB@box\hbox{{% 3124 \SB@temp% 3125 \leaders\hbox to.5em{\hss.\hss}\hskip2em\@plus1fil% 3126 {\the\SB@toks}% 3127 }}% 3128 \ifdim\wd\SB@box>\hsize% 3129 \SB@balancerows% 3130 \else% 3131 \hbox to\hsize{\unhbox\SB@box}\par% 3132 \fi% 3133 \endgroup% 3134 } 3118 3119 \SB@balancerows Typeset an index entry of the form X . . . Y that doesn’t fit on one line, where X is the content of macro \SB@temp and Y is the content of token register \SB@toks. First, we must pre-compute the width w1 of the final line of X when X is typeset as a left-justified paragraph, storing it in \SB@dimenii. This is necessary because in order to force TEX to typeset the first line of Y at some chosen width w2 , we must insert leaders of width c − w1 − w2 into the paragraph between X and Y , where c is the column width. Computing this width w1 is a bit tricky. We must tell TEX that the last line of X must not be so long that it does not even have room for the first item of Y . Thus, we must strip off the first item of Y and add it (or a non-breaking space of equivalent width) to the end of X to typeset the paragraph. Then we use \lastbox to pull off the final line and check its width. \newcommand\SB@balancerows{% \edef\SB@tempii{\the\SB@toks}% 3137 \setbox\SB@box\vbox{% 3138 \SB@toks\expandafter{\expandafter\\\the\SB@toks\\}% 3139 \SB@lop\SB@toks\SB@toks% 3140 \settowidth\SB@dimen{\the\SB@toks}% 3141 \advance\SB@dimen-.5em% 3142 \leftskip.5cm% 3143 {\hbadness\@M\hfuzz\maxdimen% 3144 \hskip-.5cm\relax\SB@temp\unskip\nobreak% 3135 3136 149 \hskip\SB@dimen\nobreak% \rightskip2em\@plus1fil\par}% \setbox\SB@box\lastbox% \setbox\SB@box\hbox{% \unhbox\SB@box% \unskip\unskip\unpenalty% \unpenalty\unskip\unpenalty% }% \expandafter% 3145 3146 3147 3148 3149 3150 3151 3152 3153 }% \expandafter\SB@dimenii\the\wd\SB@box\relax% 3154 3155 Next, compute the smallest width w2 such that the index entry text produced by \SB@multiline with \SB@dimen=w2 has no more lines than with \SB@dimen set to the maximum available width for the right-hand side. This effectively horizontalbalances the right-hand side of the index entry text, making all lines of Y roughly equal in width without introducing any extra lines. \SB@dimen\hsize% \advance\SB@dimen-.5cm% \setbox\SB@box\vbox{% \SB@multiline{\hbadness\@M\hfuzz\maxdimen}% }% \SB@dimeniii.5\SB@dimen% \SB@dimeniv\SB@dimeniii% \loop% \SB@dimeniv.5\SB@dimeniv% \setbox\SB@boxii\vbox{% \SB@dimen\SB@dimeniii% \SB@multiline{\hbadness\@M\hfuzz\maxdimen}% }% \ifnum\SB@cnt<\@M% \ifdim\ht\SB@boxii>\ht\SB@box% \advance\SB@dimeniii\SB@dimeniv% \else% \SB@dimen\SB@dimeniii% \advance\SB@dimeniii-\SB@dimeniv% \fi% \else% \advance\SB@dimeniii\SB@dimeniv% \fi% \ifdim\SB@dimeniv>2\p@\repeat% \setbox\SB@box\box\voidb@x% \setbox\SB@boxii\box\voidb@x% 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 Finally, typeset the results based on the quantities computed above. \SB@multiline\relax% 3182 3183 \SB@multiline } Create a paragraph containing text X . . . Y where X is the content of \SB@temp, Y is the content of \SB@tempii, and Y is restricted to width \SB@dimen (but 150 may span multiple lines of that width). Dimen register \SB@dimenii must be set with the expected width of the final line of X. The first argument contains any parameter definitions that should be in effect when X is processed. Note that the expansion of \SB@tempii, which may contain \SB@idxitemsep, depends on \SB@dimen. Therefore, the redefinition of \SB@dimen at the start of this macro must not be removed! \newcommand\SB@multiline[1]{% \begingroup% 3186 \SB@dimen-\SB@dimen% 3187 \advance\SB@dimen\hsize% 3188 \SB@dimenii-\SB@dimenii% 3189 \advance\SB@dimenii\SB@dimen% 3190 {#1\hskip-.5cm\relax\SB@temp\unskip\nobreak% 3191 \SB@maxmin\SB@dimenii<{1.5em}% 3192 \leftskip.5cm\rightskip2em\@plus1fil% 3193 \interlinepenalty\@M% 3194 \leaders\hbox to.5em{\hss.\hss}\hskip\SB@dimenii\@plus1fill% 3195 \nobreak{\SB@tempii\kern-2em}% 3196 \par\global\SB@cnt\badness}% 3197 \endgroup% 3198 }% 3184 3185 \SB@idxitemsep If text Y in index entry X . . . Y has multiple items in a list, those items should be separated by \\ macros instead of by commas. The \\ macro will be assigned the definition of \SB@idxitemsep during index generation, which produces the comma along with the complex spacing required if Y ends up being broken into multiple lines. In particular, it forces each wrapped line of Y to be right-justified with left margin at least \SB@dimen. \newcommand\SB@idxitemsep{% ,\kern-2em\penalty-8\hskip2.33em\@minus.11em% 3201 \hskip-\SB@dimen\@plus-1fill% 3202 \vadjust{}\nobreak% 3203 \hskip\SB@dimen\@plus1fill\relax% 3204 } 3199 3200 The following set of macros and environments are intended for use in the .sbx files that are automatically generated by an index-generating program; they shouldn’t normally appear in the user’s .tex or .sbd files directly. However, they are named as exported macros (no @ symbols) since they are used outside the package code and are therefore not stricly internal. idxblock Some indexes are divided into blocks (e.g., one for each letter of the alphabet or one for each book of the bible). Each such block should be enclosed between \begin{idxblock}{X} and \end{idxblock} lines, where X is the title of the block. The actual definition of the idxblock environment is set within the initialization code for each type of index (below). 3205 \newenvironment{idxblock}[1]{}{} 151 \idxentry \idxaltentry Within each idxblock environment there should be a series of \idxentry and/or \idxaltentry macros, one for each line of the index. Again, the exact definitions of these macros will vary between index types. 3206 3207 SB@lgidx SB@smidx Some indexes actually have two definitions for each idxblock environment—one for use when there are few enough entries to permit a small style index, and another for use in a large style index. These macros will be redefined appropriately within the initialization code for each type of index. 3208 3209 \SB@idxsetup \newcommand\idxentry[2]{} \newcommand\idxaltentry[2]{} \newenvironment{SB@lgidx}[1]{}{} \newenvironment{SB@smidx}[1]{}{} Set various parameters for a column of an index environment. \newcommand\SB@idxsetup{% \hsize\SB@colwidth% 3212 \parskip\z@skip\parfillskip\z@skip\parindent\z@% 3213 \baselineskip\f@size\p@\@plus\p@\@minus\p@% 3214 \lineskiplimit\z@\lineskip\p@\@plus\p@\@minus\p@% 3215 \hyphenpenalty\@M\exhyphenpenalty\@M% 3216 } 3210 3211 \SB@makeidxcolumn Break off enough material from \SB@box to create one column of the index. \newcommand\SB@makeidxcolumn{% \ifdim\ht\SB@box=\z@% 3219 \hskip\hsize\relax% 3220 \else% 3221 \splittopskip\z@skip\splitmaxdepth\maxdepth% 3222 \vsplit\SB@box to\SB@dimen% 3223 \global\setbox\SB@box\vbox{% 3224 \SB@idxsetup% 3225 \splitbotmark% 3226 \unvbox\SB@box% 3227 }% 3228 \fi% 3229 } 3217 3218 \SB@oneidxpage Construct one full page of the index. The definition of \SB@oneidxpage is generated dynamically based on the type of index and number of columns. 3230 \SB@displayindex \newcommand\SB@oneidxpage{} Create an index with title harg2 i and with harg1 i columns (must be a literal constant). Input the index contents from external file harg3 i, which is expected to be a TEX file. \newcommand\SB@displayindex[3]{% \ifsongindexes\begingroup% 3233 \SB@colwidth\hsize% 3234 \advance\SB@colwidth-#1\columnsep% 3231 3232 152 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 \advance\SB@colwidth\columnsep% \divide\SB@colwidth#1% \setbox\SB@envbox\vbox{% \let\SB@temp\songsection% \ifx\chapter\undefined\else% \ifx\chapter\relax\else% \let\SB@temp\songchapter% \fi% \fi% \SB@temp{#2}% }% The .sbx index file might not exist (e.g., if this is the first pass through the TEX compiler). If it exists, first try typesetting its content as a small index (one column, centered, with no divisions). 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 \IfFileExists{\csname SB@idxfilename@#3\endcsname.sbx}{% \ifsepindexes% \global\setbox\SB@box\vbox{% \null% \vfil% \unvcopy\SB@envbox% \vskip.5in\@minus.3in\relax% \hbox to\hsize{% \hfil% \vbox{% \SB@idxsetup% \renewenvironment{idxblock}[1]% {\begin{SB@smidx}{####1}}{\end{SB@smidx}}% \let\\\SB@idxitemsep% \input{\csname SB@idxfilename@#3\endcsname.sbx}% }% \hfil% }% \vskip\z@\@plus2fil\relax% }% Test whether the resulting small index fits within one page. If not, re-typeset it as a large index. 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 {\vbadness\@M\vfuzz\maxdimen% \splitmaxdepth\maxdepth\splittopskip\z@skip% \global\setbox\SB@boxii\vsplit\SB@box to\textheight}% \ifvoid\SB@box% \box\SB@boxii% \else% \SB@lgindex{#1}{#3}% \fi% \else% \SB@lgindex{#1}{#3}% \fi% }% 153 If the .sbx file doesn’t exist, then instead typeset a page with a message on it indicating that the document must be compiled a second time in order to generate the index. {% \ifsepindexes% \vbox to\textheight{% \vfil% \unvbox\SB@envbox% \vskip1em\relax% \hbox to\hsize{\hfil[Index not yet generated.]\hfil}% \vskip\z@\@plus2fil\relax% }% \else% \unvbox\SB@envbox% \hbox to\hsize{\hfil[Index not yet generated.]\hfil}% \fi% }% \ifsepindexes\clearpage\fi% \endgroup\fi% 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 \SB@lgindex } Typeset a large-style index. We begin by typesetting the entire index into a box. \newcommand\SB@lgindex[2]{% \global\setbox\SB@box\vbox{% 3297 \renewenvironment{idxblock}[1]% 3298 {\begin{SB@lgidx}{##1}}{\end{SB@lgidx}}% 3299 \let\\\SB@idxitemsep% 3300 \SB@idxsetup% 3301 \input{\csname SB@idxfilename@#2\endcsname.sbx}% 3302 \unskip% 3303 }% 3295 3296 Next, we split the box into columns and pages until the last page is reached. 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 \SB@toks{\SB@makeidxcolumn}% \SB@cnt#1\relax% \loop\ifnum\SB@cnt>\@ne% \SB@toks\expandafter{\the\SB@toks% \kern\columnsep\SB@makeidxcolumn}% \advance\SB@cnt\m@ne% \repeat% \edef\SB@oneidxpage{\the\SB@toks}% \unvbox\SB@envbox% \vskip.2in\relax% \nointerlineskip% \null% \nointerlineskip% \SB@cnt\vbadness\vbadness\@M% \SB@dimenii\vfuzz\vfuzz\maxdimen% \loop% \SB@dimen\textheight% 154 \ifinner\else\kern\z@\advance\SB@dimen-\pagetotal\fi% \global\setbox\SB@boxii\copy\SB@box% \global\setbox\SB@boxiii\hbox{\SB@oneidxpage}% \ifdim\ht\SB@box>\z@% \box\SB@boxiii% \vfil\break% \repeat% 3321 3322 3323 3324 3325 3326 3327 The final page of the index should have all equal-height columns instead of a few full columns followed by some short or empty columns at the end. To achieve this, we re-typeset the final page, trying different column heights until we find one that causes the material to span an equal percentage of all the columns on the page. \SB@dimenii\ht\SB@boxii% \divide\SB@dimenii#1\relax% \SB@maxmin\SB@dimen>\SB@dimenii% \loop% \global\setbox\SB@box\copy\SB@boxii% \global\setbox\SB@boxiii\hbox{\SB@oneidxpage}% \ifdim\ht\SB@box>\z@% \advance\SB@dimen\p@% \repeat% \box\SB@boxiii% \global\setbox\SB@boxii\box\voidb@x% \vbadness\SB@cnt\vfuzz\SB@dimenii% 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 \showindex } Create an index with title harg2 i based on the data associated with index identifier harg3 i (which was passed to \newindex). Optional argument harg1 i specifies the number of columns. This macro calls the appropriate index-creation macro depending on the type of index that harg3 i was declared to be. \newcommand\showindex[3][0]{% \@ifundefined{SB@idxsel@#3}{\SB@errnoidx{#3}}{% 3343 \expandafter\let\expandafter\SB@temp\csname SB@idxsel@#3\endcsname% 3344 \SB@cnt#1\relax% 3345 \ifnum\SB@cnt<\@ne\SB@cnt\SB@temp232\relax\fi% 3346 \expandafter\SB@temp% 3347 \expandafter\SB@maketitleindex% 3348 \expandafter\SB@makescripindex% 3349 \expandafter\SB@makeauthorindex% 3350 \expandafter{\the\SB@cnt}% 3351 {#2}{#3}% 3352 }% 3353 } 3341 3342 \SB@maketitleindex Create a song title index. harg1 i is a column count, harg2 i is the title, and harg3 i is the index identifier (which was passed to \newindex). \newcommand\SB@maketitleindex{% \ifnum\idxheadwidth>\z@% 3356 \renewenvironment{SB@lgidx}[1]{ 3354 3355 155 \hbox{\SB@colorbox\idxbgcolor{\vbox{% \hbox to\idxheadwidth{{\idxheadfont\relax##1}\hfil}% }}}% \nobreak\vskip3\p@\@plus2\p@\@minus2\p@\nointerlineskip% }{\penalty-50\vskip5\p@\@plus5\p@\@minus4\p@}% \else% \renewenvironment{SB@lgidx}[1]{}{}% \fi% \renewenvironment{SB@smidx}[1]{}{}% \renewcommand\idxentry[2]{% \SB@ellipspread{\idxtitlefont\relax\ignorespaces##1\unskip}% {{\idxrefsfont\relax##2}}% }% \renewcommand\idxaltentry[2]{% \SB@ellipspread{\idxlyricfont\relax\ignorespaces##1\unskip}% {{\idxrefsfont\relax##2}}% }% \SB@displayindex% 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 \SB@idxcolhead In a scripture index, this macro remembers the current book of the bible we’re in so that new columns can be headed with “Bookname (continued)”. 3376 \SB@idxheadsep } \newcommand\SB@idxcolhead{} Add vertical space following the header line that begins (or continues) a section of a scripture index. \newcommand\SB@idxheadsep{{% \SB@dimen4\p@% 3379 \advance\SB@dimen-\prevdepth% 3380 \SB@maxmin\SB@dimen<\z@% 3381 \SB@dimenii\SB@dimen% 3382 \SB@maxmin\SB@dimenii>\p@% 3383 \vskip\SB@dimen\@plus\p@\@minus\SB@dimenii% 3384 }} 3377 3378 \SB@idxcont Typeset the “Bookname (continued)” line that continues a scripture index section when it spans a column break. \newcommand\SB@idxcont[1]{% \hbox to\hsize{{\idxcont{#1}}\hfil}% 3387 \nobreak% 3388 \SB@idxheadsep\nointerlineskip% 3389 } 3385 3386 \SB@makescripindex Create a scripture index. harg1 i is a column count, harg1 i is the title, and harg2 i is the index identifier (which was passed to \newscripindex). \newcommand\SB@makescripindex{% \renewenvironment{SB@lgidx}[1]{% 3392 \gdef\SB@idxcolhead{##1}% 3393 \hbox to\hsize{{\idxbook{##1}}\hfil}% 3390 3391 156 \nobreak% \SB@idxheadsep\nointerlineskip% }{% \mark{\noexpand\relax}% \penalty-20\vskip3\p@\@plus3\p@\relax% }% \renewenvironment{SB@smidx}[1] {\begin{SB@lgidx}{##1}}{\end{SB@lgidx}}% \renewcommand\idxentry[2]{% \SB@ellipspread{\hskip.25cm\idxscripfont\relax##1}% {{\idxrefsfont\relax##2}}% \SB@toks\expandafter{\SB@idxcolhead}% \mark{\noexpand\SB@idxcont{\the\SB@toks}}% }% \renewcommand\idxaltentry[2]{\SB@erridx{a scripture}}% \SB@displayindex% 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 \SB@makeauthorindex } Create an author index. harg1 i is a column count, harg2 i is the title, and harg2 i is the index identifier (which was passed to \newauthindex). \newcommand\SB@makeauthorindex{% \renewenvironment{SB@lgidx}[1]{}{}% 3413 \renewenvironment{SB@smidx}[1]{}{}% 3414 \renewcommand\idxentry[2]{% 3415 \SB@ellipspread{{\idxauthfont\relax\sfcode‘.\@m##1}}% 3416 {{\idxrefsfont##2}}% 3417 }% 3418 \renewcommand\idxaltentry[2]{\SB@erridx{an author}}% 3419 \SB@displayindex% 3420 } 3411 3412 16.16 Error Messages We break error messages out into separate macros here in order to reduce the length (in tokens) of the more frequently used macros that do actual work. This can result in a small speed improvement on slower machines. \SB@Error All errors and warnings will be reported as coming from package “songs”. \SB@Warn 3421 \newcommand\SB@Error{\PackageError{songs}} 3422 \newcommand\SB@Warn{\PackageWarning{songs}} \SB@errspos \newcommand\SB@errspos{% \SB@Error{Illegal \protect\songpos\space argument}{The argume% 3425 nt to \protect\songpos\space must be a number from 0 to 3.}% 3426 } 3423 3424 157 \SB@errnse \newcommand\SB@errnse{% \SB@Error{Nested songs environments are not supported}{End th% 3429 e previous songs environment before beginning the next one.}% 3430 } 3427 3428 \SB@errpl \newcommand\SB@errpl{% \SB@Error{\protect\includeonlysongs\space not permitted with% 3433 in a songs environment}{\protect\includeonlysongs\space can o% 3434 nly be used in the document preamble or between songs environ% 3435 ments in the document body.}% 3436 } 3431 3432 \SB@errrtopt \newcommand\SB@errrtopt{% \SB@Error{Cannot display chords in a rawtext dump}{You have u% 3439 sed the rawtext option in the \protect\usepackage\space lin% 3440 e and have either used the chorded option as well or have use% 3441 d the \protect\chordson\space macro subsequently.}% 3442 } 3437 3438 \SB@warnrc \newcommand\SB@warnrc{% \SB@Warn{The \protect\repchoruses\space feature will not wor% 3445 k when the number of columns is set to zero}% 3446 } 3443 3444 \SB@errboo \newcommand\SB@errboo{% \SB@Error{Encountered \protect\beginsong\space without seein% 3449 g an \protect\endsong\space for the previous song}% 3450 {Song \thesongnum\space might be missing a% 3451 n \protect\endsong\space line.}% 3452 } 3447 3448 \SB@errbor \newcommand\SB@errbor{% \SB@Error{Encountered \protect\beginsong\space without seein% 3455 g an \protect\endscripture\space for the preceding scriptur% 3456 e quotation}{A scripture quotation appearing after son% 3457 g \thesongnum\space might be missing a% 3458 n \protect\endscripture\space line.}% 3459 } 3453 3454 158 \SB@erreov \newcommand\SB@erreov{% \SB@Error{Encountered \protect\endsong\space without seein% 3462 g an \protect\endverse\space for the preceding verse}{Son% 3463 g \thesongnum\space has a \protect\beginverse\space% 3464 line with no matching \protect\endverse\space line.}% 3465 } 3460 3461 \SB@erreoc \newcommand\SB@erreoc{% \SB@Error{Encountered \protect\endsong\space without seein% 3468 g an \protect\endchorus\space for the preceding chorus}{Son% 3469 g \thesongnum\space has a \protect\beginchorus\space% 3470 line with no matching \protect\endchorus\space line.}% 3471 } 3466 3467 \SB@erreor \newcommand\SB@erreor{% \SB@Error{Encountered \protect\endsong\space without seein% 3474 g an \protect\endscripture for the preceding scripture quot% 3475 e}{A scripture quote appearing before song \thesongnum\space% 3476 ended with \protect\endsong\space instead of wit% 3477 h \protect\endscripture.}% 3478 } 3472 3473 \SB@erreot \newcommand\SB@erreot{% \SB@Error{Encountered \protect\endsong\space with no matchin% 3481 g \protect\beginsong}{Before song \thesongnum\space there wa% 3482 s an \protect\endsong\space with no matchin% 3483 g \protect\beginsong.}% 3484 } 3479 3480 \SB@errbvv \newcommand\SB@errbvv{% \SB@Error{Encountered \protect\beginverse\space without seein% 3487 g an \protect\endverse\space for the preceding verse}{Son% 3488 g \thesongnum\space might have a verse that has n% 3489 o \protect\endendverse\space line.}% 3490 } 3485 3486 \SB@errbvc \newcommand\SB@errbvc{% \SB@Error{Encountered \protect\beginverse\space without seein% 3493 g an \protect\endchorus\space for the preceding chorus}{Son% 3494 g \thesongnum\space might have a chorus that has n% 3495 o \protect\endchorus\space line.}% 3496 } 3491 3492 159 \SB@errbvt \newcommand\SB@errbvt{% \SB@Error{Encountered \protect\beginverse\space without firs% 3499 t seeing a \protect\beginsong\space line}{Before son% 3500 g \thesongnum, there is a \protect\beginverse\space line no% 3501 t contained in any song.}% 3502 } 3497 3498 \SB@errevc \newcommand\SB@errevc{% \SB@Error{Encountered \protect\endverse\space while process% 3505 ing a chorus}{Song \thesongnum\space might hav% 3506 e a \protect\beginchorus\space concluded by a% 3507 n \protect\endverse\space instead of an \protect\endchorus.}% 3508 } 3503 3504 \SB@errevo \newcommand\SB@errevo{% \SB@Error{Encountered \protect\endverse\space without firs% 3511 t seeing a \protect\beginverse}{Song \thesongnum\space m% 3512 ight have an \protect\endverse\space with no matchin% 3513 g \protect\beginverse.}% 3514 } 3509 3510 \SB@errevt \newcommand\SB@errevt{% \SB@Error{Encountered an \protect\endverse\space outside o% 3517 f any song}{Before song \thesongnum, there is a% 3518 n \protect\endverse\space line not preceded b% 3519 y a \protect\beginsong\space line.}% 3520 } 3515 3516 \SB@erretex \newcommand\SB@erretex{% \SB@Error{The \protect\repchoruses\space feature requires e-% 3523 TeX compatibility}{Your version of LaTeX2e does not appear t% 3524 o be e-TeX compatible. Find a distribution that includes e-T% 3525 eX support in order to use this feature.}% 3526 } 3521 3522 \SB@errbcv \newcommand\SB@errbcv{% \SB@Error{Encountered \protect\beginchorus\space without see% 3529 ing an \protect\endverse\space for the preceding verse}{Son% 3530 g \thesongnum\space might hav% 3531 e a \protect\beginverse\space with no match% 3532 ing \protect\endverse.}% 3533 } 3527 3528 160 \SB@errbcc \newcommand\SB@errbcc{% \SB@Error{Encountered \protect\beginchorus\space without see% 3536 ing an \protect\endchorus\space for the preceding chorus}% 3537 {Song \thesongnum\space might have a \protect\beginchorus% 3538 \space with no matching \protect\endchorus.}% 3539 } 3534 3535 \SB@errbct \newcommand\SB@errbct{% \SB@Error{Encountered \protect\beginchorus\space without see% 3542 ing a \protect\beginsong\space line first}{After son% 3543 g \thesongnum\space there is a \protect\beginchorus\space% 3544 line outside of any song.}% 3545 } 3540 3541 \SB@errecv \newcommand\SB@errecv{% \SB@Error{Encountered an \protect\endchorus\space while proc% 3548 essing a verse}{Song \thesongnum\space might hav% 3549 e a \protect\beginverse\space concluded by \protect\endchorus% 3550 \space instead of \protect\endverse.}% 3551 } 3546 3547 \SB@erreco \newcommand\SB@erreco{% \SB@Error{Encountered \protect\endchorus\space without firs% 3554 t seeing a \protect\beginchorus}{Song \thesongnum\space m% 3555 ight have an \protect\endchorus\space with no match% 3556 ing \protect\beginchorus.}% 3557 } 3552 3553 \SB@errect \newcommand\SB@errect{% \SB@Error{Encountered an \protect\endchorus\space outside o% 3560 f any song}{Before song \thesongnum, there is a% 3561 n \protect\endchorus\space line not preceded b% 3562 y a \protect\beginsong\space line.}% 3563 } 3558 3559 \SB@errbro \newcommand\SB@errbro{% \SB@Error{Missing \protect\endsong}% 3566 {Nested song and intersong environments are not supported% 3567 . Song \thesongnum\space might be missing a% 3568 n \protect\endsong\space line.}% 3569 } 3564 3565 161 \SB@errbrr \newcommand\SB@errbrr{% \SB@Error{Nested intersong environments are not supported}% 3572 {A scripture quote or other intersong environment before s% 3573 ong \thesongnum\space is missing its ending line.}% 3574 } 3570 3571 \SB@errero \newcommand\SB@errero{% \SB@Error{Encountered an \protect\endscripture\space whil% 3577 e processing a song}{Song \thesongnum\space ends wit% 3578 h \protect\endscripture\space when it should end wit% 3579 h \protect\endsong.}% 3580 } 3575 3576 \SB@errert \newcommand\SB@errert{% \SB@Error{Encountered an \protect\endscripture\space with% 3583 out first seeing a \protect\beginscripture}{Before son% 3584 g \thesongnum, there is an \protect\endscripture\space w% 3585 ith no matching \protect\beginscripture.}% 3586 } 3581 3582 \SB@errscrip \newcommand\SB@errscrip[1]{% \SB@Error{Encountered a \protect#1\space outside a scriptu% 3589 re quote}{\protect#1\space can only appear betwee% 3590 n \protect\beginscripture\space an% 3591 d \protect\endscripture\space lines.}% 3592 } 3587 3588 \SB@errchord \newcommand\SB@errchord{% \SB@Error{Song \thesongnum\space seems to have chord% 3595 s that appear outside of any verse or chorus}{All chords a% 3596 nd lyrics should appear between \protect\beginverse\space% 3597 and \protect\endverse, or between \protect\beginchorus\space% 3598 and \protect\endchorus.}% 3599 } 3593 3594 \SB@errreplay \newcommand\SB@errreplay{% \SB@Error{Replayed chord has no matching chord}{Son% 3602 g \thesongnum\space uses \protect^ more times than the% 3603 re are chords in the previously memorized verse.}% 3604 } 3600 3601 162 \SB@errreg \newcommand\SB@errreg[1]{% \SB@Error{Unknown chord-replay register name: #1}{Chord-re% 3607 play registers must be declared with \protect\newchords.}% 3608 } 3605 3606 \SB@errdup \newcommand\SB@errdup[1]{% \SB@Error{Duplicate definition of chord-replay register% 3611 : #1}{\protect\newchords\space was used to declare the sa% 3612 me chord-replay register twice.}% 3613 } 3609 3610 \SB@errmbar \newcommand\SB@errmbar{% \SB@Error{Song \thesongnum\space seems to have measur% 3616 e bars that appear outside of any verse or chorus}{All mea% 3617 sure bars (produced with \protect\mbar\space or |) must ap% 3618 pear between \protect\beginverse\space an% 3619 d \protect\endverse, or between \protect\beginchorus\space% 3620 and \protect\endchorus.}% 3621 } 3614 3615 \SB@errtab \newcommand\SB@errtab{% \SB@Error{Invalid argument to \protect\gtab\space macro. R% 3624 eplacing it with \protect\0.}{Valid arguments consist onl% 3625 y of: X, O, 0, 1, 2, 3, or 4.}% 3626 } 3622 3623 \SB@errnoidx \newcommand\SB@errnoidx[1]{% \SB@Error{Unknown index identifier: #1}{This index identifie% 3629 r was never declared using \protect\newindex.}% 3630 } 3627 3628 \SB@erridx \newcommand\SB@erridx[1]{% \SB@Error{\protect\idxaltentry\space not allowed in #1 index}% 3633 {This error should not occur. The index generation routines ha% 3634 ve malfunctioned. Try deleting all temporary files and then re% 3635 compiling.}% 3636 } 3631 3632 163 16.17 Option Processing \ifchorded Reserve conditionals for all of the various option settings. We wait to define these \iflyric since if any are used earlier than this, it is an error in the package code, and we’d \ifslides rather get an error than continue. \ifmeasures 3637 \newif\ifchorded \ifpartiallist 3638 \newif\iflyric\lyrictrue \ifrepchorus 3639 \newif\ifslides \iftranscapos 3640 \newif\ifmeasures \ifnolyrics 3641 \newif\ifpartiallist \ifrawtext 3642 \newif\ifrepchorus \ifsongindexes 3643 \newif\iftranscapos 3644 \newif\ifnolyrics \ifsepindexes 3645 \newif\ifrawtext \ifpagepreludes 3646 \newif\ifsongindexes\songindexestrue \ifSB@colorboxes 3647 \newif\ifsepindexes\sepindexestrue \ifSB@omitscrip 3648 \newif\ifpagepreludes 3649 3650 \nolyrics \pagepreludes \newif\ifSB@colorboxes\SB@colorboxestrue \newif\ifSB@omitscrip The \nolyrics and \pagepreludes macros are just shorthand for \nolyricstrue and \pagepreludestrue, respectively. \newcommand\nolyrics{} \let\nolyrics\nolyricstrue 3653 \newcommand\pagepreludes{\pagepreludestrue\songpos0} 3651 3652 Finally we’re ready to process all of the package options. This is delayed until near the end because the option processing code needs to execute various macros found in the previous sections. 3654 3655 \SB@colorbox \SB@chordson \ProcessOptions\relax Include the colors package and define colors, if requested. \ifSB@colorboxes \RequirePackage{color} 3658 \definecolor{SongbookShade}{gray}{.80} 3659 \newcommand\SB@colorbox[2]{% 3660 \ifx\@empty#1% 3661 \vbox{% 3662 \kern3\p@% 3663 \hbox{\kern3\p@{#2}\kern3\p@}% 3664 \kern3\p@% 3665 }% 3666 \else% 3667 \colorbox{#1}{#2}% 3668 \fi% 3669 } 3670 \else 3671 \newcommand\SB@colorbox[2]{\vbox{% 3656 3657 164 \kern3\p@% \hbox{\kern3\p@{#2}\kern3\p@}% \kern3\p@% 3672 3673 3674 3675 3676 }} \fi 16.18 Rawtext Mode If generating raw text, most of what has been defined previously is ignored in favor of some very specialized macros that write all the song lyrics to a text file. \ifrawtext \SB@newwrite\SB@txtout 3679 \immediate\openout\SB@txtout=\jobname.txt 3680 \newif\ifSB@doEOL 3681 {\catcode‘\^^M12 % 3682 \catcode‘\^^J12 % 3683 \gdef\SB@printEOL{\ifSB@doEOL^^M^^J\fi}} 3684 {\catcode‘#12\gdef\SB@hash{#}} 3685 {\catcode‘&12\gdef\SB@amp{&}} 3686 \renewcommand\SB@@@beginsong{% 3687 \begingroup% 3688 \def\’{}\def\‘{}\def\v{}\def\u{}\def\={}\def\^{}% 3689 \def\.{}\def\H{}\def\~{}\def\"{}\def\t{}% 3690 \def\copyright{(c)}% 3691 \let~\space% 3692 \let\par\SB@printEOL% 3693 \let\#\SB@hash% 3694 \let\&\SB@amp% 3695 \catcode‘|9 % 3696 \catcode‘*9 % 3697 \catcode‘^9 % 3698 \def\[##1]{}% 3699 \resettitles% 3700 \immediate\write\SB@txtout{\thesongnum. \songtitle}% 3701 \nexttitle% 3702 \foreachtitle{\immediate\write\SB@txtout{(\songtitle)}}% 3703 \ifx\songauthors\@empty\else% 3704 \immediate\write\SB@txtout{\songauthors}% 3705 \fi% 3706 \ifx\SB@rawrefs\@empty\else% 3707 \immediate\write\SB@txtout{\SB@rawrefs}% 3708 \fi% 3709 \immediate\write\SB@txtout{}% 3710 \SB@doEOLfalse% 3711 \obeylines% 3712 } 3713 \renewcommand\SB@endsong{% 3714 \SB@doEOLtrue% 3715 \immediate\write\SB@txtout{\songcopyright\space% 3677 3678 165 \songlicense\SB@printEOL}% \endgroup% \SB@insongfalse% \stepcounter{songnum}% 3716 3717 3718 3719 } \def\SB@parsesrefs#1{\def\songrefs{#1}} 3722 \long\def\beginverse#1#2\endverse{% 3723 \SB@doEOLtrue\begingroup% 3724 \def\textnote##1{##1}% 3725 \def\SB@temp{#1}% 3726 \def\SB@star{*}% 3727 \ifx\SB@temp\SB@star% 3728 \immediate\write\SB@txtout{\@gobble#2}% 3729 \else% 3730 \immediate\write\SB@txtout{#2}% 3731 \fi% 3732 \endgroup\SB@doEOLfalse} 3733 \long\def\beginchorus#1\endchorus{% 3734 \SB@doEOLtrue\begingroup% 3735 \def\textnote##1{##1}% 3736 \immediate\write\SB@txtout{Chorus:#1}% 3737 \endgroup\SB@doEOLfalse} 3738 \long\def\beginscripture#1\endscripture{} 3739 \def\musicnote#1{} 3740 \def\textnote#1{% 3741 \SB@doEOLtrue% 3742 \immediate\write\SB@txtout{#1\SB@printEOL}% 3743 \SB@doEOLfalse} 3744 \def\brk{} 3745 \def\rep#1{(x#1)} 3746 \def\echo#1{(#1)} 3747 \def\mbar#1#2{} 3748 \def\lrep{} 3749 \def\rrep{} 3750 \def\nolyrics{} 3751 \renewcommand\memorize[1][]{} 3752 \renewcommand\replay[1][]{} 3753 \fi 3720 3721 16.19 Codeline Index Numbers underlined refer to the code line where the corresponding entry is defined; numbers in roman refer to the code lines where the entry is used. \" \# \% \& . . . . . . . . . . . . Symbols . . . . . 2191, . . . . . 2600, . . . . . 3022, .......... 3689 3693 3106 3694 \’ . . . . . . . . 2189, \, . . . . . . . . . . . . . \- . . . . . . . . . . . . . \. 2194, 2986, 2997, \/ 1713, 1719, 2215, 166 3688 1095 2216 3689 2592 \; . . . . . . . . . . . . . 1095 \= . . . . . . . . 2193, 3688 \@centercr . . . . . . 1218 \@currentlabel 806, 1261 \@flushglue . . . . 63, 66, 135, 150, 291, 538, 613, 710, 711, 802, 835, 1613 \@ifdefinable . . . 25–29 \@ifnextchar . . 782, 785, 2668, 2679, 3070, 3079 \@ifstar . . . . . . . . . . . . . . 710, 714, 717, 1237 \@ixpt . . . . . 2611, 2612 \@onlypreamble . . 2974, 2976, 2978, 3111–3114 \@par . . . . . . . . . . . 1187 \@sanitize . . . . . . 1517 \@seccntformat . . . . . . . . . . . . . . . 2902, 2903, 2906, 2910, 2911, 2914 \@sptoken . . 1006, 1017, 1061, 1823, 2306, 2522 \@startsection . . . . . . . . . . . . . . . . 2904, 2912 \@viiipt . . . 2610, 2611 \@viipt 2609, 2610, 2738 \@vipt . 2608, 2609, 2759 \@vpt . . . . . . . . . . . 2607 \@xiipt 2614, 2615, 2755 \@xipt . . . . . 2613, 2614 \@xivpt . . . . 2615, 2616 \@xviipt . . . 2616, 2617 \@xxpt . . . . . 2617, 2618 \@xxvpt . . . . . . . . . 2618 \[ . . . . . . . . 2228, 2271, 2481, 2482, 2489, 2490, 2630, 2637, 2654, 3698 \\ . . . 721, 723, 805, 998, 1000, 1022, 1024, 1218, 2086, 2664, 2676, 2987, 2998, 3138, 3259, 3299 \^ . . . . . . . . 2190, 2222, 2227, 3681, 3682, 3688 \‘ . . . . . . . . 2188, 3688 \~ 2192, 2985, 2996, 3689 \ . . . . . . . 78, 123, 2353 A \AA . . . . . . . . . . . . 2207 \aa . . . . . . . . . . . . 2206 \Acolon . . . . . . . . . 1644 \active . . . . 1079, 1082, 1089, 1675, 1676, 2061, 2222, 2225, 2227, 2643– 2646, 2652, 2653, 2985 \AE . . . . . . . . . . . . 2205 \ae . . . . . . . . . . . . 2204 \afterpreludeskip . . . . . . . . . . . . . . . 89, 850 \alphascale . . . . . . 1766 \arabic . . . . . . . . 73, 76 \AtBeginDocument . . 293 \AtEndDocument . . . 3029 \authbyword . . . . . . 3086 \authignoreword . . 3086 \authsepword . . . . . 3086 B \b . . . . . . . . . . . . . 2201 \badness . . . . . . . . . . . . 1420, 1426, 1432, 3196 \baselineadj . . . 93, 893 \baselineskip 61, 96, 97, 881, 884, 885, 888, 891, 893, 980, 1268, 1274, 1357, 1616, 1617, 1994, 2029, 2036, 2044, 3213 \Bcolon . . . . . . . . . 1644 \beforepostludeskip . . . . . . . . . . . 89, 699, 857 \beginchorus . . . . 1324, 3469, 3506, 3528, 3535, 3537, 3541, 3543, 3554, 3556, 3597, 3619, 3733 \beginscripture . . . . . . 1605, 1649, 1661, 1667, 3583, 3585, 3590, 3738 \beginsong . . . . . . . . . . . . . . . 773, 1245, 1330, 3448, 3454, 3481, 3483, 3499, 3519, 3542, 3562 \beginverse . . . . . 1228, 3463, 3486, 3492, 3498, 3500, 3511, 3513, 3531, 3549, 3596, 3618, 3722 \bfseries . 77, 124, 128, 130, 984, 2907, 2915 \break . . . . . . . 369, 398, 405, 412, 623, 624, 3326 \brk . . . . . . . 1439, 3744 167 \brkpenalty . . . . . . 113, 1446, 1454, 1459, 1464 C \c . . . . . . . . . . . . . 2199 \c@page 438, 451, 537, 628 \c@section . . 845, 3039 \capo . . . . . . . . . . . 1779 \catcode . . . 1079, 1082, 1089, 1675, 1676, 2061, 2062, 2222, 2225–2227, 2369, 2643–2646, 2652, 2653, 2804, 2985, 2986, 3022, 3106, 3681, 3682, 3684, 3685, 3695–3697 \cbarwidth . . . . . . . . . . . 108, 151, 1196, 1393, 1394, 1399, 1408, 1444 \ccpenalty 113, 288, 1148 \centering . . . . . . 161, 928, 947, 2907, 2915 \ch . . . 2273, 2349, 2626 \chapter . . . 3239, 3240 \CheckCommand . . . . 1217 chorded (option) . . . . 181 \chordedfalse 203, 1503 \chordedtrue . 189, 1503 \chordlocals . . 86, 2229 \chordsoff . . . . . . . 181 \chordson . . . 181, 3441 chorus (environment) 1324 \chorusfont 47, 142, 1362 \chorusjustify . . . . . . . . . . . . . . 58, 144, 1362 \chorusmark . . . . . . . . . . . . . . . 119, 1337, 1343 \clearpage . . . . . . . . . . . . 625, 627, 2932, 3292 \clineparams . . 95, 2555 \closeout . . 3017, 3024 \colbotglue . . . . . . 132, 150, 198, 212, 291, 430, 614, 1157, 1166, 1468 \colorbox . . . . . . . 3667 \columnsep . . . 254, 256, 345, 3234, 3235, 3308 \commitsongs . 609, 2930 \copyright . . . . . . 3690 \cvpenalty 113, 290, 1146 D \d . . . . . . . . . . . . . 2200 \DeclareFlatSize . 2604 \DeclareLyricChar . . . . . . . . . 2125, 2188–2217 \DeclareNoHyphen . . . . . . . . . . . . . . 2125, 2218 \DeclareNonLyric . 2125 \DeclareOption 138, 169– 172, 175, 181, 182, 215, 216, 241, 242, 245, 246 \define@key . . . . . . . 764 \definecolor . . . . . 3658 \discretionary . . . 2217 E \echo . . . . . . 1516, 3746 \emergencystretch 1618 \endchorus . . . . . . 821, 1243, 1295, 1328, 1333, 3468, 3470, 3493, 3495, 3507, 3536, 3538, 3547, 3549, 3553, 3555, 3559, 3561, 3598, 3620, 3733 \endendverse . . . . . 3489 \endgraf . . . 1193, 1656 \endlinechar . . . . . 1522 \endscripture . . . . . . . . . . . . 1610, 3455, 3458, 3474, 3477, 3576, 3578, 3582, 3584, 3591, 3738 \endsong . . . . . . . . . . . . 778, 1254, 1292, 1333, 1373, 3449, 3451, 3461, 3467, 3473, 3476, 3480, 3482, 3565, 3568, 3579 \endverse . . . . . . . . . . . 820, 1242, 1254, 1327, 1386, 3462, 3464, 3487, 3504, 3507, 3510, 3512, 3516, 3518, 3529, 3532, 3550, 3597, 3619, 3722 \enskip . . . . 1120, 1134 \ensuremath . . . . . . 2600 environments: chorus . . . . . . . 1324 idxblock . . . . . 3205 intersong . . . . . 1552 SB@lgidx . . . . . 3208 SB@smidx . . . . . 3208 scripture . . . . . 1605 song . . . . . . . . . . 773 songgroup . . . . . 1541 songs . . . . . . . . 2917 verse . . . . . . . . 1228 verse* . . . . . . . 1228 \escapechar . . . . . . 2118 \eTeXversion . . . . . 2, 3 \everychorus . . 83, 1350 \everypar . . . . . . . . . . . . . . . 1278, 1360, 1502 \everyverse . . . 83, 1283 \exhyphenpenalty . . . . . . . . . . . . . . 2583, 3215 \extendpostlude 122, 981 \extendprelude . . . . . . . . . . . . . . 122, 928, 955 F \f@baselineskip . . 2622 \f@size 96, 880, 902, 1616, 2597, 2620, 2622, 3213 \finalhyphendemerits . . . . . . . . . . . . . . . 1638 \flat . . . . . . . . . . . 2601 \flatsymbol . 2600, 2603 \flt . . . . 883, 904, 1860, 1909–1913, 2602, 2647 \fontencoding . . . . . . . . 1538, 2736, 2745, 2753 \fontfamily . . . . . . . . . . 1538, 2736, 2745, 2753 \fontseries . . . . . . . . . . . . . . 2737, 2746, 2754 \fontshape . . . . . . . . . . . . . . 2737, 2746, 2754 \fontsize . . 2621, 2712, 2738, 2747, 2755, 2759 \foreachtitle . . . . . . . . . . 743, 813, 952, 3702 G \gtab . . 2800, 2813, 3623 \gtabtrans . 2814, 2818 H \H . . . . . . . . 2197, 3689 \hangafter . . . . . . . 164 \hangindent . . . . . . . 164 168 \hbadness . . . . . . . . . . . . . . . 3143, 3159, 3167 \hfuzz . 3143, 3159, 3167 \hphantom . . 2482, 2630 \hrule . . . 703, 840, 1561 \hsize 800, 832, 840, 852, 863, 920, 924, 927, 945, 1477, 1479–1481, 1559, 1561, 1570, 2835, 2843, 2844, 2846, 2851, 2853, 3128, 3131, 3156, 3187, 3211, 3219, 3233, 3253, 3284, 3289, 3386, 3393 \Huge . . . . . . . . . . . . 45 \huge . . . . . . . . . . . . 141 \hyperlink . . 2946–2948 \hypertarget . 2940–2942 \hyphenchar . . . . . . 2565 \hyphenpenalty . . . . . . . . . . . . . . . . 2584, 3215 I \i . . . . . . . . . . . . . 2213 \idxaltentry . . . . 3206, 3370, 3408, 3418, 3632 \idxauthfont . 128, 3415 \idxbgcolor . . . 55, 3357 idxblock (environment) . . . . . . . . . . . . . . 3205 \idxbook . . . . 130, 3393 \idxcont . . . . 131, 3386 \idxentry . . . . . . . . . . . 3206, 3366, 3402, 3414 \idxheadfont . 124, 3358 \idxheadwidth . . . . . . . . . . . . . 102, 3355, 3358 \idxlyricfont 126, 3371 \idxrefsfont . . . . . 129, 3368, 3372, 3404, 3416 \idxscripfont 127, 3403 \idxtitlefont 125, 3367 \if@filesw . . . . . . 2965 \if@twoside . . . . . . . . . . 451, 457, 462, 475, 537 \ifchorded . . . 222, 233, 882, 903, 1268, 1274, 1355, 1403, 1409, 1503, 1515, 2028, 2652, 3637 \IfFileExists . . 5, 3246 \iflyric . . . . . . . . 3637 \ifmeasures . . . . . . 194, 208, 2442, 2653, 3637 \ifnolyrics . 2550, 3637 \ifpagepreludes 832, 839, 854, 870, 944, 947, 3637 \ifpartiallist . . . . . . . . . . . . . 593, 610, 711, 714, 717, 1468, 3637 \ifrawtext . . . . . . . . . . . . . . . 186, 3637, 3677 \ifrepchorus . . . . . . . . . . . . . . . 260, 325, 579, 824, 1247, 1338, 1353, 1378, 1445, 1449, 3637 \ifSB@brokenword . . . . . . . . . 2051, 2556, 2584 \ifSB@chordedspec . . . . . . . . . . . . . . 148, 179 \ifSB@chorustop . . . . . . . . . . 1301, 1403, 1409 \ifSB@colorboxes . . . . . . . . . . . . . . 3637, 3656 \ifSB@convertnotes . . . . . . . . 1726, 1786, 1793 \ifSB@doEOL . 3680, 3683 \ifSB@etex . . . . . . . . . . . . . 1, 277, 1304, 1516 \ifSB@firstchord . . . . . . . . . 2077, 2236, 2240 \ifSB@gettabind . . . . . . . . . . 2761, 2836, 2845 \ifSB@gotchorus . . . . . . 1303, 1339, 1378, 1449 \ifSB@inchorus . . . . . . . . . . . . . 228, 239, 748, 821, 1195, 1243, 1295, 1328, 1369, 1393, 1443, 1495, 1509, 1960, 2520 \ifSB@insong . . . . . . . . . . . 748, 775, 819, 1241, 1286, 1326, 1368, 1440, 1553, 1580, 1584, 1602 \ifSB@intersong . . . . . . . . 748, 776, 875, 1554, 1565, 1585, 1591, 1621, 1629, 1647, 1660, 1666 \ifSB@inverse . 156, 227, 238, 748, 820, 1145, 1242, 1287, 1327, 1386, 1493, 1507, 1959, 2520 \ifSB@measurespec . . . . . . . . . . . 179, 193, 207 \ifSB@needkey 1770, 1899 \ifSB@nohat . 2085, 2706 \ifSB@omitscrip . . . . . . . . . . 1573, 1593, 3637 \ifSB@pdf . . . . . 8, 2937 \ifSB@preamble . . . . . . . . 16, 148, 198, 212, 250 \ifSB@prefshrps . . . . . . . . . . . . . . . 1769, 1902 \ifSB@prevverse . . . . . . . . . . . . . . . 825, 1146, 1148, 1216, 1249, 1339 \ifSB@songsenv . . . . . . . . . . . . . 267, 748, 2918 \ifSB@stanza . . . . . . . . . 1140, 1143, 1497, 1511 \ifSB@test 18, 365, 528, 2289, 2319, 2330, 2371, 2392, 2468, 2530, 2551 \ifSB@testii . . . 18, 372 \ifSB@trackch . . . . . . . . . . . . 2068, 2085, 2657 \ifSB@wordends . . . . . . . . . . . 2051, 2536, 2579 \ifsepindexes . . . . . . . . 3247, 3279, 3292, 3637 \ifslides . . . . . . . . . . . 45, 887, 907, 919, 3637 \ifsongindexes . . . . . . . . . . . 3018, 3232, 3637 \iftranscapos 1780, 3637 \ifvnumbered . . . . . 825, 1215, 1249, 1260, 1293 \includeonlysongs . . . . . . . . . 265, 3432, 3433 \indexentry . . 771, 3070 \indexesoff . . . 170, 172 \indexeson . . . . . . . 172 \indexsongsas . . . . 3081 \indextitleentry . . . . . . . . . . . . . . . 772, 3078 \input . 3023, 3260, 3301 \interlinepenalty . . . . . . . . . 112, 1191, 1192, 1194, 1203, 1204, 3193 intersong (environment) . . . . . . . . . . . . . 1552 \item . . . . . . . . . . . 1226 169 \itemindent . 1221, 1222 \itemsep . . . . . . . . 1220 J \j . . . . . . . . . . . . . 2214 \jobname 2968, 3023, 3679 \justifycenter . . . . . . . . . . . . . . 143, 145, 160 \justifyleft 58, 59, 154 L \L . . . . . . . . . . . . . 2211 \l . . . . . . . . . . . . . 2210 \LARGE 77, 124, 2907, 2915 \Large . . . . . . . . . . . 45 \large . . . . . . . . . . . 85 \lastbox . . . . . . . . 691, 694, 1632, 1964, 3147 \lastcolglue . . 134, 531 \lastpenalty . 411, 1492 \lastskip . . . . . . . . . . . 1162, 1568, 1963, 2539 \leaders 1408, 3125, 3194 \leftmargin . 1223, 1224 \leftskip . . . . . 62, 66, 80, 155, 156, 161, 163, 801, 834, 1394, 1395, 1475, 1480, 1614, 1633, 1654, 1670, 3142, 3192 \lineskip . 99, 948, 3214 \lineskiplimit 98, 3214 \list . . . . . . . . . . . 1219 \listparindent . . . 1222 \lq . . . . . . . 1702, 1715 \lrep . . . . . . 2035, 3748 lyric (option) . . . . . 181 \lyricfalse . . . . . . . 189 \lyricfont . 43, 78, 141, 815, 901, 1176, 2482 \lyrictrue . . 203, 3638 M \m@th . . . . . . . . . . . 2593 \makeatletter . . . . 3022 \makepostlude . 859, 979 \makeprelude . . 848, 917 \mark . . . . . . . . . . . . . . . . 335, 2001, 3397, 3406 \marks . . . . . . . . . . 697, 826, 1250, 1353, 1445 \maxdepth 309, 3221, 3267 \mbar . . . . . . . . . . 2022, 2024, 2347, 3617, 3747 \mch . . . 2274, 2351, 2632 \meaning . . . 2092, 2110, 2157, 2158, 2161, 2528 \measurebar . . . . . . . . . . . . . 2023, 2345, 2487– 2490, 2634, 2637, 2649 \measuresfalse . . . . 231 \measuresoff . . . . . . 215 \measureson . . . . . . . 215 \measurestrue . . . . . 220 \memorize . . . . . . . . . . . . . . . 1258, 2667, 3751 \meter . . 809, 1956, 2020 \minfrets . . . 136, 2859 \MultiwordChords . 2253 \musicnote . . . . . . . . . . . . . . 1515, 1780, 3739 N \newauthorindex . . 2977 \newbox . . . . . . . . . . 27 \newchords . . . . . . . . . . . . . . 2661, 3607, 3611 \newcount . . . . . . . . 25 \newcounter 69, 70, 2935 \newdimen . . . . . . . . 26 \newenvironment . . . . . . . . . . . 773, 1231, 1324, 1541, 1552, 1583, 1605, 2917, 3205, 3208, 3209 \newif . . 1, 8, 16, 18, 19, 179, 180, 748–752, 1140, 1215, 1216, 1301, 1303, 1726, 1769, 1770, 2051, 2052, 2236, 2657, 2706, 2761, 3637–3650, 3680 \newindex . . 2973, 3629 \newlength . . . . . . . . . . 40, 87, 89, 91, 93, 102, 104, 106, 108, 110, 2709 \newmark . . . 1310, 1311 \newmarks . . 1314, 1315 \newpage . . . . . . . . . 628 \newscripindex . . . 2975 \newsongkey . . . . . . . . . . . . . 760, 766, 768–772 \newtoks . . . . . . . . . 28 \newwrite . . . . . . . . 29 \nextcol . . . . . . . . . 709 \nexttitle . . . . . . 733, 735, 745, 812, 951, 3701 \nobreakspace . . . . 2235 noindexes (option) . . 172 \nolyrics . . 3651, 3750 \nolyricstrue . . . . 3652 nomeasures (option) . 215 \nonfrenchspacing 1095 nopdfindex (option) . 175 \norepchoruses . . . . 277 \normalfont . . . . . . . . . . . . . 43, 129, 141, 2829 \normalsize 43, 129, 2829 noscripture (option) 242 noshading (option) . . 171 \nosongnumbers . . . . 272 \notebgcolor . . 55, 1504 \notefont . . . . 47, 1472 \notejustify . . 60, 1482 \notenameA . . . . . . . . . . . . . . 1727, 1742, 1884 \notenameB . . . . . . . . . . . . . . 1727, 1743, 1885 \notenameC . . . . . . . . . . . . . . 1727, 1744, 1886 \notenameD . . . . . . . . . . . . . . 1727, 1745, 1887 \notenameE . . . . . . . . . . . . . . 1727, 1746, 1888 \notenameF . . . . . . . . . . . . . . 1727, 1747, 1889 \notenameG . . . . . . . . . . . . . . 1727, 1748, 1890 \notenames . . . . . . . . . . . . . . 1761, 1766, 1767 \notenamesin 1741, 1762 \notenamesout 1751, 1763 \notrans . . . . . . . . 1804 \noversenumbers . . . 273 O \o . . . . . . . . . . . . . 2208 \obeylines . . . . . . . . . . . . . . 1186, 1657, 3711 \obeyspaces . 1085, 1089 \OE . . . . . . . . . . . . 2203 \oe . . . . . . . . . . . . 2202 \onesongcolumn 147, 245 170 onesongcolumn (option) . . . . . . . . . . . . . . . 245 \openout 2968, 3020, 3679 options: chorded . . . . . . . 181 lyric . . . . . . . . . 181 noindexes . . . . . . 172 nomeasures . . . . . 215 nopdfindex . . . . . 175 noscripture . . . . 242 noshading . . . . . . 171 onesongcolumn . . 245 rawtext . . . . . . . 170 showmeasures . . . 215 slides . . . . . . . . 138 transposecapos . 241 twosongcolumns . 245 unouter . . . . . . . 168 \outer . . 168, 2097, 2102 P \p@songnum . . . . . . . 806 \p@versenum . . . . . . 1261 \PackageError . . . . 3421 \PackageWarning . . 3422 \pagepreludes . . . . 3651 \pagepreludestrue 3653 \pagetotal . . . . . . . . . . . . 358, 423, 2924, 3321 \parfillskip . . 63, 802, 835, 1613, 1638, 3212 \parindent . . . . . . . . . . . 63, 80, 101, 155, 158, 163, 835, 980, 1211, 1213, 1612, 1655, 3212 \parskip . 802, 835, 927, 954, 980, 1613, 3212 \partiallisttrue . . 268 \pdfbookmark . 2937–2939 \pdfoutput . . . . . . 9–11 \placenote 65, 145, 1504 \placeversenum . . . . . . . . . . . . . . 79, 162, 1269 \preferflats . . . . . 1782 \prefersharps . . . . 1782 \printchord . . . . . . . . . . 85, 883, 904, 2076, 2831 \printnoteA . . . . . 1734, 1752, 1903, 1909, 1913 \printnoteB . . . . . 1734, 1753, 1904, 1909, 1910 \printnoteC . . . . . . . . . . 1734, 1754, 1904, 1910 \printnoteD . . . . . 1734, 1755, 1905, 1910, 1911 \printnoteE . . . . . . . . . . 1734, 1756, 1905, 1911 \printnoteF . . . . . . . . . . 1734, 1757, 1906, 1912 \printnoteG . . . . . 1734, 1758, 1906, 1907, 1912 \printscrcite . 54, 1609 \printsongnum . . . . . . . . . . . . 77, 105, 936, 967 \printversenum . . . . . . . . . . 78, 107, 274, 1263 \ProcessOptions . . 3655 \protected@edef . . . . . . . . . . . 806, 1261, 3032 \protected@write . 2981 R \raggedright . . . . . 1212 rawtext (option) . . . . 170 \rawtexttrue . . . . . . 170 \rep . . . . . . . 1536, 3745 \repchoruses . . . . . . . . . . . . . . 277, 3444, 3522 \repchorusfalse 285, 645 \repchorustrue 280, 647 \replay . . . . . . . . . . . . . 1258, 1348, 2679, 3752 \RequirePackage . . . . . . . . . . . . . . 5, 42, 3657 \resettitles . . . . . 731, 810, 814, 844, 918, 3699 \rightmargin . . . . . 1223 \rightskip . 62, 66, 161, 801, 834, 1476, 1481, 1614, 1653, 3146, 3192 \rmfamily . . . . . . . . 126 \rq . . . . . . . 1709, 1721 \rrep . . . . . . 2043, 3749 S \SB@@@beginsong . . . . . . . . 785, 793, 795, 3686 \SB@@@ch . . . . . . . . 2626 \SB@@@gtab . . . . . . . . . . . . . . 2810, 2813, 2819 \SB@@@mch . . . . . . . 2632 \SB@@@pthead . . . . . 1004 \SB@@beginchorus . . . . . . . . . 1349, 1352, 1461 \SB@@beginsong . . . . 773 \SB@@bskvfmt . . . . . . 773 \SB@@ch . . . . . . . . . 2626 \SB@@chmacro 2338, 2340 \SB@@chord . 2220, 2237 \SB@@csify . . . . . . 2766 \SB@@echo . . . . . . . 1516 \SB@@gtab . . 2805, 2807 \SB@@idxcmd . . . . . . 3086 \SB@@idxentry 3070, 3079 \SB@@lop . . . . . . . . . 719 \SB@@mch . . . . . . . . 2632 \SB@@par . . . 1187, 1207 \SB@@prspace . . . . . 1084 \SB@@prstep . . . . . . 1052 \SB@@pthead . . . . . . 1004 \SB@@rechord . 191, 2693 \SB@@replay . . . . . . 2679 \SB@@selectcol . . . . . . . . . . 417, 507, 510, 513 \SB@@srcomma . . . . . 1097 \SB@@srcso . . . . . . 1131 \SB@@srdash . . . . . . 1103 \SB@@srhyphen . . . . 1103 \SB@@srspace . . . . . 1111 \SB@@UTFtest . . . . . 2106 \SB@accidental . . . . . . . . . . . 2591, 2602, 2603 \SB@activehat . . . . . . . . . . . . 2069, 2071, 2075, 2272, 2341, 2638, 2650 \SB@addDtest . . . . . . . . . 2132, 2134, 2136, 2155 \SB@addMtest 2141, 2173 \SB@addNtest . . . . . . . . . . . . . 2130, 2139, 2164 \SB@addtoindex . . . . . . . . . . . 3031, 3045, 3052 \SB@addtoindexes . . . . . . . . . . 811, 3043, 3075 \SB@addtotitles . . . . . . . . . . . 813, 3049, 3077 \SB@allindexes . . 2954, 2962, 2963, 3019, 3088 171 \SB@amp . . . . 3685, 3694 \SB@appendsp . . . . . . . . . . 995, 1038, 1824, 2437 \SB@atopfret . . . . 2718, 2732, 2733, 2742, 2759 \SB@balancerows . . . . . . . . . . . . . . . 3129, 3135 \SB@begincname . . 2220, 2221, 2628, 2635, 2800 \SB@beginverse . . 1229, 1232, 1237, 1238, 1240 \SB@box . . . . . . 30, 307, 657, 658, 668, 669, 678, 680, 691, 694, 700, 883, 884, 904, 905, 940, 960, 963, 965, 971, 975, 984, 985, 988, 989, 1176– 1178, 1181, 1259, 1263– 1266, 1269, 1290, 1354, 1374–1376, 1381, 1384, 1419, 1431, 1452, 1453, 1457, 1458, 1472, 1473, 1483, 1487, 1531, 1534, 1632, 1634, 1964–1966, 1968, 1984, 1986, 1987, 1996, 1997, 2004, 2830, 2835, 2851, 3123, 3128, 3131, 3137, 3147–3149, 3155, 3158, 3170, 3180, 3218, 3222, 3223, 3226, 3248, 3268, 3269, 3296, 3322, 3324, 3332, 3334 \SB@boxii . 30, 307, 308, 424, 426, 440, 934, 942, 960, 961, 1968, 1970, 1971, 1985, 1986, 1989, 1998, 1999, 2010, 2833, 2837, 2841, 2855, 3165, 3170, 3181, 3268, 3270, 3322, 3328, 3332, 3338 \SB@boxiii . . . 30, 308, 433, 435, 445, 490, 491, 2834, 2842, 2857, 2858, 3323, 3325, 3333, 3337 \SB@boxup . . 1471, 1504 \SB@bracket . . . . . . . . . . . . 190, 204, 2219, 2654 \SB@breakpoint . . . . . . . . 381, 549, 1144, 1154, 1446, 1454, 1459, 1464 \SB@brokenwordfalse . . . . . . . . . . . . 2533, 2544 \SB@brokenwordtrue . . . . . . . . . . . . . 2536, 2546 \SB@bskvfmt . . . . . . . . . . . . . 782, 788, 790, 791 \SB@bsoldfmt . . . . . . 773 \SB@cbarshift . . . . . . . . . . . 66, 157, 161, 1392 \SB@ch . . . 192, 206, 2626 \SB@ch@off 206, 236, 2626 \SB@ch@on 192, 234, 2626 \SB@chbgroup 2309, 2448 \SB@chbspace . . . . . . . . . . . . . 2415, 2416, 2419 \SB@chbstok . . . . . . . . . . . . . . 2058, 2426, 2506 \SB@chdone . . . . . 2256, 2269, 2399, 2414, 2430, 2478, 2483, 2491, 2493 \SB@chegroup 2311, 2452 \SB@chegrpdone . . . 2452 \SB@chegrpmacro . . 2452 \SB@chegrpname . . . 2452 \SB@chegrpouter . . 2452 \SB@chegrpscan . . . 2452 \SB@chendspace . . . . . . . . . . . 2259, 2412, 2429 \SB@chespace . . . . . . . . . . . . . 2259, 2290, 2309, 2311, 2316, 2320, 2325, 2350, 2352, 2360–2362, 2372, 2412, 2429, 2445 \SB@chexpspace . . . . . . . . . . . . . . . 2258, 2307, 2408, 2415, 2427, 2433 \SB@chgetname 2333, 2336 \SB@chgetspace . . . 2419 \SB@chhyph . 2315, 2400 \SB@chimpspace . . . . . . . . . . . 2257, 2354, 2356, 2408, 2416, 2428, 2432 \SB@chkidxlst . . . . . . . . . . . . 2920, 3055, 3074 \SB@chlig . . 2350, 2479 \SB@chlyrdone . . . . . . . . . . . . 2256, 2414, 2493 \SB@chmacro . 2300, 2328 \SB@chmain . . . . . . 2262 \SB@chmbar . . . . . . . . . . . . . . 2346, 2348, 2441 \SB@chmstop . . . . . . 2377 \SB@chmulti . . . . . . 2377 \SB@chnorm . . . . . . . . . . . . . . 2282, 2283, 2286 \SB@chnxtdone . . . . . . . . . . . . 2257, 2258, 2267, 2292, 2322, 2331, 2342, 2344, 2374, 2405, 2409, 2411, 2432, 2433, 2443 \SB@chnxtrelax . . . . . . . . . . . . 2267, 2271–2274 \SB@chnxtstep . . . . . . . . . . . . 2267, 2275–2277, 2290, 2316, 2320, 2325, 2372, 2403, 2428, 2445 \SB@chord 190, 2220, 2701 \SB@chordbox . . . . 2056, 2065, 2066, 2246, 2425, 2531, 2552, 2563, 2570 \SB@chordedspectrue . . . . . . . . . . . . . 183, 184 \SB@chordsoff . 148, 181 \SB@chordson . 181, 3654 \SB@chorusbar . . . . . . . . 1375, 1398, 1452, 1457 \SB@chorusbox . 325, 579, 582, 590, 648, 682, 698, 797, 824, 1247, 1302, 1340, 1341, 1379, 1380, 1450, 1451, 1555, 1586 \SB@chorustopfalse 1460 \SB@chorustoptrue 1334 \SB@chother . 2302, 2305 \SB@chothermac . . . . . . . . . . . . . . . . 2359, 2365 \SB@chscan . 2251, 2262, 2379, 2394, 2439, 2450 \SB@chspcdone 2430, 2493 \SB@chstart . 2250, 2270 \SB@chstep . 2268, 2377 \SB@chstepfour . . . . . . . . . . . . . . . . 2362, 2377 \SB@chstepthree . . . . . . . . . . . . . . . 2361, 2377 \SB@chsteptwo 2360, 2377 \SB@chtrymacro . . . . . . . . . . . . . . . . 2295, 2298 \SB@clearbskeys 760, 781 172 \SB@cleardpage . . . . . . . . . . . . . . 535, 616, 717 \SB@clearlig . . . . . . . . . 2514, 2553, 2568, 2576 \SB@clearpage . 250, 521, 536, 558, 615, 636, 714 \SB@closeall . . 753, 775, 776, 778, 875, 1254, 1292, 1333, 1373, 1553, 1554, 1557, 1580, 1584, 1585, 1588, 1602, 1610 \SB@cmark . . . . . . . . . . . . . 662, 671, 1250, 1318 \SB@cmarkclass . . . . . . . . . . . . . 661, 670, 826, 1250, 1304, 1353, 1445 \SB@cnt . . . 30, 248, 249, 252, 392, 399, 401, 406, 419, 428, 430, 449, 450, 452, 472, 473, 487–489, 491, 492, 494, 495, 498, 529–531, 1191, 1194, 1773–1776, 1858, 1861, 1864, 1867, 1877, 1883, 1892, 1896–1898, 1903, 1909, 1922, 2114–2116, 2122, 2128, 2359, 2368, 2369, 2567, 2573, 2586, 2768, 2774, 2799, 2859, 2864, 2865, 2887, 2888, 2890, 2993, 2996, 2997, 2999, 3000, 3169, 3196, 3305, 3306, 3309, 3317, 3339, 3344, 3345, 3350 \SB@cntii . . . . . . . . . . . 30, 425, 426, 434, 435, 439, 440, 444, 445, 448, 457, 460, 462, 469, 471, 477, 486, 2888, 2890 \SB@colbox . . . 301, 302, 359, 361, 374, 378, 379, 391, 393, 394, 524, 545 \SB@colnum 299, 346, 359, 361, 364, 370, 425, 450, 473, 486, 487, 494, 530 \SB@colon . . . . . . . . . . . . . . . 1644, 1645, 1646 \SB@colorbox . . . . . 934, 965, 1504, 3357, 3656 \SB@colorboxesfalse 171 \SB@colorboxestrue 3649 \SB@colwidth . . . . . . . . . . . . . . . . 137, 254–258, 344, 703, 800, 832, 852, 1559, 3211, 3233–3236 \SB@computess . . . . . . . . . . . . 1405, 1406, 1415 \SB@convertnotesfalse . . . . . . . . . . . . . . 1764 \SB@convertnotestrue . . . . . . . . . . . 1749, 1759 \SB@cr@ . 805, 1258, 2658 \SB@creg 2086, 2660, 2674, 2676, 2684, 2686, 2691 \SB@csify . . . . . . . . . . . . . . . 2766, 2884, 2886, 2889, 2893, 2897, 2898 \SB@ctail . . 2072, 2659, 2686, 2691, 2695, 2700 \SB@ctoken . . . . . . 2879 \SB@cwrite . . . . . . . . . . . . . . . 2979, 3036–3038 \SB@declare . . . . . . 2125 \SB@dimen . 30, 344–347, 349, 357–359, 378, 380, 393, 396, 422, 423, 426, 491, 663, 665, 669, 672, 673, 675, 880, 881, 888, 889, 891, 896, 897, 902, 905, 908, 909, 911, 912, 942–945, 1174, 1177– 1179, 1400, 1402, 1404, 1418, 1419, 1423, 1427, 1429, 1431, 1434, 1435, 1473–1477, 1987, 1989, 1991, 1992, 2002, 2008, 2014, 2029, 2036–2038, 2040, 2044, 2045, 2047, 2049, 2531, 2535, 2561– 2564, 2594–2597, 2723– 2725, 2727, 2841–2844, 2847, 2857, 3120, 3140, 3141, 3145, 3156, 3157, 3161, 3166, 3173, 3186, 3187, 3189, 3201, 3203, 3222, 3320, 3321, 3330, 3335, 3378–3381, 3383 \SB@dimenii . . . . . . . . . . 30, 664, 672, 678, 1401, 1403, 1410, 1423, 1425, 1427, 1429, 1432, 1433, 1994–1999, 2016, 2846– 2849, 3155, 3188, 3189, 3191, 3194, 3318, 3328– 3330, 3339, 3381–3383 \SB@dimeniii . . . . . . . . . 30, 665, 667, 673, 675, 677, 3161, 3162, 3166, 3171, 3173, 3174, 3177 \SB@dimeniv . . . . . . . . . . . . . . . . 30, 3162, 3164, 3171, 3174, 3177, 3179 \SB@displayindex . . . . . 3231, 3374, 3409, 3419 \SB@doEOLfalse . . . . . . . 3710, 3732, 3737, 3743 \SB@doEOLtrue . . . . . . . . 3714, 3723, 3734, 3741 \SB@dolq . . . . . . . . 1674 \SB@donext . . . . . . 991, 1018, 1020, 1023, 1026, 1028, 1030, 1062, 1064, 1066, 1068, 1070, 1072, 1074, 1113, 1118, 1129, 1819, 1822, 1825, 1827, 1829, 1839, 1848, 1852, 1856, 1859, 1862, 1865, 1868, 1870, 2266–2269, 2309, 2311, 2333, 2338, 2350, 2352, 2360–2362, 2427, 2698, 2701, 2704 \SB@dorq . . . . . . . . 1674 \SB@dothis . . . . . . 991, 1812, 1816, 1843, 1917, 2250, 2266, 2282, 2315 \SB@dotranspose . . . . . . 1787, 1795, 1800, 1810 \SB@droppage . . 353, 421 \SB@echo . . . . . . . . 1516 \SB@ellipspread . 3118, 3367, 3371, 3403, 3415 \SB@emitchord . . . . . . . . . . . . 2502, 2507, 2519 \SB@emptylist . . . . . 719 \SB@endchorus 1324, 1367 \SB@endcname . . . . 2221, 2239, 2629, 2636, 2802 \SB@endparse . . . . 1001, 1021, 1042, 1048, 1067 173 \SB@endscripture . . . . . . . . . . . . . . 1605, 1620 \SB@endsong . . . . . . . . . . . . . . . . 773, 818, 3713 \SB@endverse . . . . . . . . . . . . . 1230, 1233, 1285 \SB@envbox . . . . . . . . . . . . . . 41, 597, 836, 854, 1609, 1630, 1637, 3237, 3251, 3282, 3288, 3312 \SB@errbcc . 1328, 3534 \SB@errbct . 1330, 3540 \SB@errbcv . 1327, 3527 \SB@errboo . . 775, 3447 \SB@errbor . . 776, 3453 \SB@errbro . . . . . . . . . . . . . . 1553, 1584, 3564 \SB@errbrr . . . . . . . . . . . . . . 1554, 1585, 3570 \SB@errbvc . 1243, 3491 \SB@errbvt . 1245, 3497 \SB@errbvv . 1242, 3485 \SB@errchord 2520, 3593 \SB@errdup . 2665, 3609 \SB@erreco . 1387, 3552 \SB@errect . 1389, 3558 \SB@errecv . 1386, 3546 \SB@erreoc . . 821, 3466 \SB@erreor . . 875, 3472 \SB@erreot . . 876, 3479 \SB@erreov . . 820, 3460 \SB@errero . . . . . . . . . . . . . . 1580, 1602, 3575 \SB@errert . . . . . . . . . . . . . . 1580, 1602, 3581 \SB@erretex . . 283, 3521 \SB@errevc . 1295, 3503 \SB@errevo . 1296, 3509 \SB@errevt . 1298, 3515 \SB@erridx . . . . . . . . . . . . . . 3408, 3418, 3631 \SB@errmbar . 1960, 3614 \SB@errnoidx . . . . . . . . . 3059, 3083, 3342, 3627 \SB@errnse . 2918, 3427 \SB@Error . . . . . . . . . . . . . . . 1043, 1951, 3421, 3424, 3428, 3432, 3438, 3448, 3454, 3461, 3467, 3473, 3480, 3486, 3492, 3498, 3504, 3510, 3516, 3522, 3528, 3535, 3541, 3547, 3553, 3559, 3565, 3571, 3576, 3582, 3588, 3594, 3601, 3606, 3610, 3615, 3623, 3628, 3632 \SB@errpl . . . 267, 3431 \SB@errreg . . . . . . . . . . . . . . 2672, 2682, 3605 \SB@errreplay 2696, 3600 \SB@errrtopt . 187, 3437 \SB@errscrip . . . . 1641, 1648, 1661, 1667, 3587 \SB@errspos . . 516, 3423 \SB@errtab . . . . . . 3622 \SB@etextrue . . . . . . . 4 \SB@everypar . . . . 1209, 1262, 1270, 1273, 1275, 1278, 1356, 1358, 1360 \SB@finger . 2758, 2869 \SB@finloop . . . . . . . . . . 617, 618, 630, 631, 638 \SB@firstchord . . . 2236 \SB@firstchordfalse . . . . . . . . . . . . . . . . 2249 \SB@firstchordtrue . . . . . . . . . . . . . 2236, 2281 \SB@flatsize 2601, 2619 \SB@fretbar . . . . . . . . . . . . . . 2721, 2863, 2866 \SB@fretempty 2750, 2785 \SB@frethit . 2750, 2785 \SB@fretnum . 2711, 2833 \SB@fretwidth 2709, 2715, 2716, 2719, 2724, 2838 \SB@gettabindfalse . . . . . . . . 2084, 2761, 2877 \SB@gettabindtrue 2064 \SB@gotchorusfalse . 798 \SB@gotchorustrue 1248 \SB@groupcnt . . 568, 573, 586, 587, 617, 618, 630, 631, 639, 652, 869, 1544 \SB@grouplvl . 872, 1542, 1546, 1548, 1549, 1551 \SB@gtab . . . . . . . . 2800 \SB@gtinc . . 2779, 2865 \SB@gtinit . 2779, 2861 \SB@gtmax . . 2799, 2860 \SB@gtset . . . . . . . . . . . . . . . 2779, 2860, 2869 \SB@gttop . . 2779, 2834 \SB@hash . . . 3684, 3693 \SB@idxcmd . . . . . . 3086 \SB@idxcolhead . . . . . . . . . . . 3376, 3392, 3405 \SB@idxcont . 3385, 3406 \SB@idxentry 3070, 3079 \SB@idxheadsep . . . . . . . . . . . 3377, 3388, 3395 \SB@idxitemsep . . . . . . . . . . . 3199, 3259, 3299 \SB@idxlineskip . . 3115 \SB@idxsetup . . . . . . . . . 3210, 3224, 3256, 3300 \SB@ifempty . . . . . . . . . . . . 719, 736, 1258, 2695 \SB@ilpenalty . . . . . . . . . . . . 1196, 1198, 1202 \SB@inchorusfalse . . . . . . . . . . . . . . 752, 1372 \SB@inchorustrue . 1332 \SB@indexlist . . . . . . . . . . . . 2919, 2931, 2953, 3044, 3050, 3056, 3057, 3060, 3064, 3066, 3073 \SB@insertchorus . . . . . . . . . . . . . . . 326, 655 \SB@insongfalse . . . . . . . . . . . . 749, 867, 3718 \SB@insongtrue . . . . 777 \SB@intersongfalse . . . . . . . . . 750, 1578, 1600 \SB@intersongtrue . . . . . . . . . . . . . 1556, 1587 \SB@inversefalse . . . . . . . 681, 696, 751, 1291 \SB@inversetrue . . . . . . . . . . . . . . . . 683, 1253 \SB@iwrite . . . . . . . . . . 2970, 2981, 3008, 3098 \SB@keepactive . . . . . . . . . . . . . . . . 2981, 2984 \SB@lastcmark . . . . . . . . . . . . . . 686, 826, 1318 174 \SB@ldqleft . . . . . . 1674 \SB@ldqright . . . . . 1674 \SB@lettertests . . . . . . . . . . 2134, 2151, 2288 SB@lgidx (environment) . . . . . . . . . . . . . . 3208 \SB@lgindex . . . . . . . . . . . . . . 3272, 3275, 3295 \SB@ligfull . 2482, 2490, 2511, 2517, 2553, 2576 \SB@ligpost . . . . . 2481, 2489, 2511, 2516, 2568 \SB@ligpre . . . . . . . . . . 2480, 2511, 2515, 2559 \SB@loadactives . . . . . . . . . 227, 228, 238, 239, 1236, 1280, 1363, 2641 \SB@lop . . . . . . . . . 719, 739, 2072, 2700, 3139 \SB@lyric . . 2053, 2243, 2279, 2280, 2314, 2378, 2393, 2422, 2424, 2437, 2449, 2486, 2499, 2507 \SB@lyricbox . . . . . . . . . 2056, 2241, 2420, 2421, 2425, 2494, 2495, 2534, 2535, 2550, 2557, 2558, 2561, 2565, 2572, 2580 \SB@lyricnohyp . . . . . . . . . . . 2055, 2314, 2497 \SB@macrotests . . . . . . . 2130, 2139, 2151, 2370 \SB@makeauthorindex . . . . . . . . . . . . 3349, 3411 \SB@makeidxcolumn . . . . . . . . 3217, 3304, 3308 \SB@makembar . 221, 1958 \SB@makescripindex . . . . . . . . . . . . . 3348, 3390 \SB@maketitleindex . . . . . . . . . . . . . 3347, 3354 \SB@maxmin . . 304, 2561, 3191, 3330, 3380, 3382 \SB@mbar . 221, 232, 2022 \SB@mch . . . . . . . . . . . . . 223, 225, 234, 236, 2632 \SB@mch@m . . . 225, 2632 \SB@mch@on . . 223, 2632 \SB@mchlig . 2352, 2479 \SB@measuremark . . . . . . . . . . 1957, 1974, 2001 \SB@measuresoff . . . . . . . . . 194, 208, 210, 215 \SB@measureson . . . . . . . . . . 194, 196, 208, 215 \SB@measurespectrue . . . . . . . . . . . . . 217, 218 \SB@memorize . . . . . 2667 \SB@meterbot . . . . . . . . . . . . . 1954, 1956, 2024 \SB@metertop . . . . . . . . . . . . . 1954, 1956, 2024 \SB@migrate 332, 340, 341 \SB@mkpage . . . 305, 359, 426, 435, 440, 445, 491 \SB@mrkbox . . . . . . . . . . . . . 303, 338, 339, 366 \SB@multiline . . . . . . . . 3159, 3167, 3182, 3184 \SB@multitests . . . . . . . . . . . 2141, 2151, 2391 \SB@nbsp . . . 2234, 2355 \SB@needkeyfalse . . . . . . . . . 1782, 1783, 1921 \SB@needkeytrue . . . . . . . . . . . . . . . 1777, 1947 \SB@newbox 25, 34–36, 41, 298, 301–303, 574, 580, 1302, 2056, 2057, 3030 \SB@newcount . 25, 38, 39, 113–118, 136, 299, 300, 568, 1551, 1725, 2054 \SB@newdimen . . . . . . 25, 30–33, 137, 1208, 2762 \SB@newindex . . . . . . . . . 2958, 2973, 2975, 2977 \SB@newtoks . . . . . . . . . . 25, 37, 728, 729, 2053, 2055, 2658, 2659, 2663 \SB@newwrite . . . . . . . . . . . . . . . 25, 2967, 3678 \SB@next 991, 1004, 1006, 1014, 1015, 1017, 1019, 1021, 1024, 1040, 1052, 1054, 1061, 1063, 1065, 1067, 1069, 1097, 1099, 1103, 1105, 1107, 1109, 1111, 1114, 1117, 1138, 1695, 1696, 1699, 1706, 1816, 1818, 1820, 1823, 1837, 1840, 1847, 1855, 1860, 1863, 1881, 1926, 1932, 1941, 2092, 2126, 2127, 2157, 2158, 2161, 2264, 2271–2277, 2287, 2299, 2306, 2308, 2310, 2312, 2317, 2341, 2343, 2345, 2347, 2349, 2351, 2353, 2355, 2358, 2389, 2399, 2401, 2426, 2440, 2455, 2457, 2460, 2487, 2506, 2522–2526, 2528 \SB@nextcol . . . . . . . . . . . . . 388, 430, 531, 538, 613, 614, 710, 711, 1468 \SB@nextname . . . . . 994, 2166, 2181, 2263, 2337, 2368, 2390, 2438, 2453, 2475, 2488, 2505, 2528 \SB@nocmark . . . . . . . . . . . . . . . . 660, 697, 1318 \SB@nocmarkclass . . . . . . . . . . . 659, 697, 1304 \SB@nohatfalse . . . 2069 \SB@nohattrue . . . . 2064 \SB@noreplay . . . . 2088, 2482, 2630, 2702, 2707 \SB@numcols 245, 246, 249, 252, 253, 255, 258, 279, 295, 299, 311, 321, 355, 364, 378, 390, 448, 449, 452, 457, 460, 462, 469, 471, 472, 477, 489, 529, 538, 543, 557, 611, 800, 831, 852, 1559, 2927 \SB@numhyps . . . . . . . . . . 2054, 2244, 2313, 2402, 2496, 2542, 2543, 2583 \SB@obeylines . . . . . . . . . . . . 1184, 1281, 1364 \SB@omitscripfalse . 243 \SB@omitscriptrue . . . . . . . . . . . . . . 242, 244 \SB@oneidxpage . . . . . . . 3230, 3311, 3323, 3333 \SB@onfret . . . . . . . . . . . . . . 2714, 2750, 2751 \SB@otesta . . . . . . 2091 \SB@otestb . . . . . . 2091 175 \SB@othertests . . . . . . . . . . . 2132, 2151, 2318 \SB@out . . . . . . . . 2956, 2966–2968, 2970, 2980, 2981, 3012, 3016, 3017, 3020, 3024, 3087, 3097 \SB@outer 168, 2227, 2228 \SB@outertest . . . . . . . . . . . . 2091, 2329, 2467 \SB@output . . . . . . . . . . . . . 354, 409, 532, 546 \SB@par . . . . . . . . 1185, 1189, 1207, 2343, 2524 \SB@parindent . . . 1208, 1211, 1213, 1612, 1614, 1637, 1653–1655, 1670 \SB@parsesrefs . . . . . . . . 767, 1045, 1608, 3721 \SB@parsetitles 779, 996 \SB@pdffalse . . . . . . . 8 \SB@pdftrue . . . . . . . 12 \SB@pgbox . . . . . . . 302, 343, 347, 348, 368, 523 \SB@prcomma . 1066, 1078 \SB@prcpy . . . . . . . . . . . . . . . 1055, 1072, 1076 \SB@preamblefalse . 296 \SB@preambletrue . . 17 \SB@prefshrpsfalse . . . . 1783, 1924, 1927, 1933, 1937, 1939, 1942, 1946 \SB@prefshrpstrue 1782, 1923, 1925, 1929, 1931, 1935, 1938, 1940, 1944 \SB@prevversefalse . . . . . . . . . . . . . . 683, 1385 \SB@prevversetrue . . . . . . 681, 696, 808, 1294 \SB@prgr . . . 1070, 1076 \SB@prhyphen 1064, 1078 \SB@printEOL . . . . . . . . . 3683, 3692, 3716, 3742 \SB@prloop . . . . . . . . . . . . . . 1048, 1052, 1076, 1077, 1080, 1083, 1087 \SB@prspace . 1062, 1084 \SB@prstep . . . . . . 1052 \SB@ptbg . . . 1020, 1036 \SB@pthead . . . . . . . . . . . . . . 1001, 1004, 1026 \SB@ptloop . . . . . . . . . . 1015, 1028, 1036, 1039 \SB@ptmain . . . . . . . . . . . . . . 1009, 1015, 1016 \SB@ptsp . . . 1018, 1037 \SB@ptstep . . . . . . . . . . 1026, 1028, 1031, 1036 \SB@putbox . . . . . . . . . . . 682, 1172, 1290, 1376 \SB@putboxes . . . . . . . . . . . . . . . . 377, 424, 545 \SB@quotesactive . . . . . . . . . 1674, 1688, 1694 \SB@raggedright . . . . . . . . 803, 947, 980, 1210 \SB@rawrefs . . . 754, 766, 767, 811, 3706, 3707 \SB@rdqleft . . . . . . 1674 \SB@rdqright . . . . . 1674 \SB@rechord . . . . . . . . . . . . 191, 205, 2639, 2693 \SB@repcolon . . . . . . . . . . . . . 2026, 2041, 2046 \SB@replay . . . . . . 2679 \SB@scanlq . . . . . . 1674 \SB@scanrq . . . . . . 1674 \SB@scripdent . . . . 1665 \SB@selectcol . . . . 416, 504, 507, 510, 513, 544 \SB@setbaselineskip . . . 199, 213, 816, 879, 1503 \SB@setchord 2059, 2248 \SB@setkeysig 1899, 1920 \SB@setversesep 294, 895 \SB@sgroup . . . . . . . . . . 566, 570, 572, 573, 868, 872, 1543, 1549, 2923 \SB@skip . . . . . . . . . . . . 30, 822, 849, 856, 1157, 1158, 1160, 1162, 1169, 1404–1406, 1408, 1410, 1412, 1568, 1569, 1963, 1977, 1980, 2539, 2540 SB@smidx (environment) . . . . . . . . . . . . . . 3208 \SB@songbox . . . . . . . . . . . . . 298, 386, 433, 490, 553, 559, 562, 576, 589, 597, 642, 799, 853, 855, 1558, 1574, 1589, 1594 \SB@songlistbrk . . . . . . . . . . . . . 601, 614, 624 \SB@songlistcdp . . . . . . . . . . . . . 601, 616, 626 \SB@songlistcp . . . . . . . . . . . . . . 601, 615, 625 \SB@songlistnc . . . . . . . . . . . . . . 601, 613, 623 \SB@songsenvfalse . . . . . . . . . . . . . . 748, 2933 \SB@songsenvtrue . 2928 \SB@songwrites . . . 780, 838, 3030, 3034, 3035 \SB@spbegnew . . . . . . . . . . . . . . . . 432, 461, 470 \SB@spcinit . 2245, 2253 \SB@spdblpg 447, 465, 479 \SB@spextnew . . . . . . . . . . . . . . . . 443, 463, 478 \SB@spextold . . . . . . . . . . . . . . . . 437, 458, 476 \SB@spos . . . . . . . . 427, 505, 508, 511, 514, 519 \SB@sposi . . . . 456, 508 \SB@sposii 468, 496, 511 \SB@sposiii . . . 485, 514 \SB@sractives 1047, 1088 \SB@srcomma . 1091, 1097 \SB@srcso . . 1118, 1131 \SB@srdash . . . . . . 1103 \SB@srhyphen 1091, 1103 \SB@srspace . . . . . . . . . . 1091, 1099, 1111, 1133 \SB@srspacing 1092, 1094 \SB@stanzabreak . . . . . . . . . . . . 681, 683, 696, 1141, 1255, 1336, 1342 \SB@stanzafalse . . . 796 \SB@stanzatrue . . . . . . . . . . . . . . . . 1257, 1347 \SB@star . . . 3726, 3727 \SB@stypcol . . . . . . . . . . . . . . . . 541, 542, 1598 \SB@stype . . . . . . . 541, 578, 593, 1596, 1598 \SB@styppage . . . . . . . . . . . . . . . 556, 598, 1596 \SB@submitenv . 595, 870 \SB@submitpart 569, 593 176 \SB@submitsong . . . . . . . . . 592, 871, 1576, 1597 \SB@tabargs . 2823, 2879 \SB@tabindent 2241, 2242, 2761, 2837–2839, 2849 \SB@targfing . . . . 2763, 2822, 2870, 2889, 2897 \SB@targfret . . . . 2763, 2820, 2833, 2892, 2896 \SB@targsfing . . . . 2867 \SB@targstr . . . . . . . . . . . . . . 2763, 2821, 2824, 2825, 2834, 2860, 2863, 2884, 2886, 2893, 2898 \SB@temp . . . . . . . . . . . . 18, 307, 313, 334, 335, 350, 353, 571, 572, 612– 616, 622–626, 639, 659– 662, 670, 671, 686, 725, 726, 897, 899, 1087, 1131, 1133, 1842, 1874, 1884–1890, 1894, 1900, 1915, 1973, 1974, 2103, 2104, 2119–2121, 2174, 2182, 2185, 2553, 2568, 2576, 2589, 2882, 2883, 2885, 2902, 2906, 2910, 2914, 2992, 3003–3006, 3010, 3019, 3021, 3044– 3046, 3050–3052, 3056, 3058, 3088, 3089, 3098, 3121, 3124, 3144, 3190, 3238, 3241, 3244, 3343, 3345, 3346, 3725, 3727 \SB@tempii 18, 308, 312, 316, 573, 574, 576, 578, 580, 582, 639, 641, 643, 644, 649, 651, 898, 899, 3009, 3010, 3032, 3033, 3058, 3059, 3061, 3064, 3095, 3096, 3136, 3195 \SB@tempiii . . . . . . . 18 \SB@tempiv . . . . . . . 18 \SB@tempv . . . . . . . . . . . . . 18, 1796, 1798, 1801 \SB@testfalse . . . . . . . . . 360, 525, 2104, 2146, 2149, 2366, 2521, 2549 \SB@testiifalse 362, 364 \SB@testiitrue . . . . 360 \SB@testtrue . . . . . 362, 364, 522, 2104, 2144, 2149, 2288, 2318, 2369, 2391, 2522–2526, 2550 \SB@titlelist . 728, 732, 998, 1022, 1032, 1033 \SB@titlesep 1000, 1041 \SB@titletail . . . . . . . . . . . 728, 732, 736, 739 \SB@toks 30, 333–335, 739, 740, 999, 1025, 1033, 1034, 1038, 1047, 1049, 1076, 1077, 1080, 1083, 1086, 1788, 1796, 1801, 1811, 1821, 1824, 1832, 1845, 1850, 1893, 1894, 1901, 1915, 2072, 2697, 2700, 2704, 2767, 2770, 2775, 3011, 3012, 3061, 3063, 3066, 3122, 3126, 3136, 3138–3140, 3304, 3307, 3311, 3405, 3406 \SB@topempty . . . . . . . . . . . . . 2732, 2780, 2869 \SB@topO . . . 2732, 2780 \SB@topX . . . 2732, 2780 \SB@tracc . . . . . . . . . . . . . . . 1862, 1865, 1881 \SB@trackch . . . . . . 2657 \SB@trackchfalse . . . . . . . . . . . . . . 2683, 2690 \SB@trackchtrue . . 2673 \SB@transposefactor . . . 804, 1725, 1772, 1773, 1776, 1785, 1794, 1806, 1857, 1896, 1899, 2809 \SB@trend . . . . . . . . . . . . . . . 1813, 1847, 1950 \SB@trgroup . 1819, 1831 \SB@trmain . . . . . . . . . . . . . . 1812, 1817, 1917 \SB@trnote . 1843, 1854 \SB@trnotestep . . . . . . . . . . . . . . . . 1856, 1872 \SB@trscan . . . . . . . . . . . . . . 1813, 1816, 1833, 1836, 1839, 1875, 1918 \SB@trskip . . . . . . . . . . . . . . 1822, 1825, 1835 \SB@trspace . . . . . . 1835 \SB@trstep . 1827, 1838 \SB@trtrans . . . . . 1859, 1868, 1878, 1881, 1882 \SB@txtout . . . . . . . . . . 3678, 3679, 3700, 3702, 3704, 3707, 3709, 3715, 3728, 3730, 3736, 3742 \SB@U@four . . . . . . 2106 \SB@U@three . . . . . . 2106 \SB@U@two . . . . . . . 2106 \SB@uncombine . . . . 3015 \SB@updatepage . . . . . . . . . . 318, 323, 337, 421 \SB@UTFtest . . . . . . . . . . . . . . 2106, 2127, 2358 \SB@Warn . . . 3421, 3444 \SB@warnrc 260, 279, 3443 \SB@wordendsfalse 2530 \SB@wordendstrue . 2530 \sbarheight 110, 152, 382, 383, 550, 551, 690, 701, 703, 839, 840, 860, 863, 1560, 1561, 1566, 1570 \scantokens . . . . . . 1523 \scitehere . 1622, 1628 \scleardpage . . . . . . 716 \sclearpage . . . . . . . 713 \scripindent . . . . . 1665 \scripoutdent . . . . 1665 scripture (environment) . . . . . . . . . . . . . 1605 \scripturefont 50, 1615 \scriptureoff . 146, 242 \scriptureon . . . . . . 242 \selectfont . . . . . . . . . . 1538, 2027, 2623, 2712, 2738, 2747, 2755, 2759 \sepindexestrue . . 3647 \sepverses . . . . . . . 286 \setkeys . . . . . . . . . 792 \setlicense . . . 759, 770 \sfcode . 984, 1095, 3415 \sffamily . . . . . . . . . . . . . . 45, 54, 77, 85, 124, 125, 127, 1984, 1985, 2712, 2759, 2907, 2915 \sharpsymbol 2600, 2602 \shiftdblquotes 52, 1674 \showauthors . . 122, 983 \showindex . . . . . . 3341 177 showmeasures (option) 215 \showrefs . . . . 122, 987 \shrp . . . 883, 904, 1863, 1903–1907, 2602, 2648 \slides . . . . . . . . . . 138 slides (option) . . . . 138 \slidestrue . . . . . . . 140 \slshape 45, 85, 125, 127, 142, 988, 1521, 1529 \small . . . . . . . . . . . 54, 127, 128, 130, 131, 928 \snumbgcolor 55, 934, 965 \solfedge . . . . . . . 1766 song (environment) . . 773 \songauthors . . 754, 768, 811, 984, 3703, 3704 \songchapter 2901, 3241 \songcolumns . . . . . . . . . . . . . . . 245, 295, 2927 \songcopyright . . . . . . . . . 123, 754, 769, 3715 songgroup (environment) . . . . . . . . . . . . . 1541 \songindexesfalse . 174 \songindexestrue . . . . . . . . . . . . . . . 173, 3646 \songlicense . . . . . . . . . . . 123, 754, 759, 3716 \songlink . . . 177, 2945 \songlist . . . . . . . . . . . . . . 265, 571, 612, 622 \songmark . . . . 119, 837 \songnumstyle . . . . . 71 \songnumwidth . 104, 272, 933, 935, 941, 958, 966 \songpos . . . . . . . . 502, 520, 3424, 3425, 3653 \songrefs . . . . 758, 766, 988, 1049, 1609, 3721 songs (environment) 2917 \songsection 2909, 3238 \songtarget . . . . . . . . . . . . . . . . 176, 845, 2936 \songtitle . . . . . . . . . . . . . 730, 737, 740, 744, 745, 811, 813, 921, 950, 952, 2939, 3700, 3702 \spacefactor . . . . . . . . . 1115, 1116, 2573, 2586 \spenalty . . . . . . . . . . . . . . 118, 149, 381, 549 \splitbotmark 341, 3225 \splitfirstmark . . . . . . . . . . . . . . . . 340, 1973 \splitfirstmarks . . . . . . . . . . . . 659, 661, 670 \splitmaxdepth . . . . . . . . . . . . 309, 3221, 3267 \splittopskip . . . . . . . . . . . . . 309, 3221, 3267 \ss . . . . . . . . . . . . 2212 \stitlefont 44, 921, 949 \strophe . . . . . . . . 1659 T \t . . . . . . . . 2198, 3689 \textbf . . . . . . . . . . 131 \textheight . . . . . . . . . . 198, 357, 422, 435, 440, 445, 3268, 3280, 3320 \textnote . . . . . . 1490, 1515, 3724, 3735, 3740 \textwidth . . . 257, 832 \theSB@songsnum . . . . . . . . . . . . . . . . 846, 3038 \thesongnum . . . . . . . . . . . . . . 71, 806, 846, 868, 936, 967, 1543, 2939, 2961, 3038, 3450, 3457, 3463, 3469, 3475, 3481, 3488, 3494, 3500, 3505, 3511, 3517, 3530, 3537, 3543, 3548, 3554, 3560, 3567, 3573, 3577, 3584, 3594, 3602, 3615, 3700 \theversenum . . . . . . . . . . . . . . . 74, 1261, 1263 \tiny 954, 981, 1984, 1985 \titleprefixword . 3086 \transcapostrue . . . 241 \transpose . 1771, 1780 transposecapos (option) . . . . . . . . . . . . . . . 241 \transposehere . . 1784, 1807, 2079, 2818, 2831 \trchordformat . . . . . . . . . . . . . . . . 1801, 1815 \twosongcolumns . . . 245 twosongcolumns (option) . . . . . . . . . . . . . . . 245 U \u . . . . . . . . 2195, 3688 \uccode . . . . . . . . . . . . . 1841, 1873, 2996, 2997 unouter (option) . . . . 168 \uppercase . . . . . . 2998 \upshape . . . 1521, 1529 \usefont . . . . . 51, 2027 \usepackage . . . . . . 3439 V \v . . . . . . . . 2196, 3688 \vbadness 420, 656, 1417, 1969, 3266, 3317, 3339 \vcpenalty 113, 289, 1148 \verse . . . . . . . . . . 1217 178 verse (environment) 1228 verse* (environment) 1228 \versefont . . . 47, 1279 \versejustify . . . . . . . . . . . 58, 143, 144, 1279 \versemark . . 119, 1256 \versenumstyle . . . . 74 \versenumwidth . . . 106, 156, 275, 1264, 1266 \versesep . . . . . . . . . . . 87, 699, 822, 898, 908, 911, 1151, 1498, 1512 \vfuzz . . 420, 656, 1417, 1969, 3266, 3318, 3339 \vnumbered . . . . . . 1215 \vnumberedfalse . . . . . . . . . . 1232, 1237, 1335 \vnumberedtrue . . . . . . . . . . . . . . . . 1229, 1238 \vrule . . . . . . 863, 1268, 1274, 1357, 1408, 1570, 2016, 2038, 2040, 2047, 2049, 2715, 2727, 2743 \vsize . . . . . . . . . . . 369 \vsplit . . 313, 658, 669, 678, 1971, 3222, 3268 \vvpenalty . . . . . . . . . . 113, 287, 289, 290, 1146 \write . 3012, 3704, 3728, W . . . . . . . . 2970, 3097, 3700, 3702, 3707, 3709, 3715, 3730, 3736, 3742
© Copyright 2024