diff options
Diffstat (limited to 'Master/texmf-dist/source')
-rw-r--r-- | Master/texmf-dist/source/latex/songs/songs.dtx | 11898 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/songs/songs.ins | 61 |
2 files changed, 11959 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/songs/songs.dtx b/Master/texmf-dist/source/latex/songs/songs.dtx new file mode 100644 index 00000000000..d2ef70a9d26 --- /dev/null +++ b/Master/texmf-dist/source/latex/songs/songs.dtx @@ -0,0 +1,11898 @@ +% \iffalse meta-comment +% +% Copyright (C) 2012 Kevin W. Hamlen +% +% This program is free software; you can redistribute it and/or +% modify it under the terms of the GNU General Public License +% as published by the Free Software Foundation; either version 2 +% of the License, or (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +% MA 02110-1301, USA. +% +% The latest version of this program can be obtained from +% http://songs.sourceforge.net. +% +% \fi +% +% \iffalse +%<*driver> +\ProvidesFile{songs.dtx} +%</driver> +%<package>\NeedsTeXFormat{LaTeX2e} +%<package>\ProvidesPackage{songs} +%<*package> + [2012/03/17 v2.14 Songs package] +%</package> +% +%<*driver> +\documentclass{ltxdoc} +\usepackage[bookmarks]{hyperref} +\usepackage[nopdfindex]{songs} +\let\oldSE\StopEventually + +% Configure the document: +\EnableCrossrefs +\CodelineIndex +\RecordChanges +%\OnlyDescription + +% Create the \Songs logo, if appropriate fonts are available: +\IfFileExists{harmony.sty}{ + \usepackage{harmony} + \usepackage{graphics} + \newcommand\Songs{\texorpdfstring{{\sffamily s\kern.07ex\resizebox{!}{1ex}{\Ganz}\kern-.09ex ngs}}{songs}} +}{ + \newcommand\Songs{\texorpdfstring{{\sffamily songs}}{songs}} +} + +% Create the logo for Christopher Rath's Songbook package: +\newcommand{\Rath}{{\sffamily Song$\flat$ook}} + +% Define some environments to simulate the interior of a verse, +% for showing samples in the documentation: +{\makeatletter + \gdef\likeverse{% + \SB@insongtrue\SB@inversetrue% + \SB@loadactives% + \global\SB@ctail\SB@cr@% + } + \gdef\chordheight{\SB@setbaselineskip} +} + +% Typeset a block of LaTeX code: +\newenvironment{codeblock}{% + \medskip% + \vbox\bgroup\begingroup% + \narrower\rightskip=0pt plus1fil% + \parindent=0pt% + \obeylines% +}{% + \endgroup\egroup% + \medskip% +} + +% Typeset a sample song or scripture quotation: +\songcolumns{0} +\newenvironment{sample}{% + \medskip% + \noindent\hfil% + \vbox\bgroup% + \hsize.5\hsize% + \advance\hsize-.5\columnsep% + \versesep=5pt% +}{% + \egroup% + \medskip% +} + +% Typeset a sample lyric book fragment: +\newenvironment{lyrics}{% + \medskip% + \noindent\hfil% + \vbox\bgroup\begingroup% + \hsize=.7\textwidth% + \leftskip=20pt\rightskip=0pt plus1fil% + \parindent=-20pt% + \likeverse\obeylines% +}{% + \par\endgroup\egroup% + \hfil\par% + \medskip% +} + +% Typeset a sample chord book fragment: +\newenvironment{chorded}{% + \medskip% + \noindent\hfil% + \vbox\bgroup\begingroup% + \hsize=.7\textwidth% + \leftskip=20pt\rightskip=0pt plus1fil% + \parindent=-20pt% + \likeverse\obeylines% + \versesep=5pt\chordheight% +}{% + \par\endgroup\egroup% + \hfil\par% + \medskip% +} + +% Typeset a "<code> produces <text>" example: +\newlength\prodlen +\setlength{\prodlen}{2.7in} +\newbox\prodbox +\newcommand{\example}{% + \medskip\setbox\prodbox\hbox\bgroup% +} +\newcommand{\produces}{% + \egroup% + \indent% + \vbox{\hbox to\prodlen{\unhbox\prodbox\hfil}}% + \ {\it produces}\quad% + \afterassignment\prodprefix% + \setbox\prodbox\hbox} +\newcommand{\prodprefix}{% + \likeverse\chordheight% + \aftergroup\prodsuffix} +\newcommand{\prodsuffix}{\unhbox\prodbox\par\medskip} +\newbox\vcbox +\newdimen\vcadjust +\newcommand{\vcenterbox}[1]{% + \setbox\vcbox\vbox{\hbox{#1}}% + \vcadjust=.5\ht\vcbox% + \advance\vcadjust by-6pt% + \lower\vcadjust\box\vcbox% +} + +% Recode \DescribeMacro and \DescribeEnv to make nice pdfbookmark entries. +% Also create some \MainImpl macros that make pdfbookmarks to help the reader +% find the "real" implementations of important macros. +\newcount\seclevel% +\newcommand{\getseclevel}{% + \ifnum\value{subsection}=0 \seclevel=2 % + \else\ifnum\value{subsubsection}=0 \seclevel=3 % + \else\seclevel=4 \fi\fi% +} +{\makeatletter + \xdef\bschar{\@backslashchar} + \global\let\For\@for} +\newcommand\DescMacro[1]{% + \getseclevel% + \pdfbookmark[\the\seclevel]{\bschar\bschar#1}{macdef-#1}% + \expandafter\DescribeMacro\expandafter{\csname#1\endcsname}% + \hyperdef{macro}{#1}{}\kern0pt% +} +\newcommand\DescMacroGroup[3]{% + \getseclevel% + \pdfbookmark[\the\seclevel]{\bschar\bschar#2}{macdef-#1}% + \expandafter\DescribeMacro\expandafter{\csname#2\endcsname}% + \For\temp:=#3\do{\hyperdef{macro}{\temp}{}}% +} +\newcommand\MainImpl[1]{% + \pdfbookmark[3]{\bschar\bschar#1}{mimpl-#1}% +} +\newcommand{\DescEnv}[1]{% + \getseclevel% + \pdfbookmark[\the\seclevel]{#1}{envdef-#1}% + \DescribeEnv{#1}% + \hyperdef{env}{#1}{}\kern0pt% +} +\newcommand{\MainEnvImpl}[1]{% + \getseclevel% + \pdfbookmark[\the\seclevel]{#1}{eimpl-#1}% +} + +% Create macros to hyperlink macro and environment names to their +% documentation points. +\newcommand{\mac}[1]{{\tt\hyperlink{macro.#1}{\char92 #1}}} +\newcommand{\env}[1]{{\tt\hyperlink{env.#1}{#1}}} + +% Defining bookmarks for definitions of active characters is a little trickier +% because many of these characters have special meanings either to TeX or to +% PDF. The only reliable way is to insert an "\ooo" escape sequence into the +% bookmark text, where ooo is the ascii number of the character expressed in +% octal. To achieve this, we use `\string<symbol> to obtain the decimal +% ascii number d of the symbol, then do some math (implemented in \octalize) +% to compute the decimal number n whose digits correspond to the octal +% representation of d, and then write n to the bookmark text using \the. +\newcount\cnta +\newcount\cntb +\newcount\cntc +\newcommand{\octalize}[2]{% + \cntb\cnta + \divide\cntb#1 + \multiply\cntb#2 + \advance\cntc\cntb + \divide\cntb#2 + \multiply\cntb#1 + \advance\cnta-\cntb +} +\newcommand{\DescChar}[2]{% + \expandafter\let\csname string#1\expandafter\endcsname + \expandafter=\string#2% + \getseclevel + \cnta\expandafter`\string#2% + \cntc0 + \octalize{64}{100}% + \octalize{8}{10}% + \octalize{1}{1}% + \pdfbookmark[\the\seclevel]{\bschar\the\cntc}{#1def}% + \expandafter\DescribeEnv\string#2% + \hyperdef{env}{#1}{}\kern0pt% +} +\newcommand{\refchar}[1]{{\tt\hyperlink{env.#1}{\csname string#1\endcsname}}} + +% At the end of the implementation section we'll have a code line index of +% macro definitions and usages. To make it look a bit less ragged than the +% default index style and to conserve some space, we'll customize a few of +% the parameters: + +\IndexPrologue{% + \subsection{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.} + +{\makeatletter + + \gdef\IndexParms{% + \sfcode`,=1750 + \parindent0pt + \columnsep15pt + \parskip0pt plus1pt + \rightskip0pt + \mathsurround0pt + \parfillskip0pt + \small + \def\@idxitem{\par\hangindent15pt}% + \def\subitem{\@idxitem\hspace*{15pt}}% + \def\subsubitem{\@idxitem\hspace*{25pt}}% + \def\indexspace{\par\vspace{10pt plus 2pt minus 3pt}}} + + \gdef\SpecialMainOptIndex#1{% + \@bsphack + \special@index{% + #1\actualchar{\string\ttfamily\space#1} (option)\encapchar main}% + \special@index{% + options:\levelchar + #1\actualchar{\string\ttfamily\space#1}\encapchar main}% + \@esphack} +} + +% Create a conditional that typesets its first argument if we're including +% the implementation section, otherwise typesets its second argument. +\newcommand\ImplOrDesc[2]{% + \ifx\StopEventually\oldSE#1\else#2\fi% +} + +% Hyphenating the word "choruses" looks weird. No "ruses" please! +\hyphenation{choruses} + +% An environment for describing the implementation of a package option: +\let\oldsmei\SpecialMainEnvIndex +\newenvironment{option}[1]{% + \let\SpecialMainEnvIndex\SpecialMainOptIndex% + \begin{environment}{#1}% + \let\SpecialMainEnvIndex\oldsmei% +}{% + \end{environment}% + \let\SpecialMainEnvIndex\oldsmei% +} + +% Describe the default setting for an option: +\newcommand\optdef[1]{\noindent{\it(Default: #1)}\hspace{.5cm}} + +% Typeset a chord name: +\newcommand{\chord}[1]{{\sffamily\slshape#1}} + +% Here are a few macros to produce nice syntax parameters: +\newcommand{\argp}[1]{\meta{arg#1}} +\newcommand\Meta[1]{\textrm{\meta{#1}}} +\newcommand\OR{\,$\mid$\,} +\newcommand\SPC{\char`\ } + +% Now let's quell those annoying "Marginpar has moved" warning messages. +{\makeatletter + \global\let\oldamp=\@addmarginpar + \global\let\oldlwnl=\@latex@warning@no@line + \gdef\@addmarginpar{% + \let\@latex@warning@no@line\@gobble% + \oldamp% + \let\@latex@warning@no@line\oldlwnl% + } +} + +% The \eat macro just gobbles its argument. I use it to appease my syntax +% highlighter when it gets confused. +\newcommand{\eat}[1]{} + +\begin{document} + \DocInput{songs.dtx} +\end{document} +%</driver> +% \fi +% +% \CheckSum{8597} +% +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} +% +% \changes{v1.0}{2001/12/01}{Initial version} +% \changes{v1.1}{2005/04/03}{Change log introduced and first release of this documentation} +% \changes{v1.17}{2005/09/24}{Transformed the source from a class to a package} +% \changes{v1.18}{2005/09/29}{Verse numbering added} +% \changes{v2.0}{2007/06/20}{Keyval syntax and chord-replay system added} +% +% \iffalse +% Here we list all the macros that should not be indexed because they are: +% (a) too common and therefore the index would be too large if we listed them, +% (b) not useful in an index because they are predefined TeX macros, or +% (c) not really macros but rather control sequence names given to \string. +% \fi +% \DoNotIndex{\@M,\@depth,\@empty,\@firstofone,\@firstoftwo,\@gobble,\@gobbletwo,\@height,\@m,\@minus,\@ne,\@plus,\@secondoftwo,\@width,\m@ne,\p@,\thr@@,\tw@,\voidb@x,\@xpt,\z@,\z@skip} +% \DoNotIndex{\advance,\char,\count,\divide,\font,\fontdimen,\maxdimen,\multiply,\setcounter,\setlength,\settoheight,\settowidth,\stepcounter} +% \DoNotIndex{\begin,\begingroup,\bgroup,\egroup,\end,\endgroup} +% \DoNotIndex{\box,\copy,\dp,\hbox,\ht,\leavevmode,\lower,\null,\prevdepth,\raise,\rlap,\setbox,\unhbox,\unhcopy,\unpenalty,\unskip,\unvbox,\unvcopy,\vbox,\vtop,\wd} +% \DoNotIndex{\csname,\def,\edef,\endcsname,\futurelet,\gdef,\global,\let,\long,\mathchardef,\newcommand,\renewcommand,\renewenvironment,\xdef} +% \DoNotIndex{\@ifundefined,\@for,\do,\else,\fi,\ifcase,\ifcat,\ifdim,\iffalse,\ifhmode,\ifmmode,\ifinner,\ifnum,\ifodd,\ifvbox,\ifvmode,\ifvoid,\ifx,\loop,\or,\repeat,\undefined} +% \DoNotIndex{\afterassignment,\aftergroup,\expandafter,\ignorespaces,\immediate,\noexpand,\protect,\relax,\space,\string,\the} +% \DoNotIndex{\hfil,\hfilneg,\hskip,\hss,\indent,\kern,\nobreak,\noindent,\nointerlineskip,\offinterlineskip,\par,\penalty,\strut,\thinspace,\vadjust,\vfil,\vfilneg,\vphantom,\vskip} +% \DoNotIndex{\@octets,\four,\three,\two,\UTFviii@,\UTFviii@zero@octets,\0,\1,\2,\3,\4,\5,\6,\7,\8,\9,\X,\O} +% +% +% \GetFileInfo{songs.dtx} +% +% \title{The \Songs\ package\thanks{This document corresponds to +% \textsf{songs}~\fileversion, dated~\filedate, +% \copyright~2012 Kevin W.~Hamlen, and +% distributed under version~2 the GNU General Public License +% as published by the Free Software Foundation.}} +% \author{Kevin W. Hamlen} +% +% \maketitle +% +% \begin{abstract} +% The \Songs\ 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. +% \end{abstract} +% +% \section{Introduction} +% +% The \Songs\ \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 \Songs\ 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. +% +% \section{Terms of Use} +% +% \noindent +% The \Songs\ 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 \S\ref{sec:license}. +% +% \medskip +% +% \noindent +% This program is distributed in the hope that it will be useful, +% but {\sc without any warranty}; without even the implied warranty of +% {\sc merchantability} or {\sc fitness for a particular purpose}. See the +% GNU General Public License in \S\ref{sec:license} 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. +% +% \medskip +% +% \noindent +% This software is copyright \copyright~2012 Kevin W.~Hamlen. +% For contact information or the latest version, see the project webpage at: +% +% \vskip1.5ex +% \begingroup\centering\noindent +% \href{http://songs.sourceforge.net}{{\tt http://songs.sourceforge.net}}\par +% \endgroup +% +% \section{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. +% +% \begin{verbatim} +% \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} +% \end{verbatim} +% +% To compile this book, execute three commands. +% First, use \LaTeX\ (|pdflatex| is recommended) to compile the document: +% +% \begin{codeblock} +% |pdflatex mybook.tex| +% \end{codeblock} +% +% \noindent +% (where |mybook.tex| is the name of the source document above). +% Next, use the |songidx| program provided with this distribution to +% generate the indexes: +% +% \begin{codeblock} +% |songidx titleidx.sxd titleidx.sbx| +% \end{codeblock} +% +% \noindent +% Finally, regenerate the document using \LaTeX\ so that the newly +% generated index data will be included: +% +% \begin{codeblock} +% |pdflatex mybook.tex| +% \end{codeblock} +% +% \noindent +% The final document is named |mybook.pdf| if you use |pdflatex| or +% |mybook.dvi| if you use regular |latex|. +% +% \begin{figure} +% \noindent\vbox{\begingroup\hsize=352pt +% \versesep=12pt\columnsep=7pt\parindent=20pt +% \def\colbotglue{0pt}\def\lastcolglue{0pt} +% \baselineadj=-1pt\relax +% \noversenumbers +% \setlength\textwidth{352pt} +% \setlength\textheight{498pt} +% \songcolumns{2} +% \vskip-3.5ex plus-1ex minus-.2ex +% \nointerlineskip\null\nointerlineskip +% \songsection*{Worship Songs} +% \begin{songs}{} +% \beginsong{Doxology}[ +% by={Louis Bourgeois and Thomas Ken}, +% sr={Revelation 5:13}, +% cr={Public domain.}] +% \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\eat\] +% \parindent=15pt +% \beginscripture{Psalm 18:2-6} +% \Acolon The LORD is my rock and my fortress and my deliverer, +% \Bcolon my God, my rock, in whom I take refuge, +% \Bcolon my shield, and the horn of my salvation, my stronghold. +% \Acolon I call upon the LORD, who is worthy to be praised, +% \Bcolon and I am saved from my enemies. +% \strophe +% \Acolon The cords of death encompassed me; +% \Bcolon the torrents of destruction assailed me; +% \Acolon the cords of Sheol entangled me; +% \Bcolon the snares of death confronted me. +% \strophe +% \Acolon In my distress I called upon the LORD; +% \Bcolon to my God I cried for help. +% \Acolon From his temple he heard my voice, +% \Bcolon and my cry to him reached his ears. +% \endscripture +% \parindent=20pt +% \beginsong{A Mighty Fortress Is Our God}[ +% by={Martin Luther}, +% cr={Public Domain.}] +% \beginverse +% A \[A]mighty \[C#m]Fortress \[B7]is our \[E]God, +% A \[D]bulwark \[A]never \[E7]fail\[A]ing. +% Our helper \[C#m]He, a\[B7]mid the \[E]flood +% Of \[D]mortal \[A]ills pre\[E7]vail\[A]ing. +% For still our \[B7sus4]an\[B7]cient \[E]foe +% Doth \[A]seek to \[E/G#]work us \[F#m]woe; +% His craft and \[B7]pow'r are \[E]great, +% And, \[Bm]armed with cruel \[C#]hate, +% On \[D]earth is \[A]not his \[E7]e\[A]qual. +% \endverse +% \beginverse +% Did ^we in ^our own ^strength con^fide, +% Our ^striving ^would be ^los^ing. +% Were not the ^right Man ^on our ^side, +% The ^Man of ^God's own ^choos^ing. +% Dost ask who ^that ^may ^be? +% Christ ^Jesus, ^it is ^He; +% Lord Saba^oth His ^Name, +% From ^age to age the ^same; +% And ^He must ^win the ^bat^tle. +% \endverse +% \endsong\eat\] +% \end{songs} +% \endgroup}\par +% \caption{Sample page from a chord book}\label{fig:sample} +% \end{figure} +% A copy of the first page of a sample song section is shown in +% Figure~\ref{fig:sample}. +% The page shown in that figure is from a chorded version of the book. +% When generating a lyric version, the chords are omitted. +% See \S\ref{sec:options} for information on how to generate different +% versions of the same book. +% +% \section{Initialization and Options}\label{sec:options} +% +% Each \LaTeX\ document that uses the \Songs\ package should contain a +% line like the following near the top of the document: +% +% \begin{codeblock} +% |\usepackage[|\meta{options}|]{songs}| +% \end{codeblock} +% +% \noindent +% Supported \meta{options} include the following: +% +% \paragraph{Output Type.} +% \DescEnv{lyric} +% \DescEnv{chorded} +% \DescEnv{slides} +% \DescEnv{rawtext} +% The \Songs\ 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 \mac{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 \meta{jobname}|.txt| +% (where \meta{jobname} is the root filename) containing lyrics without chords. +% This can be useful for importing song books into another program, such as a +% spell-checker. +% +% \DescMacro{chordson} +% \DescMacro{chordsoff} +% Chords can be turned on or off in the middle of the document +% by using the |\chordson| or |\chordsoff| macros. +% +% \DescMacro{slides} +% 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. +% +% \paragraph{Measure Bars.} +% \DescEnv{nomeasures} +% \DescEnv{showmeasures} +% \DescMacro{measureson} +% \DescMacro{measuresoff} +% The \Songs\ package includes a facility for placing measure bars in chord +% books (see \S\ref{sec:measures}). +% 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. +% +% \paragraph{Transposition.} +% \DescEnv{transposecapos} +% The |transposecapos| option changes the effect of the \mac{capo} macro. +% Normally, using |\capo{|\meta{n}|}| within a song environment produces a +% textual note in chord books that suggests the use of a guitar capo on fret +% \meta{n}. +% However, when the |transposecapos| option is active, these textual notes +% are omitted and instead the effect of |\capo{|\meta{n}|}| is the +% same as for \mac{transpose}|{|\meta{n}|}|. +% That is, chords between the \mac{capo} macro and the end of the song are +% automatically transposed up by \meta{n} 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 \S\ref{sec:notes} and \S\ref{sec:transpose} for more information on the +% \mac{capo} and \mac{transpose} macros. +% +% \paragraph{Indexes.} +% \DescEnv{noindexes} +% \DescMacro{indexeson} +% \DescMacro{indexesoff} +% 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. +% +% \DescEnv{nopdfindex} +% The |nopdfindex| option suppresses the creation of the pdf bookmark index +% that is normally included in |.pdf| files. +% If not generating a |.pdf| file, this option has no effect. +% +% \paragraph{Scripture Quotations.} +% \DescEnv{noscripture} +% \DescMacro{scriptureon} +% \DescMacro{scriptureoff} +% The |noscripture| option omits scripture quotations (see +% \S\ref{sec:scripture}) from the output. +% You can also turn scripture quotations on or off in the middle of the +% document by using |\scriptureon| or |\scriptureoff|, respectively. +% +% \paragraph{Shaded Boxes.} +% \DescEnv{noshading} +% 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. +% +% \paragraph{Partial Song Sets.} +% \DescMacro{includeonlysongs} +% 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{|\meta{songlist}|}| in the +% document preamble (i.e., before the |\begin{document}| line), where +% \meta{songlist} is a comma-separated list of the song numbers to include. +% For example, +% +% \begin{codeblock} +% |\includeonlysongs{37,50,2}| +% \end{codeblock} +% +% \noindent +% creates a document consisting only of songs 37, 50, and 2, in that order. +% +% Partial books generated with |\includeonlysongs| omit all scripture +% quotations (\S\ref{sec:scripture}), and ignore uses of +% \mac{nextcol}, \mac{brk}, \mac{sclearpage}, and \mac{scleardpage} +% between songs unless they are followed by a star (e.g., \mac{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 \meta{songlist}. +% +% The |\includeonlysongs| macro only reorders songs within each +% \env{songs} environment (see \S\ref{sec:songs}), not between different +% \env{songs} environments. +% It also cannot be used in conjunction with the \env{rawtext} option. +% +% \section{Book Sections}\label{sec:sections} +% +% \paragraph{Section Titles.} +% \DescMacro{songsection} +% \DescMacro{songchapter} +% Section titles in a song book can be produced with +% +% \begin{codeblock} +% |\songsection{|\meta{title}|}| +% \end{codeblock} +% +% \noindent +% which acts like \LaTeX's |\section| command except that it centers +% the \meta{title} text in sans serif font and omits the section number. +% When using the |book| document class, use |\songchapter| +% instead of |\songsection|. +% +% \paragraph{Indexes.} +% \DescMacro{newindex} +% \DescMacro{newauthorindex} +% \DescMacro{newscripindex} +% The \Songs\ 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: +% +% \begin{codeblock} +% |\newindex{|\meta{id}|}{|\meta{filename}|}| +% |\newauthorindex{|\meta{id}|}{|\meta{filename}|}| +% |\newscripindex{|\meta{id}|}{|\meta{filename}|}| +% \end{codeblock} +% +% \noindent +% The \meta{id} should be an alphabetic identifier that will be used to +% identify the index in other macros that reference it. +% The \meta{filename} should be a string that, when appended with an +% extension, constitutes a valid filename on the system. +% Auxiliary files named \meta{filename}|.sxd| and \meta{filename}|.sbx| +% are generated during the automatic index generation process. +% For example: +% +% \begin{codeblock} +% |\newindex{mainindex}{idxfile}| +% \end{codeblock} +% +% \noindent +% creates a title index named ``|mainindex|'' whose data is +% stored in files named |idxfile.sxd| and |idxfile.sbx|. +% +% \DescMacro{showindex} +% To display the index in the document, use: +% +% \begin{codeblock} +% |\showindex[|\meta{columns}|]{|\meta{title}|}{|\meta{id}|}| +% \end{codeblock} +% +% \noindent +% where \meta{id} is the same identifier used in the \mac{newindex}, +% \mac{newauthorindex}, or \mac{newscripindex} command, and where +% the \meta{title} 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 |[|\meta{columns}|]| 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: +% +% \begin{codeblock} +% |\showindex[2]{Index of Song Titles}{mainindex}| +% \end{codeblock} +% +% \section{Compiling}\label{sec: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: +% +% \begin{codeblock} +% |pdflatex mybook.tex| +% \end{codeblock} +% +% Second, use the |songidx| program to generate an index for each index that +% you declared with \mac{newindex}, \mac{newauthorindex}, or +% \mac{newscripindex}. +% The syntax of the |songidx| command is: +% +% \begin{codeblock} +% |songidx |[|-b| \meta{canon}|.can|] \meta{filename}|.sxd| \meta{filename}|.sbx| +% \end{codeblock} +% +% \noindent +% where \meta{filename} is the same \meta{filename} that was used in the +% \mac{newindex}, \mac{newauthorindex}, or \mac{newscripindex} macro. +% If the index was declared with \mac{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 \meta{canon} 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 +% +% \begin{codeblock} +% \mac{newindex}|{titleidx}{titlfile}| +% \mac{newauthorindex}|{authidx}{authfile}| +% \mac{newscripindex}|{scripidx}{scrpfile}| +% \end{codeblock} +% +% \noindent +% then the commands to generate indexes sorted according to a Christian +% English bible are: +% +% \begin{codeblock} +% |songidx titlfile.sxd titlfile.sbx| +% |songidx authfile.sxd authfile.sbx| +% |songidx -b bible.can scrpfile.sxd scrpfile.sbx| +% \end{codeblock} +% +% Once the indexes are generated, generate the final book by invoking +% \LaTeX\ one more time: +% +% \begin{codeblock} +% |pdflatex mybook.tex| +% \end{codeblock} +% +% \section{Songs}\label{sec:songs} +% +% \subsection{Beginning a Song} +% +% \paragraph{Song Sets.} +% \DescEnv{songs} +% Songs are contained within |songs| environments. +% Each |songs| environment begins and ends with: +% +% \begin{codeblock} +% |\begin{songs}{|\meta{indexes}|}| +% $\vdots$ +% |\end{songs}| +% \end{codeblock} +% +% \noindent +% \meta{indexes} is a comma-separated list of index identifiers +% (the \meta{id}'s specified with \mac{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 \S\ref{sec:between}). +% No text in a |songs| environment may lie outside of these environments. +% +% \paragraph{Songs.} +% \DescMacro{beginsong} +% \DescMacro{endsong} +% A song begins and ends with: +% +% \begin{codeblock} +% |\beginsong{|\meta{titles}|}[|\meta{otherinfo}|]| +% $\vdots$ +% |\endsong| +% \end{codeblock} +% +% \noindent +% Songs should appear only within \env{songs} environments (see above) +% unless you are supplying your own page-builder (see \S\ref{sec:layout}). +% +% In the \mac{beginsong} line, \meta{titles} 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 |[|\meta{otherinfo}|]| part is an optional comma-separated list of +% key-value pairs (keyvals) of the form \meta{key}|=|\meta{value}. +% The possible keys and their values are: +% +% \medskip +% \noindent\hfil\vbox{\halign{#\hfil&\kern2em{\it#}\hfil\cr +% |by={|\meta{authors}|}|&authors, composers, and other contributors\cr +% |cr={|\meta{copyright}|}|©right information\cr +% |li={|\meta{license}|}|&licensing information\cr +% |sr={|\meta{refs}|}|&related scripture references\cr +% |index={|\meta{lyrics}|}|&an extra index entry for a line of lyrics\cr +% |ititle={|\meta{title}|}|&an extra index entry for a hidden title\cr}} +% \medskip +% +% \noindent +% For example, a song that begins and ends with +% +% \begin{codeblock} +% |\beginsong{Title1 \\ Title2}[by={Joe Smith}, sr={Job 3},| +% | cr={\copyright~|\unskip\expandafter|\the\year|| XYZ.}, li={Used with permission.}]| +% |\endsong| +% \end{codeblock} +% +% \noindent looks like +% +% \begin{sample} +% \setcounter{songnum}{1}% +% \vskip1pt% +% \beginsong{Title1 \\ Title2}[by={Joe Smith}, sr={Job 3}, +% cr={\copyright~\the\year\ XYZ.}, li={Used with permission.}] +% \endsong +% \end{sample} +% +% The four keyvals used in the above example are described in detail in the +% remainder of this section; +% the final two are documented in \S\ref{sec:ientry}. +% You can also create your own keyvals (see \S\ref{sec:newkey}). +% +% \paragraph{Song Authors.} +% \DescEnv{by=} +% The |by={|\meta{authors}|}| keyval lists one or more authors, +% composers, translators, etc. +% An entry is added to each author index associated with the current +% \env{songs} environment for each contributor listed. +% Contributors are expected to be separated by commas, semicolons, or the +% word |and|. +% For example: +% +% \begin{codeblock} +% |by={Fred Smith, John Doe, and Billy Bob}| +% \end{codeblock} +% +% \noindent +% Words separated by a macro-space (\verb*@\ @\eat*) or tie (|~|) +% instead of a regular space are treated as single words by the indexer. +% For example, \verb*@The Vienna Boys' Choir@\eat* is indexed as +% ``Choir, The Vienna Boys'\thinspace'' but +% \verb*@The Vienna\ Boys'\ Choir@\eat* is indexed as +% ``Vienna Boys' Choir, The''. +% +% \paragraph{Copyright Info.} +% \DescEnv{cr=} +% The |cr={|\meta{copyright}|}| keyval specifies the copyright-holder of the +% song, if any. +% For example: +% +% \begin{codeblock} +% |cr={\copyright~2000 ABC Songs, Inc.}| +% \end{codeblock} +% +% \noindent +% Copyright information is typeset in fine print at the bottom of the song. +% +% \paragraph{Licensing Info.} +% \DescEnv{li=} +% \DescMacro{setlicense} +% Licensing information is provided by |li={|\meta{license}|}|, where +% \meta{license} is any text. +% Licensing information is displayed in fine print under the song just +% after the copyright information (if any). +% Alternatively, writing |\setlicense{|\meta{license}|}| anywhere between +% the \mac{beginsong} and \mac{endsong} lines is equivalent to using +% |li={|\meta{license}|}| in the \mac{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 +% +% \begin{codeblock} +% |\newcommand{\CCLI}{(CCLI \#1234567)}| +% \end{codeblock} +% +% \noindent +% Then you could write |li=\CCLI| in the \mac{beginsong} line of each song +% covered by CCLI. +% +% \paragraph{Scripture References.} +% \DescEnv{sr=} +% The \Songs\ package has extensive support for scripture citations and +% indexes of scripture citations. +% To cite scripture references for the song, use the keyval +% |sr={|\meta{refs}|}|, where \meta{refs} is a list of scripture +% references. +% Index entries are added to all scripture indexes associated +% with the current \env{songs} environment for each such reference. +% The |songidx| index generation program expects \meta{refs} 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 +% +% \begin{codeblock} +% |sr={John 3:16,17, 4:1-5; Jude 3}| +% \end{codeblock} +% +% The full formal syntax of a valid \meta{refs} argument is given in +% Figure~\ref{fig:srsyntax}. +% \begin{figure} +% \noindent\hfil\vbox{\advance\baselineskip2pt +% \halign{\hfil{\tt#}\,$\longrightarrow$\,&{\tt#}\hfil\cr +% \Meta{refs}&\Meta{nothing}\OR\Meta{ref};\SPC\Meta{ref};$\ldots$;\SPC\Meta{ref}\cr +% \Meta{ref}&\Meta{many-chptr-book}\SPC\Meta{chapters}\OR\Meta{one-chptr-book}\SPC\Meta{verses}\cr +% \Meta{many-chptr-book}&Genesis\OR Exodus\OR Leviticus\OR Numbers\OR $\ldots$\cr +% \Meta{one-chptr-book}&Obadiah\OR Philemon\OR 2 John\OR 3 John\OR Jude\cr +% \Meta{chapters}&\Meta{chref},\SPC\Meta{chref},$\ldots$,\SPC\Meta{chref}\cr +% \Meta{chref}&\Meta{chapter}\OR\Meta{chapter}-\Meta{chapter}\OR\Meta{chapter}:\Meta{verses}\OR\cr +% \omit&\quad\Meta{chapter}:\Meta{verse}-\Meta{chapter}:\Meta{verse}\cr +% \Meta{verses}&\Meta{vref},\Meta{vref},$\ldots$,\Meta{vref}\cr +% \Meta{vref}&\Meta{verse}\OR\Meta{verse}-\Meta{verse}\cr}} +% \caption{Formal syntax rules for song scripture references}\label{fig:srsyntax} +% \end{figure} +% In those syntax rules, \meta{chapter} and \meta{verse} 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:|\meta{verses}). +% +% \subsection{Verses and Choruses} +% +% \paragraph{Starting A Verse Or Chorus.} +% \DescMacro{beginverse} +% \DescMacro{endverse} +% \DescMacro{beginchorus} +% \DescMacro{endchorus} +% Between the \mac{beginsong} and \mac{endsong} lines of a song can +% appear any number of verses and choruses. +% A verse begins and ends with: +% +% \begin{codeblock} +% |\beginverse| +% $\vdots$ +% |\endverse| +% \end{codeblock} +% +% \noindent and a chorus begins and ends with: +% +% \begin{codeblock} +% |\beginchorus| +% $\vdots$ +% |\endchorus| +% \end{codeblock} +% +% \noindent +% Verses are numbered (unless \mac{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|. +% +% \paragraph{Repeating Choruses.} +% \DescMacro{repchoruses} +% When making overhead slides, it is often convenient to repeat the song's +% chorus after the first verse on each page, so that the projector-operator +% 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 \mac{beginverse}|*|). +% Unnumbered verses are assumed to be bridges or endings that aren't +% followed by a chorus. +% +% \DescMacro{norepchoruses} +% 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 the song where you want a chorus to be repeated on +% the overhead slides, type a construction like, +% +% \begin{codeblock} +% \mac{ifslides} +% \mac{beginchorus} +% $\vdots$ +% \mac{endchorus} +% |\fi| +% \end{codeblock} +% +% \noindent +% 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 +% +% \begin{codeblock} +% \mac{ifslides}\mac{repchoruses}|\fi| +% \end{codeblock} +% +% \noindent +% to turn automatic chorus-repeating back on, if desired. +% +% \subsection{Chords}\label{sec:chords} +% +% \DescMacro{[} +% \DescChar{hash}{#} +% \DescChar{amp}{&} +% Between the \mac{beginverse} and \mac{endverse} lines, or between +% the \mac{beginchorus} and \mac{endchorus} lines, +% chords can be produced using the macro |\[|\meta{chordname}|]|\eat\]. +% Chords only appear in chord books; they are omitted from lyric books. +% The \meta{chordname} may consist of arbitrary text. +% To produce sharp and flat symbols, use |#| and |&| respectively. +% +% Any text that immediately follows the |\[]|\eat\] 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: +% +% \example|\[E&]peace and \[Am]joy|\produces{\[E&]peace and \[Am]joy} +% \eat\] +% +% \noindent +% If whitespace (a space or \meta{return}) 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: +% +% \example|\[E&]peace and \[Am] joy|\produces{\[E&]peace and \[Am] joy} +% \eat\] +% +% 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: +% +% \example|\[F#sus4]e\[A]ternal|\produces{\[F#sus4]e\[A]ternal} +% \eat\] +% +% Sequences of chords that sit above a single word can be written +% back-to-back with no intervening space, or as a single chord: +% +% \example|\[A]\[B]\[Em]joy|\produces{\[A]\[B]\[Em]joy} +% \example|\[A B Em]joy|\produces{\[A B Em]joy} +% \eat\] +% +% \noindent +% The only difference between the two examples above is that the chords +% in the first example can later be replayed separately (see +% \S\ref{sec:replay}) 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: +% +% \example|{\[G A]e}ternal|\produces{{\[G A]e}ternal} +% \eat\] +% +% \noindent +% (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: +% +% \example|\[Gmaj7sus4]{th' eternal}|\produces{\[Gmaj7sus4]{th' eternal}} +% \eat\] +% +% \noindent +% 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'\thinspace''. +% +% \paragraph{Chords Without Lyrics.} +% \DescMacro{nolyrics} +% 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: +% +% \example|{\nolyrics Intro: \[G] \[A] \[D]}|\produces{\nolyrics Intro: \[G] \[A] \[D]} +% \eat\] +% +% \noindent +% 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 \mac{ifchorded} and |\fi| +% (see \S\ref{sec:conditionals}). +% +% \paragraph{Symbols Under Chords.} +% \DescMacro{DeclareLyricChar} +% 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 \Songs\ package to treat the symbol as +% non-chord-ending, so that it is included under chords by default just +% like an alphabetic character. +% +% \begin{codeblock} +% |\DeclareLyricChar{|\meta{token}|}| +% \end{codeblock} +% +% \noindent +% Here, \meta{token} 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, +% +% \example|\[Fmaj7]s\dag range|\produces{\[Fmaj7]s\dag range} +% \eat\] +% +% \noindent +% because |\dag| is not recognized as an alphabetic symbol; +% but if you first type, +% +% \begin{codeblock} +% |\DeclareLyricChar{\dag}| +% \end{codeblock} +% +% \noindent +% then instead you will get: +% +% \DeclareLyricChar{\dag} +% \example|\[Fmaj7]s\dag range|\produces{\[Fmaj7]s\dag range} +% \eat\] +% +% \noindent +% \DescMacro{DeclareNonLyric} +% Likewise, you can type +% +% \begin{codeblock} +% |\DeclareNonLyric{|\meta{token}|}| +% \end{codeblock} +% +% \noindent +% 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. +% +% \DescMacro{DeclareNoHyphen} +% To declare a token to be lyric-ending but without the added hyphenation, +% use |\DeclareNoHyphen{|\meta{token}|}| 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. +% +% \paragraph{Extending Chords Over Adjacent Words.} +% \DescMacro{MultiwordChords} +% 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: +% +% \example|\[Gmaj7sus4]my life|\produces{\[Gmaj7sus4]my life} +% \eat\] +% +% \noindent +% But if you first type |\MultiwordChords|, then instead you get the more +% compact: +% +% \begingroup\MultiwordChords +% \example|\[Gmaj7sus4]my life|\produces{\[Gmaj7sus4]my life} +% \eat\] +% \endgroup +% +% \noindent +% 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, +% +% \begingroup\MultiwordChords +% \example|\[F G Am]me free|\produces{\[F G Am]me free}\par +% \eat\] +% \endgroup +% +% \noindent +% 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. +% +% \paragraph{Accidentals Outside Chords.} +% \DescMacro{shrp} +% \DescMacro{flt} +% 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 \chord{C\shrp} chord, use: +% +% \begin{codeblock} +% |\newcommand{\Csharp}{C\shrp}| +% \end{codeblock} +% +% \subsection{Replaying Chords}\label{sec:replay} +% +% \DescChar{hat}{^} +% Many songs consist of multiple verses that use the same chords. +% The \Songs\ 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 (|\[]|\eat\]). +% For example, +% +% \begin{codeblock} +% \mac{beginverse} +% |\[G]This is the \[C]first \[G]verse.|\eat\] +% \mac{endverse} +% \mac{beginverse} +% |The ^second verse ^ has the same ^chords.| +% \mac{endverse} +% \end{codeblock} +% +% \noindent produces +% +% \begin{chorded}\memorize +% \[G]This is the \[C]first \[G]verse.\eat\] +% \end{chorded} +% \begin{chorded} +% The ^second verse ^ has the same ^chords. +% \end{chorded} +% +% Normal chords can appear amidst replayed chords without disrupting the +% sequence of chords being replayed. +% Thus, a third verse could say, +% +% \begin{codeblock} +% \mac{beginverse} +% |The ^third verse ^has a \[Cm]new ^chord.|\eat\] +% \mac{endverse} +% \end{codeblock} +% +% \noindent to produce +% +% \begin{chorded} +% The ^third verse ^has a \[Cm]new ^chord.\eat\] +% \end{chorded} +% +% Replaying can be used in combination with automatic transposition to produce +% modulated verses. +% See \S\ref{sec:transpose} for an example. +% +% \DescMacro{memorize} +% 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 \refchar{hat} replay chords +% from the most recently memorized verse or chorus. +% +% \paragraph{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, +% +% \begin{codeblock} +% \mac{beginverse}\mac{memorize} +% |The \[G]third \[C]chord will \[^Cm]not be re\[G]played.|\eat\] +% \mac{endverse} +% \mac{beginverse} +% |When ^replaying, the ^unmemorized chord is ^skipped.| +% \mac{endverse} +% \end{codeblock} +% +% \noindent produces +% +% \begin{chorded}\memorize +% The \[G]third \[C]chord will \[^Cm]not be re\[G]played.\eat\] +% \vskip5pt% +% When ^replaying, the ^unmemorized chord is ^skipped. +% \end{chorded} +% +% \noindent +% 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. +% +% \paragraph{Memorizing Multiple Chord Sequences.} +% By default, the \Songs\ package only memorizes one sequence of chords +% at a time and \refchar{hat} 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. +% +% \DescMacro{newchords} +% Memorized or replayed chord sequences are stored in chord-replay registers. +% To declare a new chord-replay register, type +% +% \begin{codeblock} +% |\newchords{|\meta{regname}|}| +% \end{codeblock} +% +% \noindent +% where \meta{regname} is any unique alphabetic name. +% +% Once you've declared a register, you can memorize into that register +% by providing the \meta{regname} as an optional argument to +% \mac{memorize}: +% +% \begin{codeblock} +% \mac{memorize}|[|\meta{regname}|]| +% \end{codeblock} +% +% \noindent +% Memorizing into a non-empty register replaces the contents of that +% register with the new chord sequence. +% +% \DescMacro{replay} +% To replay chord from a particular register, type +% +% \begin{codeblock} +% |\replay[|\meta{regname}|]| +% \end{codeblock} +% +% \noindent +% Subsequent uses of \refchar{hat} reproduce chords from the sequence +% stored in register \meta{regname}. +% +% 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. +% +% \subsection{Line and Column Breaks} +% +% \paragraph{Line Breaking.} +% \DescMacro{brk} +% 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, +% +% \begin{codeblock} +% |\beginverse| +% {\tt\frenchspacing This is a |\brk| short line. +% But this is a particularly long line of lyrics |\brk| that will need to be wrapped. +% } |\endverse| +% \end{codeblock} +% +% \noindent produces +% +% \begin{lyrics} +% This is a \brk short line. +% But this is a particularly long line of lyrics \brk that will need to be wrapped. +% \end{lyrics} +% +% \paragraph{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. +% +% \paragraph{Column Breaks Between Songs.} +% \DescMacro{nextcol} +% \DescMacro{sclearpage} +% \DescMacro{scleardpage} +% 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 \S\ref{sec:conditionals}. +% For example, +% +% \begin{codeblock} +% \mac{ifchorded}|\else|\mac{ifslides}|\else\brk\fi\fi| +% \end{codeblock} +% +% \noindent +% 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 \mac{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 \mac{includeonlysongs}. +% +% \subsection{Echoes and Repeats} +% +% \paragraph{Echo Parts.} +% \DescMacro{echo} +% To typeset an echo part, use |\echo{|\meta{lyrics and chords}|}|. +% Echo parts are parenthesized and italicized. +% For example, +% +% \example|Alle\[G]luia! \echo{Alle\[A]luia!}|\produces{Alle\[G]luia! \echo{Alle\[A]luia!}} +% \eat\] +% +% \paragraph{Repeated Lines.} +% \DescMacro{rep} +% To indicate that a line should be sung multiple times by all singers, put +% |\rep{|\meta{n}|}| at the end of the line. +% For example, +% +% \example|Alleluia! \rep{4}|\produces{Alleluia! \rep{4}} +% +% \DescMacro{lrep} +% \DescMacro{rrep} +% To indicate exactly where repeated parts begin and end, use |\lrep| and +% |\rrep| to create begin- and end-repeat signs. +% For example, +% +% \example|\lrep \[G]Alleluia!\rrep \rep{4}|\produces{\lrep \[G]Alleluia!\rrep \rep{4}} +% \eat\] +% +% \subsection{Measure Bars}\label{sec:measures} +% +% \DescMacro{measurebar} +% \DescChar{pipe}{|} +% 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 (``\verb@|@''). +% For example, +% +% \example\verb@Alle|\[G]luia@\produces{Alle\meter{}{}\measurebar\[G]luia} +% \eat\] +% +% \noindent +% In order for measure bars to be displayed, the \env{showmeasures} +% option must be enabled. +% Measure bars are only displayed by default in chord books. +% +% \DescMacro{meter} +% 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{|\meta{n}|}{|\meta{d}|}| +% somewhere after the \mac{beginsong} line of the song but before the +% first measure bar, to declare a time signature of \meta{n} \meta{d}th +% notes per measure. +% +% \DescMacro{mbar} +% You can also change meters mid-song either by using |\meter| in the +% middle of the song or by typing |\mbar{|\meta{n}|}{|\meta{d}|}| +% to produce a measure bar with a time signature of \meta{n}/\meta{d}. +% For example, +% +% \begin{codeblock} +% |\meter{6}{8}| +% |\beginverse| +% \verb@|Sing to the |heavens, ye \mbar{4}{4}saints of |old!@ +% |\endverse| +% \end{codeblock} +% +% \noindent produces +% +% \begin{chorded} +% \meter{6}{8}% +% \measurebar Sing to the \measurebar heavens, ye \mbar{4}{4}saints of \measurebar old! +% \end{chorded} +% +% \subsection{Textual Notes}\label{sec:notes} +% +% \DescMacro{textnote} +% \DescMacro{musicnote} +% 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: +% +% \begin{codeblock} +% |\textnote{|\meta{text}|}| +% \end{codeblock} +% +% \noindent +% To create a textual note that is displayed only in chord books, use: +% +% \begin{codeblock} +% |\musicnote{|\meta{text}|}| +% \end{codeblock} +% +% \noindent +% Both of these create a shaded box containing \meta{text}. +% For example, +% +% \begin{codeblock} +% |\textnote{Sing as a two-part round.}| +% \end{codeblock} +% +% \noindent produces +% +% \begin{lyrics} +% \textnote{Sing as a two-part round.} +% \end{lyrics} +% +% \noindent +% Textual notes can be placed anywhere within a song, either within +% verses and choruses or between them. +% +% \paragraph{Guitar Capos.} +% \DescMacro{capo} +% One special kind of textual note suggests to guitarists a fret on which +% they should put their capos. +% Macro |\capo{|\meta{n}|}| should be used for this purpose. +% It normally has the same effect as \mac{musicnote}|{capo |\meta{n}|}|; +% however, if the \env{transposecapos} option is active then it +% instead has the effect of \mac{transpose}|{|\meta{n}|}|. +% See \S\ref{sec:transpose} for more information on automatic chord +% transposition. +% +% \subsection{Index Entries}\label{sec:ientry} +% +% 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. +% +% \paragraph{Indexing Lyrics.} +% \DescEnv{index=} +% 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={|\meta{lyrics}|}| to the song's +% \mac{beginsong} line. +% For example, +% +% \begin{codeblock} +% \mac{beginsong}|{Doxology}| +% | [index={Praise God from Whom all blessings flow}]| +% \end{codeblock} +% +% \noindent +% causes the song to be indexed both as ``\textit{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 \mac{beginsong} line to produce +% multiple additional index entries. +% Index entries produced with |index={|\meta{lyrics}|}| are +% typeset in an upright font instead of in italics to distinguish +% them from song titles. +% +% \paragraph{Indexing Extra Song Titles.} +% \DescEnv{ititle=} +% To add a regular index entry typeset in italics to the title +% index(es), use: +% +% \begin{codeblock} +% |ititle={|\meta{title}|}| +% \end{codeblock} +% +% \noindent +% in the \mac{beginsong} line instead. +% Like \env{index=} keyvals, |ititle=| can be used multiple times to produce +% multiple additional index entries. +% +% \DescMacro{indexentry} +% \DescMacro{indextitleentry} +% You can also create index entries by saying +% |\indexentry[|\meta{indexes}|]{|\meta{lyrics}|}| (which creates an +% entry like \env{index=}) or +% |\indextitleentry[|\meta{indexes}|]{|\meta{title}|}| (which +% creates an entry like \env{ititle=}). +% These two macros can be used anywhere between the song's \mac{beginsong} +% and \mac{endsong} lines, and can be used multiple times to produce +% multiple entries. +% If specified, \meta{indexes} 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 +% \env{songs} environment. +% +% \subsection{Chords in Ligatures} +% +% This subsection covers an advanced topic and can probably be +% skipped by those creating song books for non-professional use. +% +% The \mac{[\eat]} 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 \ae\ and \oe. +% Notice that in each of these cases, the letters are ``squished'' +% together to form a single composite symbol. +% +% \DescMacro{ch} +% 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 typograhpical error, use the |\ch| macro to typeset +% the chord: +% +% \begin{codeblock} +% |\ch{|\meta{chord}|}{|\meta{pre}|}{|\meta{post}|}{|\meta{full}|}| +% \end{codeblock} +% +% \noindent +% where \meta{chord} is the chord text, \meta{pre} is the text to +% appear before the hyphen if the ligature is broken by auto-hyphenation, +% \meta{post} is the text to appear after the hyphen if the ligature +% is broken by auto-hyphenation, and \meta{full} is the full ligature +% if it is not broken by hyphenation. +% For example, to correctly typeset |\[Gsus4]dif\[G]ficult|\eat\], +% in which the \chord{G} chord falls in the middle of the ``ffi'' +% ligature, one should use: +% +% \example|di\ch{G}{f}{fi}{ffi}cult|\produces{di\ch{G}{f}{fi}{ffi}cult} +% +% \noindent +% This causes the ``ffi'' ligature to appear intact yet still correctly +% places the \chord{G} chord over the second f. +% To use the |\ch| macro with a replayed chord name (see \S\ref{sec:replay}), +% use |^| as the \meta{chord}. +% +% \DescMacro{mch} +% The |\mch| macro is exactly like the \mac{ch} macro except that it +% also places a measure bar into the ligature along with the chord. +% For example, +% +% \example|di\mch{G}{f}{fi}{ffi}cult|\produces{di\mch{G}{f}{fi}{ffi}cult} +% +% \noindent +% places both a measure bar and a \chord{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: +% +% \example|\meter{6}{8}di\mch{G}{f}{fi}{ffi}cult|\produces{\meter{6}{8}di\mch{G}{f}{fi}{ffi}cult} +% +% \noindent +% The \mac{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 \refchar{hat} or +% \refchar{pipe} are safe to use in ligatures. +% Thus, |dif|\refchar{pipe}\refchar{hat}|ficult| requires +% no special treatment; it leaves the ``ffi'' ligature intact when measure +% bars are not being displayed. +% +% \section{Between Songs}\label{sec:between} +% +% Never put any material directly into the top level of a \env{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. +% +% \subsection{Intersong Displays}\label{sec:intersong} +% +% \DescEnv{intersong} +% To put column-width material between the songs in a \env{songs} environment, +% use an |intersong| environment: +% +% \begin{codeblock} +% |\begin{intersong}| +% $\vdots$ +% |\end{intersong}| +% \end{codeblock} +% +% \noindent +% Material contributed in an |intersong| environment is subject to the same +% column-breaking rules as songs (see \S\ref{sec:layout}), 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|. +% +% \DescEnv{intersong*} +% To instead put page-width material above a song, use an |intersong*| +% environment: +% +% \begin{codeblock} +% |\begin{intersong*}| +% $\vdots$ +% |\end{intersong*}| +% \end{codeblock} +% +% \noindent +% This starts a new page if the current page already has column-width +% material in it. +% +% \DescEnv{songgroup} +% By default, all intersong displays are omitted when generating a partial +% book with \mac{includeonlysongs}. +% You can force them to be included whenever a particular song is included +% by using a |songgroup| environment: +% +% \begin{codeblock} +% |\begin{songgroup}| +% $\vdots$ +% |\end{songgroup}| +% \end{codeblock} +% +% \noindent +% Each |songgroup| environment may include any number of \env{intersong}, +% \env{intersong*}, or scripture quotations (see \S\ref{sec:scripture}), +% but must include exactly one song. +% When using \mac{includeonlysongs}, the entire group is included in the +% book if the enclosed song is included; otherwise the entire group is +% omitted. +% +% \subsection{Scripture Quotations}\label{sec:scripture} +% +% \paragraph{Starting a Scripture Quotation.} +% \DescMacro{beginscripture} +% \DescMacro{endscripture} +% A special form of intersong block typesets a scripture quotation. +% Scripture quotations begin and end with +% +% \begin{codeblock} +% |\beginscripture{|\meta{ref}|}| +% $\vdots$ +% |\endscripture| +% \end{codeblock} +% +% \noindent +% where \meta{ref} is a scripture reference that is +% typeset at the end of the quotation. +% The \meta{ref} argument should conform to the same syntax +% rules as for the \meta{ref} arguments passed to \mac{beginsong} +% macros (see \S\ref{sec:songs}). +% +% The text of the scripture quotation between the |\beginscripture| and +% |\endscripture| lines are parsed in normal paragraph mode. +% For example: +% +% \begin{codeblock} +% |\beginscripture{James 5:13}| +% {\tt\frenchspacing% +% Is any one of you in trouble? He should pray. Is anyone happy? Let him sing songs of praise. +% } |\endscripture| +% \end{codeblock} +% +% \noindent produces +% +% \begin{sample} +% \beginscripture{James 5:13} +% Is any one of you in trouble? He should pray. Is anyone happy? Let him sing songs of praise. +% \endscripture +% \end{sample} +% +% \paragraph{Tuplets.} +% \DescMacro{Acolon} +% \DescMacro{Bcolon} +% 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, +% +% \begin{codeblock} +% |\beginscripture{Psalm 1:1}| +% {\tt\frenchspacing% +% |\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| +% \end{codeblock} +% +% \noindent produces +% +% \begin{sample} +% \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 +% \end{sample} +% +% \paragraph{Stanzas.} +% \DescMacro{strophe} +% 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, +% +% \begin{codeblock} +% |\beginscripture{Psalm 88:2-3}| +% {\tt\frenchspacing% +% |\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| +% \end{codeblock} +% +% \noindent produces +% +% \begin{sample} +% \beginscripture{Psalm 88:2-3} +% \Acolon May my prayer come before you;\par +% \Bcolon turn your ear to my cry.\par +% \strophe +% \Acolon For my soul is full of trouble\par +% \Bcolon and my life draws near the grave. +% \endscripture +% \end{sample} +% +% \paragraph{Indented Blocks.} +% \DescMacro{scripindent} +% \DescMacro{scripoutdent} +% 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, +% +% \begin{codeblock} +% |\beginscripture{Hebrews 10:17-18}| +% {\tt\frenchspacing% +% 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| +% \end{codeblock} +% +% \noindent produces +% +% \begin{sample} +% \beginscripture{Hebrews 10:17-18} +% Then he adds:\par +% \scripindent +% \Acolon ``Their sins and lawless acts\par +% \Bcolon I will remember no more.''\par +% \scripoutdent +% And where these have been forgiven, there is no longer any sacrifice for sin. +% \endscripture +% \end{sample} +% +% \section{Guitar Tablatures}\label{sec:tablatures} +% +% \DescMacro{gtab} +% Guitar tablature diagrams can be created by using the construct +% +% \begin{codeblock} +% |\gtab{|\meta{chord}|}{|\meta{fret}|:|\meta{strings}|:|\meta{fingering}|}| +% \end{codeblock} +% +% \noindent +% where the \meta{fret} and \meta{fingering} parts are both optional +% (and you may omit any colon that borders an omitted argument). +% +% \meta{chord} is a chord name to be placed above the diagram. +% +% \meta{fret} is an optional digit (any number from 2 to 9) placed to the +% left of the diagram. +% +% \meta{strings} 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. +% +% \meta{fingering} 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: +% +% \example|\gtab{A}{X02220:001230}|\produces{\vcenterbox{\gtab{A}{{\hphantom{4}}:X02220:001230}}} +% \example|\gtab{C#sus4}{4:XX3341}|\produces{\vcenterbox{\gtab{C\shrp sus4}{4:XX3341}}} +% \example|\gtab{B&}{X13331}|\produces{\vcenterbox{\gtab{B\flt}{{\hphantom{4}}:X13331:}}} +% +% \DescMacro{minfrets} +% By default, tablature diagrams always consist of at least 4 fret rows +% (more if the \meta{strings} argument contains a number larger than 4). +% To change the minimum number of fret rows, change the value of |\minfrets|. +% For example, typing +% +% \begin{codeblock} +% |\minfrets=1| +% \end{codeblock} +% +% \noindent +% causes tablature diagrams to have only as many rows are required to +% accommodate the largest digit appearing in the \meta{strings} argument. +% +% \section{Automatic Transposition}\label{sec:transpose} +% +% \DescMacro{transpose} +% You can automatically transpose some or all of the chords in a song up by +% \meta{n} half-steps by adding the line +% +% \begin{codeblock} +% |\transpose{|\meta{n}|}| +% \end{codeblock} +% +% \noindent +% somewhere between the song's \mac{beginsong} line and the first chord to +% be transposed. +% For example, if a song's first chord is |\[D]|\eat\], and the line +% |\transpose{2}| appears before it, then the chord appears as an +% \chord{E} in the resulting document. +% Specifying a negative number for \meta{n} transposes subsequent chords +% down instead of up. +% +% The |\transpose| macro affects all chords appearing after it until the +% \mac{endsong} line. +% If two |\transpose| macros appear in the same song, their effects are +% cumulative. +% +% When the \env{transposecapos} option is active, the \mac{capo} +% macro acts like |\transpose|. +% See \S\ref{sec:notes} for more information. +% +% \paragraph{Enharmonics.} +% \DescMacro{preferflats} +% \DescMacro{prefersharps} +% When using \mac{transpose} to automatically transpose the chords of a song, +% the \Songs\ 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 \chord{E}, then all \chord{A} chords that appear in +% the song are transcribed as \chord{B\flt} chords rather than +% \chord{A\shrp} chords, since the key of \chord{F}-major (\chord{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 \mac{transpose} line +% to force all transcription to use flatted names or sharped names +% respectively, when resolving enharmonic equivalents. +% +% \paragraph{Modulated Verses.} +% Automatic transposition can be used in conjunction with chord-replaying +% (see \S\ref{sec:chords}) to produce modulated verses. +% For example, +% +% \begin{codeblock} +% \mac{beginverse}\mac{memorize} +% |\[F#]This is a \[B/F#]memorized \[F#]verse. \[E&7]|\eat\] +% \mac{endverse} +% \mac{transpose}|{2}| +% \mac{beginverse} +% |^This verse is ^modulated up two ^half-steps.| +% \mac{endverse} +% \end{codeblock} +% +% \noindent produces +% +% \begin{chorded}\memorize +% \[F#]This is a \[B/F#]memorized \[F#]verse. \[E&7]\eat\] +% \vskip5pt\replay\transpose{2}% +% ^This verse is ^modulated up two ^half-steps. +% \transpose{-2}% +% \end{chorded} +% +% \paragraph{Both Keys.} +% \DescMacro{trchordformat} +% By default, when chords are automatically transposed using \mac{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| 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 +% +% \begin{codeblock} +% |\renewcommand{\trchordformat}[2]{\vbox{\hbox{#1}\hbox{#2}}}| +% \end{codeblock} +% +% \paragraph{Changing Note Names.} +% \DescMacro{solfedge} +% \DescMacro{alphascale} +% In many countries it is common to use the solfedge names for the notes of +% the scale (\chord{LA, SI, DO, RE, MI, FA, SOL\/}) instead of the +% alphabetic names (\chord{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|. +% +% \DescMacro{notenames} +% You can use other note names as well. +% To define your own note names, type +% +% \begin{codeblock} +% |\notenames{|\meta{nameA}|}{|\meta{nameB}|}|$\ldots$|{|\meta{nameG}|}| +% \end{codeblock} +% +% \noindent +% where each of \meta{nameA} through \meta{nameG} must consist entirely of +% a sequence of one or more \emph{uppercase} letters. +% For example, some solfedge musicians use \chord{TI} instead of \chord{SI} +% for the second note of the scale. +% To automatically transpose such music, use: +% +% \begin{codeblock} +% |\notenames{LA}{TI}{DO}{RE}{MI}{FA}{SOL}| +% \end{codeblock} +% +% \DescMacro{notenamesin} +% \DescMacro{notenamesout} +% The \Songs\ 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 +% \Songs\ package which note names you typed in the input file, and then +% using |\notenamesout| to tell the \Songs\ package how you want it to +% typeset each note name in the output file. +% The final code looks like this: +% +% \begin{codeblock} +% |\notenamesin{A}{B}{C}{D}{E}{F}{G}| +% |\notenamesout{LA}{SI}{DO}{RE}{MI}{FA}{SOL}| +% \end{codeblock} +% +% \noindent +% The syntaxes of |\notenamesin| and |\notenamesout| are identical to that +% of \mac{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 \mac{alphascale}, \mac{solfedge}, +% or \mac{notenames} to reset all note names back to identical input and +% output scales. +% +% \paragraph{Transposing Chords In Macros.} +% \DescMacro{transposehere} +% The automatic transposition logic won't find chord names that are hidden +% inside macro bodies. +% For example, if you abbreviate a chord by typing, +% +% \begin{codeblock} +% |\newcommand{\mychord}{F|\mac{shrp}| sus4/C|\mac{shrp}|}| +% \mac{transpose}|{4}| +% |\[\mychord]|\eat\] +% \end{codeblock} +% +% \noindent +% then the \mac{transpose} macro fails to transpose it; the +% resulting chord is still an \chord{F\shrp sus4/C\shrp} 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: +% +% \begin{codeblock} +% |\newcommand{\mychord}{\transposehere{F|\mac{shrp}| sus4/C|\mac{shrp}|}}| +% \end{codeblock} +% +% \DescMacro{notrans} +% Transposition can be suppressed within material that would otherwise be +% transposed by using the |\notrans| macro. +% For example, writing +% +% \begin{codeblock} +% \mac{transposehere}|{G = \notrans{G}}| +% \end{codeblock} +% +% \noindent +% would typeset a transposed \chord{G} followed by a non-transposed +% \chord{G} chord. +% This does not suppress note name conversion (see \mac{notenames}). +% To suppress both transposition and note name conversion, just use +% braces (e.g., |{G}| instead of |\notrans{G}|). +% +% \paragraph{Transposing Guitar Tablatures.} +% \DescMacro{gtabtrans} +% The songs package cannot automatically transpose tablature diagrams +% (see \S\ref{sec:tablatures}). +% Therefore, when automatic transposition is taking place, only the chord +% names of \mac{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 \mac{gtab}. +% For example, to display original tablatures without transposing them even +% when transposition has been turned on, write +% +% \begin{codeblock} +% |\renewcommand{\gtabtrans}[2]{|\mac{gtab}|{|\mac{notrans}|{#1}}{#2}}| +% \end{codeblock} +% +% \noindent +% To transpose the chord name but not the diagram under it, replace +% \mac{notrans}|{#1}| with simply |#1| in the above. +% To restore the default behavior, write +% +% \begin{codeblock} +% |\renewcommand{\gtabtrans}[2]{|\mac{transposehere}|{#1}}| +% \end{codeblock} +% +% \section{Customizing the Book} +% +% \subsection{Song and Verse Numbering}\label{sec:numbering} +% +% \paragraph{Song Numbering.} +% \DescEnv{songnum} +% The |songnum| counter defines the next song's number. +% It is set to 1 at the beginning of a \env{songs} environment and is +% increased by 1 after each \mac{endsong}. +% It can be redefined anywhere except within a song. +% For example, +% +% \begin{codeblock} +% |\setcounter{songnum}{3}| +% \end{codeblock} +% +% \noindent sets the next song's number to be 3. +% +% \DescMacro{thesongnum} +% 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 +% +% \begin{codeblock} +% |\renewcommand{\thesongnum}{A\arabic{songnum}}| +% \end{codeblock} +% +% \noindent +% 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. +% +% \DescMacro{printsongnum} +% 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 \mac{thesongnum} as its only argument. +% For example, to typeset song numbers in italics atop each song, define +% +% \begin{codeblock} +% |\renewcommand{\printsongnum}[1]{\it\LARGE#1}| +% \end{codeblock} +% +% \DescMacro{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 +% +% \begin{codeblock} +% |\setlength{\songnumwidth}{2cm}| +% \end{codeblock} +% +% \noindent +% If |\songnumwidth| is set to zero, song numbers are not shown at all. +% +% \DescMacro{nosongnumbers} +% 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 \mac{songnumwidth} to zero. +% +% \paragraph{Verse Numbering.} +% \DescEnv{versenum} +% The |versenum| counter defines the next verse's number. +% It is set to 1 after each \mac{beginsong} line and is increased by 1 after +% each \mac{endverse} (except if the verse begins with \mac{beginverse}|*|). +% The |versenum| counter can be redefined anywhere within a song. +% For example, +% +% \begin{codeblock} +% |\setcounter{versenum}{3}| +% \end{codeblock} +% +% \noindent sets the next verse's number to be 3. +% +% \DescMacro{theversenum} +% You can change the verse numbering style by redefining |\theversenum|. +% For example, to cause verses to be numbered in uppercase roman numerals, +% define +% +% \begin{codeblock} +% |\renewcommand{\theversenum}{\Roman{versenum}}| +% \end{codeblock} +% +% \DescMacro{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 \mac{theversenum} as its only argument. +% For example, to typeset verse numbers in italics, define +% +% \begin{codeblock} +% |\renewcommand{\printversenum}[1]{\it\LARGE#1.\ }| +% \end{codeblock} +% +% \DescMacro{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 +% +% \begin{codeblock} +% |\setlength{\versenumwidth}{0.5cm}| +% \end{codeblock} +% +% 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|. +% +% \DescMacro{noversenumbers} +% To turn off verse numbering entirely, use |\noversenumbers|. +% This is equivalent to saying +% +% \begin{codeblock} +% |\renewcommand{|\mac{printversenum}|}[1]{}| +% |\setlength{\versenumwidth}{0pt}| +% \end{codeblock} +% +% \DescMacro{placeversenum} +% 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. +% \ImplOrDesc +% {Authors interested in changing the placement of verse numbers should +% consult \S\ref{sec:impparams} of the implementation section for more +% information on this macro.} +% {For more information on this macro, recompile this documentation with +% the implementation section included.} +% +% \subsection{Song Appearance} +% +% \paragraph{Font Selection.} +% \DescMacro{lyricfont} +% 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 +% +% \begin{codeblock} +% |\renewcommand{\lyricfont}{\sffamily\small}| +% \end{codeblock} +% +% \DescMacro{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 +% +% \begin{codeblock} +% |\renewcommand{\stitlefont}{\rmfont\Large}| +% \end{codeblock} +% +% \DescMacro{versefont} +% \DescMacro{chorusfont} +% \DescMacro{notefont} +% You can apply additional font changes to verses, choruses, and +% textual notes produced with \mac{textnote} and \mac{musicnote} by +% redefining |\versefont|, |\chorusfont|, and |\notefont|, respectively. +% For example, to typeset choruses in italics, you could define +% +% \begin{codeblock} +% |\renewcommand{\chorusfont}{\it}| +% \end{codeblock} +% +% \DescMacro{notebgcolor} +% \DescMacro{snumbgcolor} +% The colors of shaded boxes containing textual notes and song numbers +% can be changed by redefining the |\notebgcolor| and |\snumbgcolor| +% macros. +% For example: +% +% \begin{codeblock} +% |\renewcommand{\notebgcolor}{red}| +% \end{codeblock} +% +% \DescMacro{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 +% +% \begin{codeblock} +% |\renewcommand{\printchord}[1]{\rmfamily\bf#1}| +% \end{codeblock} +% +% \paragraph{Accidental Symbols.} +% \DescMacro{sharpsymbol} +% \DescMacro{flatsymbol} +% By default, sharp and flat symbols are typeset using \LaTeX's +% |\#| ($\#$) and |\flat| ($\flat$) macros. +% Users can change this by redefining |\sharpsymbol| and |\flatsymbol|. +% For example, to use |\sharp| ($\sharp$) instead of $\#$, one could +% redefine |\sharpsymbol| as follows. +% +% \begin{codeblock} +% |\renewcommand{\sharpsymbol}{\ensuremath{^\sharp}}| +% \end{codeblock} +% +% \paragraph{Verse and Chorus Titles.} +% \DescMacro{everyverse} +% \DescMacro{everychorus} +% 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, +% +% \begin{codeblock} +% |\renewcommand{\everychorus}{|\mac{textnote}|{Chorus:}}| +% \end{codeblock} +% +% \paragraph{Spacing Options.} +% \DescMacro{versesep} +% 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 +% +% \begin{codeblock} +% |\versesep=12pt plus 2pt minus 2pt| +% \end{codeblock} +% +% \DescMacro{afterpreludeskip} +% \DescMacro{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: +% +% \begin{codeblock} +% \mac{songcolumns}|{1}| +% \mac{spenalty}|=-10000| +% |\afterpreludeskip=2pt plus 1fil| +% |\beforepostludeskip=2pt plus 1fil| +% \end{codeblock} +% +% \DescMacro{baselineadj} +% The vertical distance between the baselines of consecutive lines of +% lyrics is computed by the \Songs\ package based on several factors +% including the lyric font size, the chord font size (if in \env{chorded} +% mode), and whether \env{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 +% +% \begin{codeblock} +% |\baselineadj=-1pt plus 1pt minus 0pt| +% \end{codeblock} +% +% \DescMacro{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: +% +% \begin{codeblock} +% |\renewcommand{\clineparams}{| +% | \baselineskip=12pt| +% | \lineskiplimit=1pt| +% | \lineskip=1pt| +% |}| +% \end{codeblock} +% +% \DescMacro{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|: +% +% \begin{codeblock} +% |\setlength{\cbarwidth}{0pt}| +% \end{codeblock} +% +% \DescMacro{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|: +% +% \begin{codeblock} +% |\setlength{\sbarheight}{0pt}| +% \end{codeblock} +% +% \paragraph{Song Top and Bottom Material.} +% You can adjust the header and footer material that precedes and concludes +% each song by redefining |\extendprelude| and |\extendpostlude|. +% +% \DescMacro{extendprelude} +% \DescMacro{showauthors} +% \DescMacro{showrefs} +% 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: +% +% \begin{codeblock} +% |\renewcommand{\extendprelude}{| +% | |\mac{showrefs}\mac{showauthors} +% | {\bfseries|\mac{songcopyright}|\par}| +% |}| +% \end{codeblock} +% +% \DescMacro{extendpostlude} +% By default, |\extendpostlude| prints the song's copyright and licensing +% information as a single paragraph using \mac{songcopyright} and +% \mac{songlicense}. +% The following definition changes it to also print the words +% ``Used with permission'' at the end of every song's footer information: +% +% \begin{codeblock} +% |\renewcommand{\extendpostlude}{| +% | |\mac{songcopyright}|\ |\mac{songlicense}|\unskip| +% | \ Used with permission.| +% |}| +% \end{codeblock} +% +% In general, any macro documented in \S\ref{sec:songinfo} can be used +% in |\extendprelude| and |\extendpostlude| to print song information, such +% as \mac{songauthors}, \mac{songrefs}, \mac{songcopyright}, and +% \mac{songlicense}. +% For convenience, the \mac{showauthors} and \mac{showrefs} macros display +% author and scripture reference information as a pre-formatted paragraph +% the way it appears in the default song header blocks. +% +% See \S\ref{sec:newkey} for how to define new \mac{beginsong} keyvals and +% use them in |\extendprelude|. +% +% \DescMacro{makeprelude} +% \DescMacro{makepostlude} +% 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 \Songs\ package code invokes both of these +% macros once (after processing all the material between the \mac{beginsong} +% and \mac{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. +% +% \paragraph{Page- and Column-breaking.} +% \DescMacro{vvpenalty} +% \DescMacro{ccpenalty} +% \DescMacro{vcpenalty} +% \DescMacro{cvpenalty} +% \DescMacro{brkpenalty} +% 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 \mac{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 $-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. +% +% \DescMacro{sepverses} +% Saying |\sepverses| sets all of the above penalties to $-10000$ except for +% |\ccpenalty| which is set to 100. +% This is useful in \env{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 +% +% \begin{codeblock} +% |\ccpenalty=-10000| +% \end{codeblock} +% +% \paragraph{Text Justification.} +% \DescMacro{versejustify} +% \DescMacro{chorusjustify} +% \DescMacro{justifyleft} +% \DescMacro{justifycenter} +% To cause verse or chorus text to be justified flush-left or centered, set +% |\versejustify| or |\chorusjustify| to |\justifyleft| or |\justifycenter|, +% respectively. +% For example, to cause choruses to be centered, one could type: +% +% \begin{codeblock} +% |\renewcommand{|\mac{chorusjustify}|}{\justifycenter}| +% \end{codeblock} +% +% \DescMacro{notejustify} +% 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). +% \ImplOrDesc +% {Authors interested in changing this behavior should consult +% \S\ref{sec:impparams} of the implementation section for more +% information about this macro.} +% {For more information, recompile this documentation with the +% implementation section included.} +% +% \DescMacro{placenote} +% 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|. +% \ImplOrDesc +% {Authors interested in changing this behavior should consult +% \S\ref{sec:impparams} of the implementation section for more +% information about this macro.} +% {For more information, recompile this documentation with the +% implementation section included.} +% +% \subsection{Scripture Appearance} +% +% \DescMacro{scripturefont} +% 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: +% +% \begin{codeblock} +% |\renewcommand{\scripturefont}{\sffamily\it}| +% \end{codeblock} +% +% \DescMacro{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: +% +% \begin{codeblock} +% |\renewcommand{\printscrcite}[1]{\rmfamily\it#1}| +% \end{codeblock} +% +% \subsection{Conditional Blocks}\label{sec:conditionals} +% +% 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. +% +% \DescMacroGroup{if}{if...}{ifchorded,iflyric,ifslides,ifpartiallist,ifsongindexes,ifmeasures,ifpdfindex,ifrawtext,iftranscapos,ifnolyrics,ifvnumbered} +% A conditional block begins with a macro named |\if|\meta{type}, where +% \meta{type} is one of the types listed in the first column of +% Table~\ref{tab:conditionals}. +% \begin{table} +% \newcommand\tablerule{\noalign{\hrule}} +% \newskip\oldbaselineskip \oldbaselineskip\baselineskip +% \newskip\oldlineskip \oldlineskip\lineskip +% \newdimen\oldlineskiplimit \oldlineskiplimit\lineskiplimit +% \newcommand\oninterlineskip{% +% \baselineskip\oldbaselineskip +% \lineskip\oldlineskip +% \lineskiplimit\oldlineskiplimit} +% \vbox{\offinterlineskip\hrule +% \halign{&\vrule#&\strut\quad#\hfil\quad&\vrule#&\quad\vtop{\oninterlineskip\hsize3.5in\leftskip0.25in\parindent-0.25in\indent\vrule height\ht\strutbox width0pt depth0pt#\vrule height0pt width0pt depth\dp\strutbox\par}\quad\cr +% height2pt&\omit&&\omit&\cr +% &\hfil{\large\strut Type}&&\hfil{\large\strut Processed only if\kern1pt$\ldots$}&\cr\tablerule +% height2pt&\omit&&\omit&\cr +% &|chorded|&&the \env{chorded} option is active&\cr\tablerule +% &|lyric|&&the \env{chorded} option is not active&\cr\tablerule +% &|slides|&&the \env{slides} option is active&\cr\tablerule +% &|partiallist|&&the \mac{includeonlysongs} macro is being used to extract +% a partial list of songs&\cr\tablerule +% &|songindexes|&&the \env{noindexes} option is not active&\cr\tablerule +% &|measures|&&the \env{nomeasures} option is not active&\cr\tablerule +% &|pdfindex|&&the \env{nopdfindex} option is not active&\cr\tablerule +% &|rawtext|&&the \env{rawtext} option is active&\cr\tablerule +% &|transcapos|&&the \env{transposecapos} option is active&\cr\tablerule +% &|nolyrics|&&the \mac{nolyrics} macro is in effect&\cr\tablerule +% &|vnumbered|&&the current verse is numbered (i.e., it was started +% with \mac{beginverse} instead of \mac{beginverse}|*|)&\cr} +% \hrule} +% \caption{Conditional macros}\label{tab:conditionals} +% \end{table} +% The conditional block concludes with the macro |\fi|. +% Between the |\if|\meta{type} and the |\fi| may also appear an |\else|. +% For example, in the construction +% +% \begin{codeblock} +% |\ifchorded| +% \quad\meta{A} +% |\else| +% \quad\meta{B} +% |\fi| +% \end{codeblock} +% +% \noindent +% material \meta{A} is only included if the \env{chorded} option is active, +% and material \meta{B} is only included if the \env{chorded} option is not +% active. +% +% \subsection{Page Layout}\label{sec:layout} +% +% \DescMacro{songcolumns} +% The number of columns per page can be set with |\songcolumns|. +% For example, to create 3 columns per page, write +% +% \begin{codeblock} +% |\songcolumns{3}| +% \end{codeblock} +% +% \noindent +% The number of columns should only be changed outside of \env{songs} +% environments. +% +% 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|: +% +% \begin{codeblock} +% |\songcolumns{0}| +% |\flushbottom| +% |\twocolumn[\LARGE\centering My Songs]| +% |\begin{|\env{songs}|}{}| +% $\vdots$ +% |\end{|\env{songs}|}| +% \end{codeblock} +% +% \noindent +% When disabling the page-builder, please note the following potential +% issues: +% +% \begin{itemize} +% \item The \mac{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. +% \item 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 \mac{songpos} below). +% \item Indexes produced with \mac{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 \mac{showindex}. +% \end{itemize} +% +% \DescMacro{columnsep} +% The horizontal distance between consecutive columns is controlled by +% the |\columnsep| dimension. +% For example, to separate columns by 1 centimeter of space, write +% +% \begin{codeblock} +% |\columnsep=1cm| +% \end{codeblock} +% +% \DescMacro{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: +% +% \begin{codeblock} +% |\renewcommand{\colbotglue}{0pt plus .5\textheight minus 0pt}| +% \end{codeblock} +% +% \DescMacro{lastcolglue} +% The last column in a \env{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: +% +% \begin{codeblock} +% |\renewcommand{\lastcolglue}{0pt}| +% \end{codeblock} +% +% \DescMacro{songpos} +% The \Songs\ 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 +% +% \begin{codeblock} +% |\songpos{|\meta{level}|}| +% \end{codeblock} +% +% \noindent +% 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 \mac{vvpenalty} and \mac{spenalty}). +% +% \DescMacro{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 \mac{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. +% +% \subsection{Indexes}\label{sec:idxcust} +% +% \paragraph{Index Appearance.} +% \DescMacro{indexsongsas} +% 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: +% +% \begin{codeblock} +% |\indexsongsas{|\meta{id}|}{\thepage}| +% \end{codeblock} +% +% \noindent +% where \meta{id} is the same identifier used in the \mac{newindex}, +% \mac{newauthorindex}, or \mac{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 \mac{thesongnum} in place +% of |\thepage| in the above. +% +% \DescMacro{sepindexestrue} +% \DescMacro{sepindexesfalse} +% 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|. +% +% \DescMacro{idxrefsfont} +% 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 +% +% \begin{codeblock} +% |\renewcommand{\idxrefsfont}{\bfseries}| +% \end{codeblock} +% +% \DescMacro{idxtitlefont} +% \DescMacro{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 sans-serif and lyric entries +% in regular roman font, one could define: +% +% \begin{codeblock} +% |\renewcommand{\idxtitlefont}{\sffamily\bfseries}| +% |\renewcommand{\idxlyricfont}{\rmfamily\mdseries}| +% \end{codeblock} +% +% \DescMacro{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 +% +% \begin{codeblock} +% |\renewcommand{\idxheadfont}{\sffamily\it\LARGE}| +% \end{codeblock} +% +% \DescMacro{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: +% +% \begin{codeblock} +% |\renewcommand{\idxbgcolor}{red}| +% \end{codeblock} +% +% \DescMacro{idxheadwidth} +% The |\idxheadwidth| length defines the width of the shaded boxes that +% begin each alphabetic block of a large title index. +% For example, to set the width of those boxes to 1 centimeter, you could +% define +% +% \begin{codeblock} +% |\setlength{\idxheadwidth}{1cm}| +% \end{codeblock} +% +% \DescMacro{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 +% +% \begin{codeblock} +% |\renewcommand{\idxauthfont}{\small\it}| +% \end{codeblock} +% +% \DescMacro{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 +% +% \begin{codeblock} +% |\renewcommand{\idxscripfont}{\sffamily\small\bfseries}| +% \end{codeblock} +% +% \DescMacro{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 +% +% \begin{codeblock} +% |\renewcommand{\idxbook}[1]{\framebox{\small\bfseries#1}}| +% \end{codeblock} +% +% \DescMacro{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 +% ``\meta{bookname} (continued)'' by default. +% You can change this default by redefining the |\idxcont| macro, which +% receives the \meta{bookname} as its single argument. +% For example, to typeset an index in German, one might define +% +% \begin{codeblock} +% |\renewcommand{\idxcont}[1]{\small\textbf{#1} (fortgefahren)}| +% \end{codeblock} +% +% \paragraph{Alphabetization Options.} +% \DescMacro{titleprefixword} +% 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, +% +% \begin{codeblock} +% |\titleprefixword{I}| +% \end{codeblock} +% +% \noindent +% 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. +% +% \paragraph{Special Words In Song Info.} +% \DescMacro{authsepword} +% 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, +% +% \begin{codeblock} +% |\authsepword{und}| +% \end{codeblock} +% +% \noindent +% 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. +% +% \DescMacro{authbyword} +% 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 +% +% \begin{codeblock} +% |\authbyword{durch}| +% \end{codeblock} +% +% \DescMacro{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, +% +% \begin{codeblock} +% |\authignoreword{unbekannt}| +% \end{codeblock} +% +% \subsection{Page Headers and Footers} +% +% In \LaTeX, page headers and footers are defined using a system of +% invisible \emph{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 \Songs\ package. +% For more detailed information about the marks already provided by +% \LaTeX\ and how to use them, consult any \LaTeX\ user manual. +% +% \DescMacro{songmark} +% \DescMacro{versemark} +% \DescMacro{chorusmark} +% 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 +% \S\ref{sec:songinfo}. +% To access the current song's number or the current verse's number, use +% \mac{thesongnum} or \mac{theversenum} (see \S\ref{sec:numbering}). +% For example, to include the song number in the page headings produced by +% \LaTeX's |\pagestyle{myheadings}| feature, you could redefine |\songmark| +% as follows: +% +% \begin{codeblock} +% |\renewcommand{\songmark}{\markboth{|\mac{thesongnum}|}{|\mac{thesongnum}|}}| +% \end{codeblock} +% +% \subsection{Defining New Beginsong Keyvals}\label{sec:newkey} +% +% \DescMacro{newsongkey} +% The \mac{beginsong} macro supports several optional keyval parameters for +% declaring song information, including \env{by=}, \env{sr=}, and \env{cr=}. +% Users can define their own additional keyvals as well. +% To do so, use the |\newsongkey| macro, which has the syntax +% +% \begin{codeblock} +% |\newsongkey{|\meta{keyname}|}{|\meta{initcode}|}[|\meta{default}|]{|\meta{setcode}|}| +% \end{codeblock} +% +% \noindent +% Here, \meta{keyname} is the name of the new key for the keyval, +% \meta{initcode} is \LaTeX\ code that is executed at the start of each +% \mac{beginsong} line before the \mac{beginsong} arguments are processed, +% \meta{default} (if specified) is the default value used for the keyval when +% \meta{keyname} appears in \mac{beginsong} without a value, +% and \meta{setcode} is macro code that is executed whenever +% \meta{key} is parsed as part of the \mac{beginsong} keyval arguments. +% In \meta{setcode}, |#1| expands to the value given by the user for the +% keyval (or to \meta{default} 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: +% +% \begin{codeblock} +% |\newcommand{\arranger}{}| +% |\newsongkey{arr}{\def\arranger{}}| +% | {\def\arranger{Arranged by #1\par}}| +% \end{codeblock} +% +% \noindent +% Then one could redefine \mac{extendprelude} to print the arranger below the +% other song header information: +% +% \begin{codeblock} +% |\renewcommand{\extendprelude}{| +% | |\mac{showrefs}\mac{showauthors} +% | {\bfseries\arranger}| +% |}| +% \end{codeblock} +% +% \noindent +% A \mac{beginsong} line could then specify the song's arranger as follows: +% +% \begin{codeblock} +% \mac{beginsong}|{The Title}[arr={R. Ranger}]| +% $\vdots$ +% \mac{endsong} +% \end{codeblock} +% +% \noindent This produces +% +% \begin{sample} +% \setcounter{songnum}{1}% +% \vskip1pt% +% \newcommand\arranger{}% +% \newsongkey{arr}{\def\arranger{}}% +% {\def\arranger{Arranged by #1\par}}% +% \renewcommand{\extendprelude}{ +% \showrefs\showauthors +% {\bfseries\arranger} +% }% +% \beginsong{The Title}[arr={R. Ranger}] +% \endsong +% \renewcommand{\extendprelude}{}% +% \end{sample} +% +% For more detailed information about keyvals and how they work, consult the +% documentation for David Carlisle's |keyval| package, which comes standard +% with most \LaTeXe\ installations. +% +% \subsection{Font Kerning Corrections} +% +% \paragraph{Chord Overstriking.} +% In order to conserve space and keep songs readable, the \Songs\ 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, +% +% \example|\[(Gsus4/D)]Overstrike|\produces{\[(Gsus4/D)]Overstrike} +% \eat\] +% +% \noindent +% Note that the parentheses and slash symbols in the chord name have +% invaded the lyric that sits beneath them. +% +% \DescMacro{chordlocals} +% 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: +% +% \begin{codeblock} +% |\renewcommand{\chordlocals}{\catcode`(\active| +% | \catcode`)\active| +% | \catcode`/\active}| +% |\newcommand{\smraise}[1]{\raise2pt\hbox{\small#1}}| +% |\newcommand{\myslash}{\smraise/}| +% |\newcommand{\myopenparen}{\smraise(|\eat)|}| +% |\newcommand{\mycloseparen}{\smraise)}| +% |{\chordlocals| +% | \global\let(\myopenparen| +% | \global\let)\mycloseparen| +% | \global\let/\myslash}| +% \end{codeblock} +% +% \noindent +% This sets the |/|, |(|, and |)| symbols as active characters whenever they +% appear within chord names. +% \ImplOrDesc +% {(See \S\ref{sec:chordlocals} for documentation of the +% \texttt{\string\chordlocals} hook.)} +% {(Recompile this documentation to include the implementation section +% for more information about the \texttt{\string\chordlocals} macro.)} +% Each active character is defined so that it produces a smaller, raised +% version of the original symbol. +% The result is as follows: +% +% \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} +% +% \example|\[(Gsus4/D)]Overstrike (fixed)|\produces{\[(Gsus4/D)]Overstrike (fixed)} +% \eat\] +% +% \renewcommand\chordlocals{} +% +% \noindent +% As you can see, the low-hanging symbols have been elevated so that they +% sit above the baseline, correcting the overstrike problem. +% +% \paragraph{Scripture Font Quotation Marks.} +% \DescMacro{shiftdblquotes} +% The \Songs\ 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 \mac{scripturefont} to change +% this kerning correction. +% For example, +% +% \begin{codeblock} +% |\renewcommand{|\mac{scripturefont}|}{| +% | \usefont{OT1}{pzc}{mb}{it}| +% | \shiftdblquotes{-1pt}{-2pt}{-3pt}{-4pt}| +% |}| +% \end{codeblock} +% +% \noindent +% removes 1 point of space to the left and 2 points of space to the +% right of left-double-quote characters, and 3 points to the left and 4 points +% to the right of right-double-quotes, within scripture quotations. +% +% \section{Informational Macros}\label{sec:songinfo} +% +% The macros described in this section can be used to retrieve information +% about the current song. +% This can be used when redefining \mac{extendprelude}, \mac{extendpostlude}, +% \mac{makeprelude}, \mac{makepostlude}, \mac{songmark}, \mac{versemark}, or +% \mac{chorusmark}, or any other macros that might typeset this information. +% +% \DescMacro{songauthors} +% To get the current song's list of authors (if any) use |\songauthors|. +% This yields the value of the \env{by=} key used in the \mac{beginsong} +% line. +% +% \DescMacro{songrefs} +% To get the current song's list of scripture references (if any) use +% |\songrefs|. +% This yields the value of the \env{sr=} key used in the \mac{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. +% +% \DescMacro{songcopyright} +% To get the current song's copyright info (if any), use |\songcopyright|. +% This yields the value of the \env{cr=} key used in the \mac{beginsong} line. +% +% \DescMacro{songlicense} +% To get the current song's licensing information (if any), use +% |\songlicense|. +% This yields the value of the \env{li=} key used in the \mac{beginsong} +% line, or whatever text was declared with \mac{setlicense}. +% +% \DescMacro{songtitle} +% The |\songtitle| macro yields the current song's title. +% By default this is the first title provided in the \mac{beginsong} line. +% The \mac{nexttitle} and \mac{foreachtitle} macros (see below) cause it +% to be set to the current song's other titles, if any. +% +% \DescMacro{resettitles} +% To get the current song's primary title (i.e., the first title specified +% in the song's \mac{beginsong} line), execute |\resettitles|. +% This sets the |\songtitle| macro to be the song's primary title. +% +% \DescMacro{nexttitle} +% 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). +% +% \DescMacro{foreachtitle} +% 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: +% +% \begin{codeblock} +% \mac{resettitles} +% \mac{songtitle} +% \mac{nexttitle} +% |\foreachtitle{, |\mac{songtitle}|}| +% \end{codeblock} +% +% \DescMacro{songlist} +% When \mac{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. +% +% \section{Index Generation} +% +% The material in this section describes macros provided by the \Songs\ +% 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 \S\ref{sec:compiling}. +% For info on how to customize the appearance of indexes, see +% \S\ref{sec:idxcust}. +% +% Automatic generation of song book indexes is a three stage process: +% +% \begin{enumerate} +% +% \item +% Each time a song book \LaTeX\ file is compiled, an auxiliary file named +% \meta{filename}|.sxd| is written out for each \meta{filename} +% defined using \mac{newindex}, \mac{newauthorindex}, or \mac{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 +% \mac{thesongnum}). +% The third line is an identifying label for the song used in hyperlinking. +% +% \item +% 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 \Songs\ package come +% with a specialized |songidx| program to do this. +% +% \item +% The |.sbx| files produced by the |songidx| program are then read +% in by the \mac{showindex} macro next time the source document is +% compiled using \LaTeX. +% These |.sbx| files consist of the macros and environments described below. +% +% \end{enumerate} +% +% \DescEnv{idxblock} +% In indexes that are blocked off into sections, one for each letter of the +% alphabet, the \meta{filename}|.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{codeblock} +% |\begin{idxblock}{|\meta{letter}|}| +% $\vdots$ +% |\end{idxblock}| +% \end{codeblock} +% +% \noindent +% where \meta{letter} is the letter of the alphabet for that block. +% +% \DescMacro{idxentry} +% \DescMacro{idxaltentry} +% The index entries themselves are created by lines of the form +% +% \begin{codeblock} +% |\idxentry{|\meta{leftside}|}{|\meta{rightside}|}| +% |\indexaltentry{|\meta{leftside}|}{|\meta{rightside}|}| +% \end{codeblock} +% +% \noindent +% each of which creates an index entry with \meta{leftside} on the left, +% followed by a series of dots, followed by \meta{rightside} 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 \meta{rightside}, 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. +% +% \section{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 \Rath\ package by Christopher Rath +% (\href{http://rath.ca/Misc/Songbook/}{{\tt 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. +% +% \bigskip +% +% \paragraph{Ease of Song Entry.} +% Much of the \Songs\ 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{|\meta{chord}|}{|\meta{lyric}|}|. +% The \Songs\ package uses a less conventional +% |\[|\meta{chord}|]|\meta{lyric}\eat\] syntax for several +% reasons detailed below. +% +% First, macros in the standard \LaTeX\ syntax require more key-presses +% than macros in the \Songs\ 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 \meta{lyric} will lie below the chord (because the \meta{lyric} +% part must be enclosed in braces) whereas the \Songs\ package's syntax does +% not. +% Estimating this accurately can be quite difficult, since in many cases the +% \meta{lyric} part must include punctuation or multiple words to get proper +% results. +% The \Songs\ package automates this for the user, significantly easing the +% task of chord-entry. +% +% Third, unlike the standard \LaTeX\ chord syntax, the \Songs\ 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 \Songs\ package does this automatically. +% +% Fourth and finally, some other packages allow the user to use ``|b|'' +% in a \meta{chord} to produce a flat symbol, whereas the \Songs\ package +% requires an ``|&|'' instead. +% Using ``|b|'' is more intuitive but prevents the +% use of ``|b|'' for any other purpose within a \meta{chord}, such as to +% produce a literal ``b'' or to type another macro name like |\hbox| that +% contains a ``b''. +% Consequently, the \Songs\ package uses the less obvious ``|&|'' symbol to +% produce flat symbols. +% +% \paragraph{Song Structure.} +% The \Songs\ 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. +% +% \paragraph{Multiple columns.} +% The \Songs\ 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. +% +% \paragraph{Indexes.} +% Another major feature of the \Songs\ 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 \Songs\ 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 +% well-ordered index. +% Other supported indexes include those sorted by author, by title, and by +% notable lines of lyrics. +% +% \paragraph{Automatic Transposition.} +% The \Songs\ 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). +% +% \bigskip +% +% The \Songs\ package was developed entirely independently of all other +% \LaTeX\ song book packages. +% I originally developed the set of \LaTeX\ macros that eventually became +% the \Songs\ 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 \Rath\ 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 \Rath\ package. +% It includes an excellent list of other resources that might be of interest +% to creators of song books. +% +% \section{GNU General Public License}\label{sec:license} +% +% \begingroup\small +% +% \begin{center} +% {\large\sc Terms and Conditions For \\ Copying, Distribution and Modification} +% \end{center} +% +% \begin{enumerate}\addtocounter{enumi}{-1} +% +% \item +% +% 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. +% +% \item 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. +% +% \item +% +% 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: +% +% \begin{enumerate} +% +% \item +% +% You must cause the modified files to carry prominent notices stating that +% you changed the files and the date of any change. +% +% \item +% +% 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. +% +% \item +% 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.) +% +% \end{enumerate} +% +% 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. +% +% 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. +% +% \item +% 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: +% +% \begin{enumerate} +% +% \item +% +% 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, +% +% \item +% +% 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, +% +% \item +% +% 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.) +% +% \end{enumerate} +% +% 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. +% +% \item +% 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. +% +% \item +% 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. +% +% \item +% 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. +% +% \item +% 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. +% +% \item +% 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. +% +% \item +% 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. +% +% \item +% 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 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. +% +% \begin{center} +% {\large\sc No Warranty} +% \end{center} +% +% \item +% {\sc 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.} +% +% \item +% {\sc 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.} +% +% \end{enumerate} +% +% \endgroup +% +% \StopEventually{\PrintIndex} +% +% \clearpage +% \section{Implementation} +% +% The following provides the verbatim implementation of the \Songs\ \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 \S\ref{sec:impparams}. +% To find the implementation of any particular macro, the index at the end +% of this document should prove helpful. +% +% The unwary \TeX er may wonder at the rather large size of the +% implementation. +% The volume and complexity of the code stems mainly from the following +% challenging features: +% \begin{itemize} +% \item Putting chords above lyrics fully automatically requires building an +% entire lyric-parser in \LaTeX\ (see \S\ref{sec:lyricscan}). +% \item Avoiding page-turns within songs without prohibiting column-breaks +% requires building a completely new page-breaking algorithm +% (see \S\ref{sec:pagebuilder}). +% \item 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. +% \item Song book indexes are far more complex than those for a prose book. +% See \S\ref{sec:indexgen} for some of the difficulties involved. +% \end{itemize} +% +% \subsection{Initialization} +% +% The code in this section detects any \TeX\ versioning or configuration +% settings that are relevant to the rest of the song book code. +% +% \begin{macro}{\ifSB@etex} +% Numerous enhancements are possible when using an $\varepsilon$-\TeX\ +% compatible version of \LaTeX. +% We start by checking to see if $\varepsilon$-\TeX\ primitives are +% available. +% \begin{macrocode} +\newif\ifSB@etex +\ifx\eTeXversion\undefined\else + \ifx\eTeXversion\relax\else + \SB@etextrue + \IfFileExists{etex.sty}{\RequirePackage{etex}}{} + \fi +\fi +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifSB@pdf} +% Detect whether we're generating a pdf file, since this affects the +% treatment of hyperlinks and bookmark indexes. +% \begin{macrocode} +\newif\ifSB@pdf\SB@pdffalse +\ifx\pdfoutput\undefined\else + \ifx\pdfoutput\relax\else + \ifnum\pdfoutput<\@ne\else + \SB@pdftrue + \fi + \fi +\fi +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newif\ifSB@preamble +\SB@preambletrue +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifSB@test} +% \begin{macro}{\SB@temp} +% \begin{macro}{\SB@tempii} +% \begin{macro}{\SB@tempiii} +% \begin{macro}{\SB@tempiv} +% \begin{macro}{\SB@tempv} +% Reserve some control sequence names for scratch use. +% \begin{macrocode} +\newif\ifSB@test +\newcommand\SB@temp{} +\newcommand\SB@tempii{} +\newcommand\SB@tempiii{} +\newcommand\SB@tempiv{} +\newcommand\SB@tempv{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@dimen} +% \begin{macro}{\SB@dimenii} +% \begin{macro}{\SB@dimeniii} +% \begin{macro}{\SB@dimeniv} +% \begin{macro}{\SB@box} +% \begin{macro}{\SB@boxii} +% \begin{macro}{\SB@boxiii} +% \begin{macro}{\SB@toks} +% \begin{macro}{\SB@cnt} +% \begin{macro}{\SB@cntii} +% \begin{macro}{\SB@skip} +% Reserve some temp registers for various purposes. +% \begin{macrocode} +\newdimen\SB@dimen +\newdimen\SB@dimenii +\newdimen\SB@dimeniii +\newdimen\SB@dimeniv +\newbox\SB@box +\newbox\SB@boxii +\newbox\SB@boxiii +\newtoks\SB@toks +\newcount\SB@cnt +\newcount\SB@cntii +\newskip\SB@skip +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% Load David Carlisle's |keyval| package for processing +% \meta{key}=\meta{value} style macro arguments. +% \begin{macrocode} +\RequirePackage{keyval} +% \end{macrocode} +% +% \subsection{Default Parameters}\label{sec:impparams} +% +% 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.) +% +% \begin{macro}{\lyricfont}\MainImpl{lyricfont} +% Define the font style to use for formatting song lyrics. +% \begin{macrocode} +\newcommand\lyricfont{\normalfont\normalsize} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stitlefont}\MainImpl{stitlefont} +% Define the font style to use for formatting song titles. +% \begin{macrocode} +\newcommand\stitlefont{% + \ifslides\sffamily\Huge\else\sffamily\slshape\Large\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\versefont}\MainImpl{versefont} +% \begin{macro}{\chorusfont}\MainImpl{chorusfont} +% \begin{macro}{\notefont}\MainImpl{notefont} +% \changes{v2.1}{2007/08/02}{Added} +% By default, verses, choruses, and textual notes just allow the |\lyricfont| +% style to continue. +% \begin{macrocode} +\newcommand\versefont{} +\newcommand\chorusfont{} +\newcommand\notefont{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\scripturefont}\MainImpl{scripturefont} +% \changes{v1.13}{2005/05/12}{Added kerning correction for double-quote ligatures} +% Define the font style to use for formatting scripture quotations +% (defaults to Zapf Chancery). +% \begin{macrocode} +\newcommand\scripturefont{% + \usefont{OT1}{pzc}{mb}{it}% + \shiftdblquotes{-1.1\p@}\z@{-2\p@}\z@% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\printscrcite}\MainImpl{printscrcite} +% Define the printing style for the citation at the end of a scripture +% quotation. +% \begin{macrocode} +\newcommand\printscrcite[1]{\sffamily\small#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\snumbgcolor}\MainImpl{snumbgcolor} +% \begin{macro}{\notebgcolor}\MainImpl{notebgcolor} +% \begin{macro}{\idxbgcolor}\MainImpl{idxbgcolor} +% 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 |\def|\meta{macroname}|{}|. +% \begin{macrocode} +\newcommand\snumbgcolor{SongbookShade} +\newcommand\notebgcolor{SongbookShade} +\newcommand\idxbgcolor{SongbookShade} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\versejustify}\MainImpl{versejustify} +% \begin{macro}{\chorusjustify}\MainImpl{chorusjustify} +% \changes{v2.1}{2007/08/02}{Added} +% Verses and choruses are both left-justified with hanging indentation equal +% to |\parindent|, +% \begin{macrocode} +\newcommand\versejustify{\justifyleft} +\newcommand\chorusjustify{\justifyleft} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\notejustify}\MainImpl{notejustify} +% \changes{v2.1}{2007/08/02}{Added} +% Textual notes are fully justified when they are too long to fit in +% a single line. +% \begin{macrocode} +\newcommand\notejustify{% + \advance\baselineskip\p@\relax% + \leftskip\z@skip\rightskip\z@skip% + \parfillskip\@flushglue\parindent\z@% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\placenote}\MainImpl{placenote} +% \changes{v2.1}{2007/08/02}{Added} +% 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|. +% \begin{macrocode} +\newcommand\placenote[1]{% + \leftskip\z@skip\rightskip\@flushglue\SB@cbarshift% + \noindent#1\par% +} +% \end{macrocode} +% \end{macro} +% +% These counters define the current song number and verse number. +% They can be redefined by the user at any time. +% \begin{macrocode} +\newcounter{songnum} +\newcounter{versenum} +% \end{macrocode} +% +% \begin{macro}{\thesongnum}\MainImpl{thesongnum} +% \begin{macro}{\songnumstyle} +% 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.) +% \begin{macrocode} +\renewcommand\thesongnum{\songnumstyle{songnum}} +\newcommand\songnumstyle{} +\let\songnumstyle\arabic +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\theversenum}\MainImpl{theversenum} +% \begin{macro}{\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.) +% \begin{macrocode} +\renewcommand\theversenum{\versenumstyle{versenum}} +\newcommand\versenumstyle{} +\let\versenumstyle\arabic +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\printsongnum}\MainImpl{printsongnum} +% Define the printing style for the large, boxed song numbers starting each +% song. +% \begin{macrocode} +\newcommand\printsongnum[1]{\sffamily\bfseries\LARGE#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\printversenum}\MainImpl{printversenum} +% Define the printing style for the verse numbers to the left of each verse. +% \begin{macrocode} +\newcommand\printversenum[1]{\lyricfont#1.\ } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\placeversenum}\MainImpl{placeversenum} +% \changes{v2.1}{2007/08/02}{Added} +% 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. +% \begin{macrocode} +\newcommand\placeversenum[1]{% + \hskip-\leftskip\hskip-\parindent\relax% + \box#1% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\everyverse}\MainImpl{everyverse} +% \begin{macro}{\everychorus}\MainImpl{everychorus} +% \changes{v2.1}{2007/08/02}{Added} +% The following hooks allow users to insert material at the head of each +% verse or chorus. +% \begin{macrocode} +\newcommand\everyverse{} +\newcommand\everychorus{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\printchord}\MainImpl{printchord} +% Define the printing style for chords. +% \begin{macrocode} +\newcommand\printchord[1]{\sffamily\slshape\large#1} +% \end{macrocode} +% \end{macro} +% +% \label{sec:chordlocals} +% \begin{macro}{\chordlocals}\MainImpl{chordlocals} +% 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. +% \begin{macrocode} +\newcommand\chordlocals{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\versesep}\MainImpl{versesep} +% 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. +% \begin{macrocode} +\newskip\versesep +\versesep123456789sp\relax +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\afterpreludeskip}\MainImpl{afterpreludeskip} +% \begin{macro}{\beforepostludeskip}\MainImpl{beforepostludeskip} +% 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. +% \begin{macrocode} +\newskip\afterpreludeskip +\afterpreludeskip=2\p@\@plus4\p@ +\newskip\beforepostludeskip +\beforepostludeskip=2\p@\@plus4\p@ +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\baselineadj}\MainImpl{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. +% \begin{macrocode} +\newskip\baselineadj +\baselineadj\z@skip +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\clineparams}\MainImpl{clineparams} +% 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. +% \begin{macrocode} +\newcommand\clineparams{% + \baselineskip\f@size\p@% + \advance\baselineskip-2\p@% + \lineskiplimit-2\p@% + \lineskip-2\p@% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\parindent} +% The |\parindent| length controls how far broken lyric lines are +% indented from the left margin. +% \begin{macrocode} +\parindent.25in +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\idxheadwidth}\MainImpl{idxheadwidth} +% Specify the width of the head-boxes in a large index. +% \begin{macrocode} +\newlength\idxheadwidth +\setlength\idxheadwidth{1.5cm} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\songnumwidth}\MainImpl{songnumwidth} +% Set the width of the song number boxes that begin each song. +% We guess a suitable width by typesetting the text ``999.'' +% \begin{macrocode} +\newlength\songnumwidth +\settowidth\songnumwidth{\printsongnum{999.}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\versenumwidth}\MainImpl{versenumwidth} +% Set the width that is reserved for normal-sized verse numbers. +% (Verse numbers wider than this will indent the first line of lyrics.) +% \begin{macrocode} +\newlength\versenumwidth +\settowidth\versenumwidth{\printversenum{9\kern1em}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\cbarwidth} +% This dictates the width of the vertical line placed to the left of +% choruses. +% Setting it to |0pt| eliminates the line entirely. +% \begin{macrocode} +\newlength\cbarwidth +\setlength\cbarwidth\p@ +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sbarheight} +% This dictates the height of the horizontal line placed between each pair +% of songs. +% Setting it to |0pt| eliminates the line entirely. +% \begin{macrocode} +\newlength\sbarheight +\setlength\sbarheight\p@ +% \end{macrocode} +% \end{macro} +% +% 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). +% \begin{macrocode} +\interlinepenalty\@m +% \end{macrocode} +% +% \begin{macro}{\vvpenalty}\MainImpl{vvpenalty} +% \begin{macro}{\ccpenalty}\MainImpl{ccpenalty} +% \begin{macro}{\vcpenalty}\MainImpl{vcpenalty} +% \begin{macro}{\cvpenalty}\MainImpl{cvpenalty} +% \begin{macro}{\brkpenalty}\MainImpl{brkpenalty} +% \changes{v2.1}{2007/08/02}{Added.} +% 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$. +% \begin{macrocode} +\newcount\vvpenalty\vvpenalty200 +\newcount\ccpenalty\ccpenalty200 +\newcount\vcpenalty\vcpenalty200 +\newcount\cvpenalty\cvpenalty200 +\newcount\brkpenalty\brkpenalty200 +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\spenalty}\MainImpl{spenalty} +% \changes{v2.1}{2007/08/02}{Added.} +% 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. +% \begin{macrocode} +\newcount\spenalty\spenalty100 +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\songmark}\MainImpl{songmark} +% \changes{v1.17}{2005/09/24}{Added.} +% \begin{macro}{\versemark}\MainImpl{versemark} +% \begin{macro}{\chorusmark}\MainImpl{chorusmark} +% \changes{v2.1}{2007/08/02}{Added.} +% 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. +% \begin{macrocode} +\newcommand\songmark{} +\newcommand\versemark{} +\newcommand\chorusmark{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\extendprelude}\MainImpl{extendprelude} +% \begin{macro}{\extendpostlude}\MainImpl{extendpostlude} +% \changes{v2.0}{2007/06/18}{Added.} +% 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. +% \begin{macrocode} +\newcommand\extendprelude{\showrefs\showauthors} +\newcommand\extendpostlude{\songcopyright\ \songlicense\unskip} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\idxheadfont}\MainImpl{idxheadfont} +% \changes{v2.8}{2009/02/22}{Added.} +% Users can redefine |\idxheadfont| to affect the font in which each capital +% letter that heads a section of a title index is rendered. +% \begin{macrocode} +\newcommand\idxheadfont{\sffamily\bfseries\LARGE} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\idxtitlefont}\MainImpl{idxtitlefont} +% \changes{v2.8}{2009/02/22}{Added.} +% Users can redefine |\idxtitlefont| to affect the font in which song title +% index entries are rendered. +% \begin{macrocode} +\newcommand\idxtitlefont{\sffamily\slshape} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\idxlyricfont}\MainImpl{idxlyricfont} +% \changes{v2.8}{2009/02/22}{Added.} +% Users can redefine |\idxlyricfont| to affect the font in which notable lines +% of lyrics are rendered in a title index. +% \begin{macrocode} +\newcommand\idxlyricfont{\rmfamily} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\idxscripfont}\MainImpl{idxscripfont} +% \changes{v2.8}{2009/02/22}{Added.} +% Users can redefine |\idxscripfont| to affect the font in which scripture +% references are rendered in a scripture index. +% \begin{macrocode} +\newcommand\idxscripfont{\sffamily\small\slshape} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\idxauthfont}\MainImpl{idxauthfont} +% \changes{v2.8}{2009/02/22}{Added.} +% Users can redefine |\idxauthfont| to affect the font in which contributor +% names are rendered in an author index. +% \begin{macrocode} +\newcommand\idxauthfont{\small\bfseries} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\idxrefsfont}\MainImpl{idxrefsfont} +% \changes{v2.8}{2009/02/22}{Added.} +% 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. +% \begin{macrocode} +\newcommand\idxrefsfont{\normalfont\normalsize} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\idxbook}\MainImpl{idxbook} +% \changes{v2.8}{2009/02/22}{Added.} +% Users can redefine |\idxbook| to dictate the book name header in a +% scripture index that begins each book of the bible. +% \begin{macrocode} +\newcommand\idxbook[1]{\small\bfseries#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\idxcont}\MainImpl{idxcont} +% \changes{v2.0}{2007/06/18}{Added.} +% Users can redefine |\idxcont| to dictate the column header in a scripture +% index after a column break falls within a book of the bible. +% \begin{macrocode} +\newcommand\idxcont[1]{\small\textbf{#1} (continued)} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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|. +% \begin{macrocode} +\newcommand\colbotglue{} +\let\colbotglue\z@skip +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\lastcolglue} +% Glue of size |\lastcolglue| is inserted at the bottom of the last column. +% \begin{macrocode} +\newcommand\lastcolglue{} +\let\lastcolglue\@flushglue +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\minfrets} +% Define the minimum number of fret rows that should appear in tablature +% diagrams. +% \begin{macrocode} +\newcount\minfrets\minfrets4 +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@colwidth} +% 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. +% \begin{macrocode} +\newdimen\SB@colwidth +% \end{macrocode} +% \end{macro} +% +% \subsection{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 \S\ref{sec:optproc} because +% some of the macros defined here refer to macros that have not yet been +% defined. +% +% \begin{option}{slides}\MainEnvImpl{slides} +% \begin{macro}{\slides}\MainImpl{slides} +% \optdef{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. +% \begin{macrocode} +\DeclareOption{slides}{\slides} +\newcommand\slides{% + \slidestrue% + \def\lyricfont{\normalfont\huge}% + \def\chorusfont{\slshape}% + \def\versejustify{\justifycenter}% + \let\chorusjustify\versejustify + \def\placenote##1{\justifycenter\noindent##1\par}% + \scriptureoff% + \onesongcolumn% + \ifSB@preamble\ifSB@chordedspec\else\SB@chordsoff\fi\fi% + \spenalty-\@M% + \let\colbotglue\@flushglue% + \setlength\cbarwidth\z@% + \setlength\sbarheight\z@% +} +% \end{macrocode} +% \end{macro} +% \end{option} +% +% \begin{macro}{\justifyleft} +% \changes{v2.1}{2007/08/02}{Added} +% 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. +% \begin{macrocode} +\newcommand\justifyleft{% + \leftskip\parindent% + \ifSB@inverse\advance\leftskip\versenumwidth\fi% + \SB@cbarshift% + \parindent-\parindent% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\justifycenter} +% \changes{v2.1}{2007/08/02}{Added} +% 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. +% \begin{macrocode} +\newcommand\justifycenter{% + \centering\SB@cbarshift\rightskip\leftskip% + \def\placeversenum##1{% + \hskip-\leftskip\hskip-\parindent\relax% + \hangindent-\wd##1\hangafter\m@ne% + \box##1\hfil% + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{option}{unouter}\MainEnvImpl{unouter} +% \begin{macro}{\SB@outer} +% \optdef{off} +% Several macros provided by the \Songs\ 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|. +% \begin{macrocode} +\newcommand\SB@outer{\outer} +\DeclareOption{unouter}{\let\SB@outer\relax} +% \end{macrocode} +% \end{macro} +% \end{option} +% +% \begin{option}{rawtext}\MainEnvImpl{rawtext} +% \optdef{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.) +% \begin{macrocode} +\DeclareOption{rawtext}{\rawtexttrue\indexesoff} +% \end{macrocode} +% \end{option} +% +% \begin{option}{nopdfindex}\MainEnvImpl{nopdfindex} +% \optdef{off} +% Inhibit the creation of the bookmark index in pdf files. +% This option can only be set in the |\usepackage| line because initializing +% the pdfbookmark library at all causes a (possibly empty) bookmark index to +% be created. +% \begin{macrocode} +\DeclareOption{nopdfindex}{\pdfindexfalse} +% \end{macrocode} +% \end{option} +% +% \begin{option}{noshading}\MainEnvImpl{noshading} +% \optdef{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.) +% \begin{macrocode} +\DeclareOption{noshading}{\SB@colorboxesfalse} +% \end{macrocode} +% \end{option} +% +% \begin{option}{noindexes}\MainEnvImpl{noindexes} +% \begin{macro}{\indexeson}\MainImpl{indexeson} +% \begin{macro}{\indexesoff}\MainImpl{indexesoff} +% \optdef{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. +% \begin{macrocode} +\DeclareOption{noindexes}{\indexesoff} +\newcommand\indexeson{\songindexestrue} +\newcommand\indexesoff{\songindexesfalse} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{option} +% +% \begin{macro}{\ifSB@measurespec} +% \begin{macro}{\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 if +% each of these options has been explicitly specified by the user or if it +% is still in a default state. +% \begin{macrocode} +\newif\ifSB@measurespec +\newif\ifSB@chordedspec +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{option}{chorded}\MainEnvImpl{chorded} +% \begin{option}{lyric}\MainEnvImpl{lyric} +% \begin{macro}{\chordson}\MainImpl{chordson} +% \begin{macro}{\chordsoff}\MainImpl{chordsoff} +% \begin{macro}{\SB@chordson} +% \begin{macro}{\SB@chordsoff} +% \changes{v1.22}{2007/05/15}{Update \cs{baselineskip} when in songs.} +% \optdef{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. +% \begin{macrocode} +\DeclareOption{chorded}{\chordson} +\DeclareOption{lyric}{\chordsoff} +\newcommand\chordson{\SB@chordedspectrue\SB@chordson} +\newcommand\chordsoff{\SB@chordedspectrue\SB@chordsoff} +\newcommand\SB@chordson{% + \ifrawtext% + \SB@errrtopt% + \else% + \chordedtrue\lyricfalse% + \let\SB@bracket\SB@chord% + \let\SB@rechord\SB@@rechord% + \let\SB@ch\SB@ch@on% + \ifSB@measurespec% + \ifmeasures\SB@measureson\else\SB@measuresoff\fi% + \else% + \SB@measureson% + \fi% + \ifSB@preamble\def\colbotglue{\z@\@plus.5\textheight}\fi% + \SB@setbaselineskip% + \fi% +} +\newcommand\SB@chordsoff{% + \chordedfalse\lyrictrue% + \def\SB@bracket##1]{\ignorespaces}% + \let\SB@rechord\relax% + \let\SB@ch\SB@ch@off% + \ifSB@measurespec% + \ifmeasures\SB@measureson\else\SB@measuresoff\fi% + \else% + \SB@measuresoff% + \fi% + \ifSB@preamble\let\colbotglue\z@skip\fi% + \SB@setbaselineskip% +} +% \end{macrocode} +% \eat\] +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{option} +% \end{option} +% +% \begin{option}{showmeasures}\MainEnvImpl{showmeasures} +% \begin{option}{nomeasures}\MainEnvImpl{nomeasures} +% \begin{macro}{\measureson}\MainImpl{measureson} +% \begin{macro}{\measuresoff}\MainImpl{measuresoff} +% \begin{macro}{\SB@measureson} +% \begin{macro}{\SB@measuresoff} +% \optdef{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. +% \begin{macrocode} +\DeclareOption{showmeasures}{\measureson} +\DeclareOption{nomeasures}{\measuresoff} +\newcommand\measureson{\SB@measurespectrue\SB@measureson} +\newcommand\measuresoff{\SB@measurespectrue\SB@measuresoff} +\newcommand\SB@measureson{% + \measurestrue% + \let\SB@mbar\SB@makembar% + \ifchorded% + \let\SB@mch\SB@mch@on% + \else% + \let\SB@mch\SB@mch@m% + \fi% + \ifSB@inverse\SB@loadactives\fi% + \ifSB@inchorus\SB@loadactives\fi% +} +\newcommand\SB@measuresoff{% + \measuresfalse% + \let\SB@mbar\@gobbletwo% + \ifchorded% + \let\SB@mch\SB@ch@on% + \else% + \let\SB@mch\SB@ch@off% + \fi% + \ifSB@inverse\SB@loadactives\fi% + \ifSB@inchorus\SB@loadactives\fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{option} +% \end{option} +% +% \begin{option}{transposecapos}\MainEnvImpl{transposecapos} +% \optdef{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. +% \begin{macrocode} +\DeclareOption{transposecapos}{\transcapostrue} +% \end{macrocode} +% \end{option} +% +% \begin{option}{noscripture}\MainEnvImpl{noscripture} +% \begin{macro}{\scriptureon}\MainImpl{scriptureon} +% \begin{macro}{\scriptureoff}\MainImpl{scriptureoff} +% \optdef{off} +% Inhibits the display of scripture quotes. +% This option can also be toggled on and off anywhere with the |\sciptureon| +% and |\scriptureoff| macros. +% \begin{macrocode} +\DeclareOption{noscripture}{\SB@omitscriptrue} +\newcommand\scriptureon{\SB@omitscripfalse} +\newcommand\scriptureoff{\SB@omitscriptrue} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{option} +% +% \begin{option}{onesongcolumn}\MainEnvImpl{onesongcolumn} +% \begin{option}{twosongcolumns}\MainEnvImpl{twosongcolumns} +% \begin{macro}{\onesongcolumn}\MainImpl{onesongcolumn} +% \begin{macro}{\twosongcolumns}\MainImpl{twosongcolumns} +% \begin{macro}{\songcolumns}\MainImpl{songcolumns} +% \optdef{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 \env{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. +% \begin{macrocode} +\DeclareOption{twosongcolumns}{\SB@numcols\tw@} +\DeclareOption{onesongcolumn}{\SB@numcols\@ne} +\newcommand\songcolumns[1]{% + \SB@cnt#1\relax% + \ifnum\SB@cnt=\SB@numcols\else% + \ifSB@preamble\else{\SB@clearpage}\fi% + \fi% + \SB@numcols\SB@cnt% + \ifnum\SB@numcols>\z@% + \SB@colwidth-\columnsep% + \multiply\SB@colwidth\SB@numcols% + \advance\SB@colwidth\columnsep% + \advance\SB@colwidth\textwidth% + \divide\SB@colwidth\SB@numcols% + \else% + \ifrepchorus\SB@warnrc\fi% + \fi% +} +\newcommand\onesongcolumn{\songcolumns\@ne} +\newcommand\twosongcolumns{\songcolumns\tw@} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{option} +% \end{option} +% +% \begin{macro}{\includeonlysongs}\MainImpl{includeonlysongs} +% \begin{macro}{\songlist} +% Display only a select list of songs and ignore the rest. +% \begin{macrocode} +\newcommand\songlist{} +\newcommand\includeonlysongs[1]{% + \ifSB@songsenv\SB@errpl\else% + \partiallisttrue% + \renewcommand\songlist{#1}% + \fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\nosongnumbers}\MainImpl{nosongnumbers} +% \changes{v2.9}{2009/04/01}{Added.} +% The user can turn off song numbering with the following macro. +% \begin{macrocode} +\newcommand\nosongnumbers{\setlength\songnumwidth\z@} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\noversenumbers}\MainImpl{noversenumbers} +% \changes{v1.20}{2006/03/12}{Added.} +% The user can turn off verse numbering with the following macro. +% \begin{macrocode} +\newcommand\noversenumbers{% + \renewcommand\printversenum[1]{}% + \setlength\versenumwidth\z@% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\repchoruses}\MainImpl{repchoruses} +% \begin{macro}{\norepchoruses}\MainImpl{norepchoruses} +% \changes{v2.1}{2007/08/02}{Added.} +% Using |\repchoruses| causes choruses to be automatically repeated on +% subsequent pages of the song. +% The feature requires $\varepsilon$-\TeX\ because the supporting code needs +% an extended mark register class. +% \begin{macrocode} +\ifSB@etex + \newcommand\repchoruses{% + \ifnum\SB@numcols<\@ne\SB@warnrc\fi% + \repchorustrue% + } +\else + \newcommand\repchoruses{\SB@erretex} +\fi +\newcommand\norepchoruses{\repchorusfalse} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\sepverses{% + \vvpenalty-\@M% + \ccpenalty100 % + \vcpenalty\vvpenalty% + \cvpenalty\vvpenalty% + \let\colbotglue\@flushglue% +} +% \end{macrocode} +% \end{macro} +% +% Some option settings, margins, and other lengths are finalized at the end of +% the preamble. +% That code is below. +% +% \begin{macrocode} +\AtBeginDocument{ +% \end{macrocode} +% +% If the user hasn't set the |\versesep|, set it to the default. +% \begin{macrocode} + \SB@setversesep +% \end{macrocode} +% +% Initialize page layout algorithm. +% \begin{macrocode} + \songcolumns\SB@numcols +% \end{macrocode} +% +% Macros used after this point occur outside the preamble. +% \begin{macrocode} + \SB@preamblefalse +} +% \end{macrocode} +% +% \subsection{Page-builder} +% \label{sec:pagebuilder} +% +% 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. +% +% \begin{macro}{\SB@songbox} +% The most recently processed song (or scripture quotation) is stored in this +% box. +% \begin{macrocode} +\newbox\SB@songbox +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@numcols} +% \begin{macro}{\SB@colnum} +% Reserve two count registers to hold the total number of columns and the +% current column number, respectively. +% \begin{macrocode} +\newcount\SB@numcols\SB@numcols\tw@ +\newcount\SB@colnum +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@colbox} +% Reserve a box register to hold the current column in progress. +% \begin{macrocode} +\newbox\SB@colbox +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@colbox} +% Reserve a box register to hold the current page in progress. +% \begin{macrocode} +\newbox\SB@pgbox +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@mrkbox} +% Reserve a box register to hold marks that migrate out of songs as they +% get split into columns and pages. +% \begin{macrocode} +\newbox\SB@mrkbox +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@maxmin} +% The following helper macro takes the max or min of two dimensions. +% If \argp{2}=``|<|'', it sets \argp{1} to the maximum of \argp{1} and +% \argp{3}. +% If \argp{2}=``|>|'', it sets \argp{1} to the minimum of \argp{1} and +% \argp{3}. +% \begin{macrocode} +\newcommand\SB@maxmin[3]{\ifdim#1#2#3#1#3\fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@mkpage} +% 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: +% \begin{enumerate} +% \item the box $b$ to split (must not be |\SB@box|, which is used as a +% temp register), +% \item a count register $i$ equaling column index (zero or greater) +% where the content of $b$ is to begin, and +% \item the desired column height. +% \end{enumerate} +% Box $b$ is split and $i$ is incremented until $i$ reaches +% |\SB@numcols| or $b$ is emptied, whichever occurs first. +% If $b$ is emptied first, the final column is \emph{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. +% 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. +% \begin{macrocode} +\newcommand\SB@mkpage[3]{% + \begingroup% + \splitmaxdepth\maxdepth\splittopskip\z@skip% + \global\setbox#1\vbox{% + \unvbox#1% + \nointerlineskip% + \null% + \vfil% + }% + \loop\ifnum#2<\SB@numcols% + \setbox\SB@box\vsplit#1to#3\relax% + \ifvoid#1% + #2\SB@numcols% + \else% + \SB@updatepage% + \global\advance#2\@ne% + \ifrepchorus\ifvoid\SB@chorusbox\else% + \SB@insertchorus#1% + \fi\fi% + \fi% + \repeat% + \global\setbox#1\vbox{% + \unvbox\SB@box% + \unvbox#1% + \unskip% + \setbox\SB@box\lastbox% + }% + \endgroup% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@migrate} +% Migrate a mark out of a recently split vertical list, but do not insert +% superfluous empty marks that may override previous marks. +% \begin{macrocode} +\newcommand\SB@migrate[1]{% + \SB@toks\expandafter{#1}% + \edef\SB@temp{\the\SB@toks}% + \ifx\SB@temp\@empty\else\mark{\the\SB@toks}\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@updatepage} +% Update boxes |\SB@pgbox| and |\SB@mrkbox| immediately after splitting +% the contents of |\SB@colbox|. +% \begin{macrocode} +\newcommand\SB@updatepage{% + \global\setbox\SB@mrkbox\vbox{% + \unvbox\SB@mrkbox% + \SB@migrate\splitfirstmark% + \SB@migrate\splitbotmark% + }% + \global\setbox\SB@pgbox\hbox{% + \SB@dimen\SB@colwidth% + \advance\SB@dimen\columnsep% + \multiply\SB@dimen\SB@colnum% + \advance\SB@dimen-\wd\SB@pgbox% + \unhbox\SB@pgbox% + \ifdim\SB@dimen=\z@\else\hskip\SB@dimen\relax\fi% + \box\SB@box% + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@droppage{\setbox\SB@box\box\voidb@x} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@output} +% 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. +% This final, in-progress column is left unfinished, pending future +% contributions. +% \begin{macrocode} +\newcommand\SB@output{% + \ifnum\SB@numcols>\z@\begingroup% + \loop% + \SB@dimen\textheight% + \ifinner\else\advance\SB@dimen-\pagetotal\fi% + \SB@mkpage\SB@colbox\SB@colnum\SB@dimen% + \ifnum\SB@colnum<\SB@numcols\else% + \unvbox\SB@mrkbox% + \ifinner\else\kern\z@\fi% + \box\SB@pgbox% + \ifinner\else\vfil\break\vskip\vsize\relax\fi% + \global\SB@colnum\z@% + \repeat% + \endgroup\else% + \unvbox\SB@colbox\unskip% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@putboxes[1]{% + \SB@dimen\ifnum\SB@numcols>\z@\ht\SB@colbox\else\p@\fi% + #1\SB@colbox% + \ifdim\SB@dimen>\z@% + \SB@breakpoint\spenalty% + \ifdim\sbarheight>\z@% + \vskip-\sbarheight\relax% + \fi% + \fi% + #1\SB@songbox% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@nextcol[2]{% + \ifnum#1>\z@% + \ifnum\SB@numcols>\z@% + \global\setbox\SB@colbox\vbox{% + \SB@cnt#1\relax% + \SB@dimen\ht\SB@colbox% + \unvbox\SB@colbox% + \unskip% + \ifdim\SB@dimen>\z@% + \vskip#2\relax% + \break% + \advance\SB@cnt\m@ne% + \fi% + \loop\ifnum\SB@cnt>\z@% + \nointerlineskip% + \null% + \vfil% + \break% + \advance\SB@cnt\m@ne% + \repeat% + }% + \SB@output% + \else% + \ifnum\lastpenalty=-\@M\null\fi% + \break% + \fi% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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). +% \begin{macrocode} +\newcommand\SB@selectcol{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@@selectcol} +% \changes{v2.1}{2007/08/02}{Rewritten to better handle glue} +% \changes{v2.9}{2009/07/30}{Rewritten to handle repeated choruses} +% 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. +% \begin{macrocode} +\newcommand\SB@@selectcol{% + \begingroup% + \SB@cnt\z@% + \vbadness\@M\vfuzz\maxdimen% + \let\SB@updatepage\SB@droppage% + \SB@dimen\textheight% + \ifinner\else\advance\SB@dimen-\pagetotal\fi% + \setbox\SB@boxii\vbox{\SB@putboxes\unvcopy}% + \SB@cntii\SB@colnum% + \SB@mkpage\SB@boxii\SB@cntii\SB@dimen% + \SB@spos% + \global\SB@cnt\SB@cnt% + \endgroup% + \SB@nextcol\SB@cnt\colbotglue% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@spbegnew} +% Begin a trial typesetting of the current song on a fresh page to see if +% it fits within a page. +% \begin{macrocode} +\newcommand\SB@spbegnew{% + \setbox\SB@boxiii\copy\SB@songbox% + \SB@cntii\z@% + \SB@mkpage\SB@boxiii\SB@cntii\textheight% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@spextold} +% Tentatively extend the song previously typeset on the current even page to +% the next odd page to see if it fits on a double-page. +% If the current page is odd-numbered, do nothing since extending the song +% to the next page would introduce a page-turn. +% \begin{macrocode} +\newcommand\SB@spextold{% + \ifodd\c@page\else% + \SB@cntii\z@% + \SB@mkpage\SB@boxii\SB@cntii\textheight% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@spextnew} +% Extend the trial typesetting started with |\SB@spbegnew| to a second +% page to see if the song fits on a fresh double-page. +% \begin{macrocode} +\newcommand\SB@spextnew{% + \SB@cntii\z@% + \SB@mkpage\SB@boxiii\SB@cntii\textheight% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@spdblpg{% + \ifnum\SB@cntii<\SB@numcols% + \SB@cnt\SB@numcols% + \advance\SB@cnt-\SB@colnum% + \if@twoside\ifodd\c@page\else% + \advance\SB@cnt\SB@numcols% + \fi\fi% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@sposi} +% This is the level-1 song positioning algorithm. +% It moves songs to the next double-page only if doing so would avoid a +% page-turn that would otherwise appear within the song. +% \begin{macrocode} +\newcommand\SB@sposi{% + \ifnum\SB@cntii<\SB@numcols\else\if@twoside% + \SB@spextold% + \fi\fi% + \ifnum\SB@cntii<\SB@numcols\else% + \SB@spbegnew% + \ifnum\SB@cntii<\SB@numcols\else\if@twoside% + \SB@spextnew% + \fi\fi% + \SB@spdblpg% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@sposii{% + \ifnum\SB@cntii<\SB@numcols\else% + \SB@spbegnew% + \ifnum\SB@cntii<\SB@numcols% + \SB@cnt\SB@numcols% + \advance\SB@cnt-\SB@colnum% + \else% + \if@twoside% + \SB@spextold% + \ifnum\SB@cntii<\SB@numcols\else% + \SB@spextnew% + \SB@spdblpg% + \fi% + \fi% + \fi% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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, page-break, or page-turn that would +% otherwise appear within the song. +% \begin{macrocode} +\newcommand\SB@sposiii{% + \ifnum\SB@cntii>\SB@colnum% + \SB@cnt\SB@colnum% + \advance\SB@cnt\@ne% + \ifnum\SB@cnt<\SB@numcols% + \setbox\SB@boxiii\copy\SB@songbox% + \SB@mkpage\SB@boxiii\SB@cnt\SB@dimen% + \advance\SB@cnt\m@ne% + \fi% + \ifnum\SB@cnt>\SB@colnum% + \SB@cnt\z@% + \SB@sposii% + \else% + \SB@cnt\@ne% + \fi% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\songpos} +% This is the macro by which the user adjusts the aggressiveness level of the +% song-positioning algorithm. +% See the macros above for what each level does. +% \begin{macrocode} +\newcommand\songpos[1]{% + \ifcase#1% + \let\SB@selectcol\relax% + \let\SB@spos\relax% + \or% + \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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@spos{} +\songpos\thr@@ +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@clearpage} +% 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). +% \begin{macrocode} +\newcommand\SB@clearpage{% + \SB@testtrue% + \ifvoid\SB@pgbox\ifvoid\SB@colbox\SB@testfalse\fi\fi% + \ifSB@test% + \SB@cnt\SB@numcols% + \advance\SB@cnt-\SB@colnum% + \SB@nextcol\SB@cnt\lastcolglue% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@cleardpage} +% Like |\SB@clearpage| but shift to a fresh \emph{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. +% \begin{macrocode} +\newcommand\SB@cleardpage{% + \SB@clearpage% + \if@twoside\ifodd\c@page% + \SB@nextcol\SB@numcols\@flushglue% + \fi\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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 column-submission type. +% \begin{macrocode} +\newcommand\SB@stype{\SB@stypcol} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@stypcol} +% \changes{v2.1}{2007/08/02}{Rewritten to better handle glue} +% 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. +% \begin{macrocode} +\newcommand\SB@stypcol{% + \ifnum\SB@numcols>\z@% + \SB@selectcol% + \global\setbox\SB@colbox\vbox{\SB@putboxes\unvbox}% + \SB@output% + \else% + \unvbox\voidb@x% + \SB@breakpoint\spenalty% + \ifdim\sbarheight>\z@% + \vskip-\sbarheight\relax% + \fi% + \unvbox\SB@songbox% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@styppage{% + \ifnum\SB@numcols>\z@% + \SB@clearpage% + \unvbox\SB@songbox% + \null\nointerlineskip% + \else% + \unvbox\SB@songbox% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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|. +% \begin{macrocode} +\newcommand\SB@sgroup{} +\let\SB@sgroup\@empty +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcount\SB@groupcnt +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@submitpart} +% 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|. +% \begin{macrocode} +\newcommand\SB@submitpart{% + \ifx\SB@sgroup\@empty\else% + \@for\SB@temp:=\songlist\do{% + \ifx\SB@temp\SB@sgroup% + \edef\SB@tempii{\SB@sgroup @\the\SB@groupcnt}% + \expandafter\newbox\csname songbox@\SB@tempii\endcsname% + \global\expandafter\setbox + \csname songbox@\SB@tempii\endcsname\box\SB@songbox% + \global\expandafter\let% + \csname stype@\SB@tempii\endcsname\SB@stype% + \ifrepchorus\ifvoid\SB@chorusbox\else% + \expandafter\newbox\csname chbox@\SB@tempii\endcsname% + \global\expandafter\setbox% + \csname chbox@\SB@tempii\endcsname\box\SB@chorusbox% + \fi\fi% + \fi% + }% + \global\advance\SB@groupcnt% + \ifnum\SB@groupcnt<\z@\m@ne\else\@ne\fi% + \fi% + \setbox\SB@songbox\box\voidb@x% + \setbox\SB@chorusbox\box\voidb@x% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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.) +% \begin{macrocode} +\newcommand\SB@submitsong{% + \ifpartiallist\SB@submitpart\else\SB@stype\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@songlistbrk} +% \begin{macro}{\SB@songlistnc} +% \begin{macro}{\SB@songlistcp} +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@songlistbrk{} +\def\SB@songlistbrk{brk} +\newcommand\SB@songlistnc{} +\def\SB@songlistnc{nextcol} +\newcommand\SB@songlistcp{} +\def\SB@songlistcp{sclearpage} +\newcommand\SB@songlistcdp{} +\def\SB@songlistcdp{scleardpage} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\commitsongs}\MainImpl{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. +% \begin{macrocode} +\newcommand\commitsongs{% + \ifpartiallist% + \ifnum\SB@numcols>\z@% + \@for\SB@temp:=\songlist\do{% + \ifx\SB@temp\SB@songlistnc\SB@nextcol\@ne\@flushglue\else% + \ifx\SB@temp\SB@songlistbrk\SB@nextcol\@ne\colbotglue\else% + \ifx\SB@temp\SB@songlistcp\SB@clearpage\else% + \ifx\SB@temp\SB@songlistcdp\SB@cleardpage\else% + \SB@groupcnt\m@ne\SB@finloop% + \SB@groupcnt\z@\SB@finloop% + \fi\fi\fi\fi% + }% + \else% + \@for\SB@temp:=\songlist\do{% + \ifx\SB@temp\SB@songlistnc\vfil\break\else% + \ifx\SB@temp\SB@songlistbrk\break\else% + \ifx\SB@temp\SB@songlistcp\clearpage\else% + \ifx\SB@temp\SB@songlistcdp% + \clearpage% + \ifodd\c@page\null\newpage\fi% + \else% + \SB@groupcnt\m@ne\SB@finloop% + \SB@groupcnt\z@\SB@finloop% + \fi\fi\fi\fi% + }% + \fi% + \fi% + \SB@clearpage% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@finloop} +% While contributing saved material included by |\includeonlysongs|, +% this macro contributes each series of boxes grouped together as part of a +% |songgroup| environment. +% \begin{macrocode} +\newcommand\SB@finloop{% + \loop\edef\SB@tempii{\SB@temp @\the\SB@groupcnt}% + \expandafter\ifx% + \csname songbox@\SB@tempii\endcsname\relax\else% + \setbox\SB@songbox\expandafter\box% + \csname songbox@\SB@tempii\endcsname% + \expandafter\ifx\csname chbox@\SB@tempii\endcsname\relax% + \repchorusfalse% + \else% + \repchorustrue% + \setbox\SB@chorusbox\expandafter\box% + \csname chbox@\SB@tempii\endcsname% + \fi% + \csname stype@\SB@tempii\endcsname% + \advance\SB@groupcnt\ifnum\SB@groupcnt<\z@\m@ne\else\@ne\fi% + \repeat% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@insertchorus[1]{{% + \vbadness\@M\vfuzz\maxdimen% + \setbox\SB@box\copy#1% + \setbox\SB@box\vsplit\SB@box to\maxdimen% + \edef\SB@temp{\splitfirstmarks\SB@nocmarkclass}% + \ifx\SB@temp\SB@nocmark\else% + \edef\SB@temp{\splitfirstmarks\SB@cmarkclass}% + \ifx\SB@temp\SB@cmark% + \SB@dimen4096\p@% + \SB@dimenii\maxdimen% + \SB@dimeniii\SB@dimen% + \loop% + \SB@dimeniii.5\SB@dimeniii% + \setbox\SB@box\copy#1% + \setbox\SB@box\vsplit\SB@box to\SB@dimen% + \edef\SB@temp{\splitfirstmarks\SB@cmarkclass}% + \ifx\SB@temp\SB@cmark% + \SB@dimenii\SB@dimen% + \advance\SB@dimen-\SB@dimeniii% + \else% + \advance\SB@dimen\SB@dimeniii% + \fi% + \ifdim\SB@dimeniii>2\p@\repeat% + \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% + }% +% \end{macrocode} +% 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 high-level 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. +% \begin{macrocode} + \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% +}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\nextcol}\MainImpl{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. +% \begin{macrocode} +\newcommand\nextcol{% + \@ifstar{\SB@nextcol\@ne\@flushglue}% + {\ifpartiallist\else\SB@nextcol\@ne\@flushglue\fi}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sclearpage}\MainImpl{sclearpage} +% Move to the next page if the current page is nonempty. +% \begin{macrocode} +\newcommand\sclearpage{% + \@ifstar\SB@clearpage{\ifpartiallist\else\SB@clearpage\fi}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\scleardpage}\MainImpl{scleardpage} +% Move to the next even-numbered page if the current page is odd or nonempty. +% \begin{macrocode} +\newcommand\scleardpage{% + \@ifstar\SB@cleardpage{\ifpartiallist\else\SB@cleardpage\fi}% +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Songs} +% +% The following macros handle the parsing and formatting of the material that +% begins and ends each song. +% +% \begin{macro}{\SB@lop} +% \begin{macro}{\SB@@lop} +% \begin{macro}{\SB@emptylist} +% \begin{macro}{\SB@ifempty} +% The following macros were adapted from Donald Knuth's \emph{The \TeX book}, +% for manipulating lists of the form +% {\it |\\|item1|\\|item2|\\|...|\\|itemN|\\|}. +% \begin{macrocode} +\newcommand\SB@lop[1]{\expandafter\SB@@lop\the#1\SB@@lop#1} +\newcommand\SB@@lop{} +\def\SB@@lop\\#1\\#2\SB@@lop#3#4{\global#3{\\#2}\global#4{#1}} +\newcommand\SB@emptylist{} +\def\SB@emptylist{\\} +\newcommand\SB@ifempty[3]{% + \edef\SB@temp{\the#1}% + \ifx\SB@temp\SB@emptylist#2\else#3\fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@titlelist} +% \begin{macro}{\SB@titletail} +% 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. +% \begin{macrocode} +\newtoks\SB@titlelist +\newtoks\SB@titletail +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\songtitle} +% \changes{v1.15}{2005/05/26}{Added song title iterators} +% The |\songtitle| macro will initially hold the primary title of the +% current song. +% The user can iterate over titles using |\nexttitle| or |\foreachtitle|. +% \begin{macrocode} +\newcommand\songtitle{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\resettitles}\MainImpl{resettitles} +% \changes{v1.15}{2005/05/26}{Added.} +% Initialize the title list iterator. +% \begin{macrocode} +\newcommand\resettitles{% + \global\SB@titletail\SB@titlelist% + \nexttitle% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\nexttitle}\MainImpl{nexttitle} +% \changes{v1.15}{2005/05/26}{Added.} +% Advance the title list iterator to the next title. +% \begin{macrocode} +\newcommand\nexttitle{% + \SB@ifempty\SB@titletail{% + \global\let\songtitle\relax% + }{% + \SB@lop\SB@titletail\SB@toks% + \edef\songtitle{\the\SB@toks}% + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\foreachtitle}\MainImpl{foreachtitle} +% \changes{v1.15}{2005/05/26}{Added.} +% Execute a block of code for each remaining title in the title list. +% \begin{macrocode} +\newcommand\foreachtitle[1]{% + \ifx\songtitle\relax\else% + \loop#1\nexttitle\ifx\songtitle\relax\else\repeat% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifSB@insong} +% \begin{macro}{\ifSB@intersong} +% \begin{macro}{\ifSB@inverse} +% \begin{macro}{\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. +% \begin{macrocode} +\newif\ifSB@songsenv\SB@songsenvfalse +\newif\ifSB@insong\SB@insongfalse +\newif\ifSB@intersong\SB@intersongfalse +\newif\ifSB@inverse\SB@inversefalse +\newif\ifSB@inchorus\SB@inchorusfalse +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@closeall{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@rawrefs} +% \begin{macro}{\songauthors}\MainImpl{songauthors} +% \begin{macro}{\songcopyright}\MainImpl{songcopyright} +% \begin{macro}{\songlicense}\MainImpl{songlicense} +% The current song's scripture references, authors, copyright info, and +% copyright license information are stored in these macros. +% \begin{macrocode} +\newcommand\SB@rawrefs{} +\newcommand\songauthors{} +\newcommand\songcopyright{} +\newcommand\songlicense{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\songrefs}\MainImpl{songrefs} +% 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. +% \begin{macrocode} +\newcommand\songrefs{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\setlicense}\MainImpl{setlicense} +% The user sets the licensing info for the current song with this command. +% \begin{macrocode} +\newcommand\setlicense{\gdef\songlicense} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\newsongkey}\MainImpl{newsongkey} +% \begin{macro}{\SB@clearbskeys} +% \changes{v2.0}{2007/06/18}{Added.} +% 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.) +% \begin{macrocode} +\newcommand\SB@clearbskeys{} +\newcommand\newsongkey[2]{% + \expandafter\gdef\expandafter\SB@clearbskeys\expandafter% + {\SB@clearbskeys#2}% + \define@key{beginsong}{#1}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% 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. +% \begin{macrocode} +\newsongkey{sr}{\def\SB@rawrefs{}\gdef\songrefs{}} + {\def\SB@rawrefs{#1}\SB@parsesrefs{#1}} +\newsongkey{by}{\def\songauthors{}}{\def\songauthors{#1}} +\newsongkey{cr}{\def\songcopyright{}}{\def\songcopyright{#1}} +\newsongkey{li}{\setlicense{}}{\setlicense{#1}} +\newsongkey{index}{}{\indexentry{#1}} +\newsongkey{ititle}{}{\indextitleentry{#1}} +% \end{macrocode} +% +% \begin{environment}{song}\MainEnvImpl{song} +% \begin{macro}{\beginsong} +% \begin{macro}{\SB@@beginsong} +% \begin{macro}{\SB@bsoldfmt} +% \begin{macro}{\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. +% \begin{macrocode} +\newenvironment{song}{\beginsong}{\SB@endsong} +\newcommand\beginsong[1]{% + \ifSB@insong\SB@errboo\SB@closeall\fi% + \ifSB@intersong\SB@errbor\SB@closeall\fi% + \SB@insongtrue% + \def\SB@closeall{\endsong}% + \SB@parsetitles{#1}% + \global\setbox\SB@songwrites\box\voidb@x% + \SB@clearbskeys% + \@ifnextchar[\SB@bskvfmt\SB@@beginsong% +} +\newcommand\SB@@beginsong{% + \@ifnextchar\bgroup\SB@bsoldfmt\SB@@@beginsong% +} +\newcommand\SB@bsoldfmt[3]{% + \SB@bskvfmt[sr={#1},by={#2},cr={#3}]% +} +\newcommand\SB@bskvfmt{} +\def\SB@bskvfmt[#1]{% + \setkeys{beginsong}{#1}% + \SB@@@beginsong% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@@@beginsong} +% \changes{v1.12}{2005/05/10}{Redid spacing and page-breaking} +% \changes{v1.14}{2005/05/15}{Improved scripture reference line-breaking} +% \changes{v2.0}{2007/06/18}{Added keyval syntax.} +% 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. +% \begin{macrocode} +\newcommand\SB@@@beginsong{% + \global\SB@stanzafalse% + \setbox\SB@chorusbox\box\voidb@x% + \SB@gotchorusfalse% + \setbox\SB@songbox\vbox\bgroup\begingroup% + \ifnum\SB@numcols>\z@\hsize\SB@colwidth\fi% + \leftskip\z@skip\rightskip\z@skip% + \parfillskip\@flushglue\parskip\z@skip% + \SB@raggedright% + \global\SB@transposefactor\z@% + \global\SB@cr@{\\}% + \protected@edef\@currentlabel{\p@songnum\thesongnum}% + \setcounter{versenum}{1}% + \SB@prevversetrue% + \meter44% + \resettitles% + \SB@addtoindexes\songtitle\SB@rawrefs\songauthors% + \nexttitle% + \foreachtitle{\expandafter\SB@addtotitles\expandafter{\songtitle}}% + \resettitles% + \lyricfont% + \SB@setbaselineskip% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@endsong} +% \changes{v1.12}{2005/05/10}{Redid spacing and page-breaking} +% \changes{v2.0}{2007/06/18}{Removed hyperref dependency} +% 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. +% \begin{macrocode} +\newcommand\SB@endsong{% + \ifSB@insong% + \ifSB@inverse\SB@erreov\endverse\fi% + \ifSB@inchorus\SB@erreoc\endchorus\fi% + \global\SB@skip\versesep% + \unskip% + \ifrepchorus\ifvoid\SB@chorusbox\else% + \ifSB@prevverse\ifvnumbered% + \marks\SB@cmarkclass{\SB@lastcmark}% + \fi\fi% + \fi\fi% + \endgroup\egroup% + \setbox\SB@songbox\vbox{% + \songmark% + \unvbox\SB@songwrites% + \ifnum\SB@numcols>\z@\hsize\SB@colwidth\fi% + \leftskip\z@skip\rightskip\z@skip% + \parfillskip\@flushglue\parskip\z@skip\parindent\z@% + \ifdim\sbarheight>\z@% + \hrule\@height\sbarheight\@width\hsize% + \nobreak\vskip5\p@% + \fi% + \ifpdfindex\begingroup% + \ifx\pdfbookmark\undefined\else% + \ifx\pdfbookmark\relax\else% + \resettitles% + \pdfbookmark[\ifnum\c@section=\z@1\else2\fi]% + {\thesongnum. \songtitle}% + {song\theSB@songsnum-\thesongnum}% + \fi\fi% + \endgroup\fi% + \vbox{\makeprelude}% + \nobreak\vskip\SB@skip% + \vskip\afterpreludeskip\relax% + \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% + }% + \SB@insongfalse% + \edef\SB@sgroup{\thesongnum}% + \global\SB@groupcnt\z@% + \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% +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% +% \begin{macro}{\SB@setbaselineskip} +% \changes{v1.22}{2007/05/15}{Added.} +% \changes{v2.1}{2007/08/02}{Fixed to scale better with large font sizes.} +% Set the |\baselineskip| to an appropriate line height. +% \begin{macrocode} +\newcommand\SB@setbaselineskip{% + \SB@dimen\f@size\p@% + \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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@setversesep} +% Set the |\versesep| to an appropriate amount if has not already been +% explicitly set by the user. +% \begin{macrocode} +\newcommand\SB@setversesep{% + \SB@dimen123456789sp% + \edef\SB@temp{\the\SB@dimen}% + \edef\SB@tempii{\the\versesep}% + \ifx\SB@temp\SB@tempii% + \begingroup% + \lyricfont% + \SB@dimen\f@size\p@% + \ifchorded% + \setbox\SB@box\hbox{{\printchord{ABCDEFG\shrp\flt/j7}}}% + \advance\SB@dimen\ht\SB@box% + \fi% + \ifslides% + \global\versesep1.2\SB@dimen\@plus.3\SB@dimen% + \@minus.3\SB@dimen% + \else% + \global\versesep.75\SB@dimen\@plus.25\SB@dimen% + \@minus.13\SB@dimen% + \fi% + \endgroup% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\makeprelude}\MainImpl{makeprelude} +% \changes{v1.15}{2005/05/26}{Added to make song header format customizable.} +% \changes{v2.0}{2007/06/18}{Arguments removed to support keyval syntax.} +% 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. +% \begin{macrocode} +\newcommand\makeprelude{% + \resettitles% + \ifslides% + \hbox to\hsize{{% + \hfil\stitlefont\songtitle\hfil% + }}% + \vskip5\p@% + \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{% + \ifnum\SB@numcols>\z@\hsize\SB@colwidth\fi% + \ifdim\songnumwidth>\z@% + \advance\hsize-\wd\SB@boxii% + \advance\hsize-3\p@% + \fi% + \SB@raggedright\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% + }% + \else% + \unvbox\SB@box% + \fi% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\makepostlude}\MainImpl{makepostlude} +% \changes{v1.15}{2005/05/26}{Added to make song trailer format customizable.} +% \changes{v2.0}{2007/06/18}{Arguments removed to support keyval syntax.} +% Generate the material that ends each song. +% \begin{macrocode} +\newcommand\makepostlude{% + \SB@raggedright\baselineskip\z@skip\parskip\z@skip\parindent\z@% + \tiny\extendpostlude% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\showauthors}\MainImpl{showauthors} +% Display the author line in the prelude. +% \begin{macrocode} +\newcommand\showauthors{% + \setbox\SB@box\hbox{\bfseries\sfcode`.\@m\songauthors}% + \ifdim\wd\SB@box>\z@\unhbox\SB@box\par\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\showrefs}\MainImpl{showrefs} +% Display the scripture references in the prelude. +% \begin{macrocode} +\newcommand\showrefs{% + \setbox\SB@box\hbox{\slshape\songrefs\vphantom,}% + \ifdim\wd\SB@box>\z@\unhbox\SB@box\par\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@next} +% \begin{macro}{\SB@donext} +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@next{} +\newcommand\SB@donext{} +\newcommand\SB@dothis{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@nextname} +% Sometimes when scanning ahead we |\string|ify the name of the next token. +% When that happens, the name is stored in this macro for safekeeping. +% \begin{macrocode} +\newcommand\SB@nextname{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@appendsp} +% 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. +% \begin{macrocode*} +\newcommand\SB@appendsp[1]{#1\expandafter{\the#1 }} +% \end{macrocode*} +% \end{macro} +% +% \begin{macro}{\SB@parsetitles} +% \changes{v2.1}{2007/08/02}{Added} +% Parse a list of song titles. +% This just involves removing leading and trailing spaces from around each +% title in the |\\|-separated list. +% \begin{macrocode} +\newcommand\SB@parsetitles[1]{% + \begingroup% + \global\SB@titlelist{\\}% + \SB@toks{}% + \let\\\SB@titlesep% + \let\SB@dothis\SB@pthead% + \SB@ptstart#1\SB@endparse% + \endgroup% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@ptstart} +% The iterator of the title parser loop just scans the next token. +% \begin{macrocode} +\newcommand\SB@ptstart{\futurelet\SB@next\SB@dothis} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@pthead} +% While processing tokens at the head of a title, we skip over all spaces +% until we reach a non-space token. +% \begin{macrocode} +\newcommand\SB@pthead{% + \ifcat\noexpand\SB@next\noexpand\@sptoken% + \expandafter\SB@ptsp% + \else% + \SB@toks{}% + \let\SB@dothis\SB@ptmain% + \expandafter\SB@ptmain% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@ptmain{% + \ifcat\noexpand\SB@next\noexpand\@sptoken% + \let\SB@donext\SB@ptsp% + \else\ifcat\noexpand\SB@next\noexpand\bgroup% + \let\SB@donext\SB@ptbg% + \else\ifx\SB@next\SB@endparse% + \global\SB@titlelist\expandafter{\the\SB@titlelist\\}% + \let\SB@donext\@gobble% + \else% + \ifx\SB@next\\% + \SB@toks{}% + \let\SB@dothis\SB@pthead% + \fi% + \let\SB@donext\SB@ptstep% + \fi\fi\fi% + \SB@donext% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@ptstep[1]{% + \global\SB@titlelist\expandafter\expandafter\expandafter{% + \expandafter\the\expandafter\SB@titlelist\the\SB@toks#1}% + \SB@toks{}% + \SB@ptstart% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@ptbg[1]{\SB@ptstep{{#1}}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@ptsp} +% 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. +% \begin{macrocode} +\newcommand\SB@ptsp{ + \SB@appendsp\SB@toks% + \afterassignment\SB@ptstart% + \let\SB@next= } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@titlesep{SB@titlesep} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@endparse} +% 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. +% \begin{macrocode} +\newcommand\SB@endparse{% + \SB@Error{Title parsing failed}{This error should not occur.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@testdigit} +% \begin{macro}{\SB@@testdigit} +% The following decides whether a token or |\let|-defined control sequence +% is a digit and sets conditional |\ifSB@test| accordingly. +% \begin{macrocode} +\newcommand\SB@testdigit[1]{% + \SB@testfalse% + \ifcat1\noexpand#1\SB@@testdigit#1\fi% +} +\newcommand\SB@@testdigit[1]{% + \ifx0#1\SB@testtrue\else% + \ifx1#1\SB@testtrue\else% + \ifx2#1\SB@testtrue\else% + \ifx3#1\SB@testtrue\else% + \ifx4#1\SB@testtrue\else% + \ifx5#1\SB@testtrue\else% + \ifx6#1\SB@testtrue\else% + \ifx7#1\SB@testtrue\else% + \ifx8#1\SB@testtrue\else% + \ifx9#1\SB@testtrue% + \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@parsesrefs} +% \changes{v1.14}{2005/05/15}{Added} +% 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)~Non-breaking, 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. +% +% 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 $\varepsilon$-\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 +% $\varepsilon$-\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. +% \begin{macrocode} +\newcommand\SB@parsesrefs[1]{% + \begingroup% + \SB@toks{\begingroup\SB@sractives}% + \SB@prloop#1\SB@endparse% + \xdef\songrefs{\the\SB@toks\endgroup}% + \endgroup% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@prloop} +% \begin{macro}{\SB@prstep} +% \begin{macro}{\SB@@prstep} +% The main loop of the scripture reference scanner identifies each space, +% hyphen, and comma for special treatment. +% \begin{macrocode} +\newcommand\SB@prloop{\futurelet\SB@next\SB@prstep} +\newcommand\SB@prstep{% + \ifcat\noexpand\SB@next A% + \expandafter\SB@prcpy% + \else% + \expandafter\SB@@prstep% + \fi% +} +\newcommand\SB@@prstep{% + \ifcat\noexpand\SB@next\noexpand\@sptoken% + \let\SB@donext\SB@prspace% + \else\ifx\SB@next-% + \let\SB@donext\SB@prhyphen% + \else\ifx\SB@next,% + \let\SB@donext\SB@prcomma% + \else\ifx\SB@next\SB@endparse + \let\SB@donext\@gobble% + \else\ifcat\noexpand\SB@next\bgroup% + \let\SB@donext\SB@prgr% + \else% + \let\SB@donext\SB@prcpy% + \fi\fi\fi\fi\fi% + \SB@donext% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@prcpy} +% \begin{macro}{\SB@prgr} +% Anything that isn't one of the special tokens above, and anything in a +% group, is copied without modification. +% \begin{macrocode} +\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} +% \end{macrocode} +% \end{macro} +% \end{macro} + +% \begin{macro}{\SB@prcomma} +% \begin{macro}{\SB@prhyphen} +% Commas and hyphens are replaced with active equivalents. +% \begin{macrocode} +\newcommand\SB@prcomma[1]{} +{\catcode`,\active + \gdef\SB@prcomma#1{\SB@toks\expandafter{\the\SB@toks,}\SB@prloop}} +\newcommand\SB@prhyphen[1]{} +{\catcode`-\active + \gdef\SB@prhyphen#1{\SB@toks\expandafter{\the\SB@toks-}\SB@prloop}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@prspace} +% \begin{macro}{\SB@@prspace} +% Spaces are made active as well, but doing so requires some +% specialized code since they cannot be consumed as implicit macro arguments. +% \begin{macrocode*} +\newcommand\SB@prspace[1]{} +{\obeyspaces +\gdef\SB@prspace{\SB@toks\expandafter{\the\SB@toks }\SB@@prspace}} +% \end{macrocode*} +% \begin{macrocode} +\newcommand\SB@@prspace{\afterassignment\SB@prloop\let\SB@temp= } +% \end{macrocode} +% \end{macro} +% \end{macro} + +% \begin{macro}{\SB@sractives} +% 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. +% \begin{macrocode*} +\newcommand\SB@sractives{} +{\catcode`,\active\catcode`-\active\obeyspaces% +\gdef\SB@sractives{% +\let,\SB@srcomma\let-\SB@srhyphen\let \SB@srspace% +\SB@srspacing}% +} +% \end{macrocode*} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@srspacing{% + \nonfrenchspacing\sfcode`\;=1500\sfcode`\,=1250\relax% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@srcomma} +% \begin{macro}{\SB@@srcomma} +% Commas not already followed by whitespace are appended with a thin, +% non-breaking space. +% \begin{macrocode} +\newcommand\SB@srcomma{,\futurelet\SB@next\SB@@srcomma} +\newcommand\SB@@srcomma{% + \ifx\SB@next\SB@srspace\else% + \nobreak\thinspace% + \fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@srhyphen} +% \begin{macro}{\SB@@srhyphen} +% \begin{macro}{\SB@srdash} +% \begin{macro}{\SB@@srdash} +% Hyphens that are not already part of a ligature (an en- or em-dash) +% become en-dashes. +% \begin{macrocode} +\newcommand\SB@srhyphen{\futurelet\SB@next\SB@@srhyphen} +\newcommand\SB@@srhyphen{% + \ifx\SB@next\SB@srhyphen\expandafter\SB@srdash\else--\fi% +} +\newcommand\SB@srdash[1]{\futurelet\SB@next\SB@@srdash} +\newcommand\SB@@srdash{% + \ifx\SB@next\SB@srhyphen---\expandafter\@gobble\else--\fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@srspace} +% \begin{macro}{\SB@@srspace} +% To compress consecutive whitespace, we ignore spaces +% immediately followed by more whitespace. +% Spaces not preceded by a semicolon or comma become non-breaking. +% 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). +% \begin{macrocode} +\newcommand\SB@srspace{\futurelet\SB@next\SB@@srspace} +\newcommand\SB@@srspace{% + \let\SB@donext\relax% + \ifx\SB@next\SB@srspace\else% + \ifnum\spacefactor>\@m% + \ifnum\spacefactor>1499 % + \ifcat\noexpand\SB@next0% + \let\SB@donext\SB@srcso% + \else% + \penalty-5\enskip% + \fi% + \else% + \space% + \fi% + \else% + \nobreak\space% + \fi% + \fi% + \SB@donext% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@srcso} +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@srcso[1]{\futurelet\SB@temp\SB@@srcso} +\newcommand\SB@@srcso{% + \ifx\SB@temp\SB@srspace% + \penalty-5\enskip% + \else% + \space% + \fi% + \SB@next% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Verses and Choruses} +% +% The following programming typesets song contents, including verses, choruses, +% and textual notes. +% +% \begin{macro}{\ifSB@stanza} +% The following conditional remembers if we've seen any stanzas yet in the +% current song. +% \begin{macrocode} +\newif\ifSB@stanza +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@stanzabreak} +% \changes{v1.12}{2005/05/10}{Fixed stanza counting code and improved spacing} +% End this song stanza and start a new one. +% \begin{macrocode} +\newcommand\SB@stanzabreak{% + \ifhmode\par\fi% + \ifSB@stanza% + \SB@breakpoint{% + \ifSB@inverse% + \ifSB@prevverse\vvpenalty\else\cvpenalty\fi% + \else% + \ifSB@prevverse\vcpenalty\else\ccpenalty\fi% + \fi% + }% + \vskip\versesep% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@breakpoint} +% Insert a valid breakpoint into the vertical list comprising a song. +% \begin{macrocode} +\newcommand\SB@breakpoint[1]{% + \begingroup% + \ifnum#1<\@M% + \SB@skip\colbotglue\relax% + \SB@skip-\SB@skip% + \else% + \SB@skip\z@skip% + \fi% + \advance\SB@skip\lastskip% + \unskip% + \nobreak% + \ifnum#1<\@M% + \vskip\colbotglue\relax% + \penalty#1% + \fi% + \vskip\SB@skip% + \endgroup% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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 letters that dangle below the baseline. +% \begin{macrocode} +\newcommand\SB@putbox[2]{% + \begingroup% + \SB@dimen\dp#2% + #1#2% + \setbox\SB@box\hbox{{\lyricfont p}}% + \ifdim\SB@dimen<\dp\SB@box% + \advance\SB@dimen-\dp\SB@box% + \vskip-\SB@dimen% + \fi% + \setbox\SB@box\box\voidb@x% + \endgroup% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@obeylines} +% Within verses and choruses we would like to use |\obeylines| so that each +% \meta{return} 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 \meta{return} as well. +% \begin{macrocode} +\newcommand\SB@obeylines{% + \let\par\SB@par% + \obeylines% + \let\@par\SB@@par% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@par} +% The following replacement definition of |\par| constructs paragraphs in +% which page-breaks 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.) +% \begin{macrocode} +\newcommand\SB@par{% + \ifhmode% + \SB@cnt\interlinepenalty% + \interlinepenalty\@M% + \endgraf% + \interlinepenalty\SB@cnt% + \ifSB@inchorus% + \ifdim\cbarwidth>\z@\nobreak\else\SB@ilpenalty\fi% + \else% + \SB@ilpenalty% + \fi% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@ilpenalty{% + \ifnum\interlinepenalty=\z@\else% + \penalty\interlinepenalty% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@@par} +% This replacement definition of |\@par| restores the |\SB@par| definition of +% |\par| and then ends the paragraph. +% \begin{macrocode} +\newcommand\SB@@par{\let\par\SB@par\par} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@parindent} +% \changes{v1.12}{2005/05/10}{Added} +% Reserve a length to remember the current |\parindent|. +% \begin{macrocode} +\newdimen\SB@parindent +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@everypar} +% Reserve a control sequence to hold short-term changes to |\everypar|. +% \begin{macrocode} +\newcommand\SB@everypar{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@raggedright} +% \changes{v1.12}{2005/05/10}{Added} +% Perform |\raggedright| except don't nuke the |\parindent|. +% \begin{macrocode} +\newcommand\SB@raggedright{% + \SB@parindent\parindent% + \raggedright% + \parindent\SB@parindent% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\vnumbered} +% \changes{v2.1}{2007/08/02}{Renamed.} +% The following conditional remembers whether this verse is being numbered +% or not (i.e., it distinguishes between |\beginverse| and |\beginverse*|). +% \begin{macrocode} +\newif\ifvnumbered +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifSB@prevverse} +% Reserve a conditional to remember if the previous block in this song was +% a verse. +% \begin{macrocode} +\newif\ifSB@prevverse +% \end{macrocode} +% \end{macro} +% +% 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. +% \begin{macrocode} +\CheckCommand\verse{% + \let\\\@centercr% + \list{}{% + \itemsep\z@% + \itemindent-1.5em% + \listparindent\itemindent% + \rightmargin\leftmargin% + \advance\leftmargin1.5em% + }% + \item\relax% +} +% \end{macrocode} +% +% \begin{environment}{verse}\MainEnvImpl{verse} +% \begin{environment}{verse*} +% \begin{macro}{\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 if 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. +% \begin{macrocode} +\renewenvironment{verse} + {\vnumberedtrue\SB@beginverse} + {\SB@endverse} +\newenvironment{verse*} + {\vnumberedfalse\SB@beginverse} + {\SB@endverse} +\newcommand\beginverse{% + \begingroup% + \SB@loadactives% + \@ifstar{\endgroup\vnumberedfalse\SB@beginverse}% + {\endgroup\vnumberedtrue\SB@beginverse}% +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% \end{environment} +% +% \begin{macro}{\SB@beginverse} +% \changes{v1.12}{2005/05/10}{Shifted to using \cs{parindent} instead of \cs{everypar} to do indentation} +% 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. +% \begin{macrocode} +\newcommand\SB@beginverse{% + \ifSB@insong% + \ifSB@inverse\SB@errbvv\endverse\fi% + \ifSB@inchorus\SB@errbvc\endchorus\fi% + \else% + \SB@errbvt\beginsong{Unknown Song}% + \fi% + \ifrepchorus\ifvoid\SB@chorusbox\else% + \SB@gotchorustrue% + \ifSB@prevverse\ifvnumbered% + \marks\SB@cmarkclass{\SB@cmark}% + \fi\fi% + \fi\fi% + \SB@inversetrue% + \def\SB@closeall{\endverse\endsong}% + \SB@stanzabreak% + \versemark\nobreak% + \global\SB@stanzatrue% + \SB@ifempty\SB@cr@\memorize{\replay[]}% + \setbox\SB@box\vbox\bgroup\begingroup% + \ifvnumbered% + \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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@endverse} +% End a verse. +% This involves unboxing the verse material with |\SB@putbox|, which +% corrects for last lines that are unusually shallow. +% \begin{macrocode} +\newcommand\SB@endverse{% + \ifSB@insong% + \ifSB@inverse% + \unpenalty% + \endgroup\egroup% + \SB@putbox\unvbox\SB@box% + \SB@inversefalse% + \def\SB@closeall{\endsong}% + \ifvnumbered\stepcounter{versenum}\fi% + \SB@prevversetrue% + \else\ifSB@inchorus\SB@errevc\endchorus% + \else\SB@errevo\fi\fi% + \else% + \SB@errevt% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newif\ifSB@chorustop +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chorusbox} +% When |\repchoruses| is used, the first sequence of consecutive choruses +% is remembered in the following box register. +% \begin{macrocode} +\newbox\SB@chorusbox +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifSB@gotchorus} +% The following conditional remembers whether we've completed storing the +% first block of consecutive choruses. +% \begin{macrocode} +\newif\ifSB@gotchorus +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@cmarkclass} +% \begin{macro}{\SB@nocmarkclass} +% \changes{v2.6}{2008/02/14}{Added safe allocation of extended mark registers} +% The |\repeatchoruses| feature requires the use of two extended mark +% classes provided by $\varepsilon$-\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 +% $\varepsilon$-\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. +% \begin{macrocode} +\ifSB@etex + \@ifundefined{newmarks}{ + \@ifundefined{newmark}{ + \mathchardef\SB@cmarkclass83 + \mathchardef\SB@nocmarkclass84 + }{ + \newmark\SB@cmarkclass + \newmark\SB@nocmarkclass + } + }{ + \newmarks\SB@cmarkclass + \newmarks\SB@nocmarkclass + } +\fi +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@cmark} +% \begin{macro}{\SB@lastcmark} +% \begin{macro}{\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 $\varepsilon$-\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 already-inserted 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! +% \begin{macrocode} +\newcommand\SB@cmark{} +\def\SB@cmark{SB@cmark} +\newcommand\SB@lastcmark{} +\def\SB@lastcmark{SB@lastcmark} +\newcommand\SB@nocmark{} +\def\SB@nocmark{SB@nocmark} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{environment}{chorus}\MainEnvImpl{chorus} +% \begin{macro}{\beginchorus} +% \changes{v1.12}{2005/05/10}{Shifted to using \cs{parindent} instead of \cs{everypar} to do indentation} +% \changes{v1.14}{2005/05/15}{Choruses now stretch like the verses} +% 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. +% \begin{macrocode} +\newenvironment{chorus}{\beginchorus}{\SB@endchorus} +\newcommand\beginchorus{% + \ifSB@insong + \ifSB@inverse\SB@errbcv\endverse\fi% + \ifSB@inchorus\SB@errbcc\endchorus\fi% + \else% + \SB@errbct\beginsong{Unknown Song}% + \fi% + \SB@inchorustrue% + \def\SB@closeall{\endchorus\endsong}% + \SB@chorustoptrue% + \vnumberedfalse% + \SB@stanzabreak% + \chorusmark% + \ifrepchorus% + \ifSB@gotchorus\else\ifSB@prevverse\else% + \global\setbox\SB@chorusbox\vbox{% + \unvbox\SB@chorusbox% + \SB@stanzabreak% + \chorusmark% + }% + \fi\fi% + \fi% + \global\SB@stanzatrue% + \replay[]% + \SB@@beginchorus% + \everychorus\relax% +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@@beginchorus{% + \ifrepchorus\marks\SB@cmarkclass{}\fi% + \setbox\SB@box\vbox\bgroup\begingroup% + \ifchorded% + \def\SB@everypar{% + \vrule\@height\baselineskip\@width\z@\@depth\z@% + \gdef\SB@everypar{}% + }% + \everypar{\SB@everypar\everypar{}}% + \fi% + \chorusfont\chorusjustify% + \SB@loadactives% + \SB@obeylines% + \penalty12345 % +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@endchorus{% + \ifSB@insong% + \ifSB@inchorus% + \unpenalty% + \endgroup\egroup% + \SB@inchorusfalse% + \def\SB@closeall{\endsong}% + \setbox\SB@box\vbox{% + \SB@chorusbar\SB@box% + \SB@putbox\unvbox\SB@box% + } + \ifrepchorus\ifSB@gotchorus\else% + \global\setbox\SB@chorusbox\vbox{% + \unvbox\SB@chorusbox% + \unvcopy\SB@box% + }% + \fi\fi% + \unvbox\SB@box% + \SB@prevversefalse% + \else\ifSB@inverse\SB@errecv\endverse% + \else\SB@erreco\fi\fi% + \else% + \SB@errect% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@cbarshift} +% Increase |\leftskip| to accommodate the chorus bar, if any. +% \begin{macrocode} +\newcommand\SB@cbarshift{% + \ifSB@inchorus\ifdim\cbarwidth>\z@% + \advance\leftskip\cbarwidth% + \advance\leftskip5\p@\relax% + \fi\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@chorusbar[1]{% + \ifdim\cbarwidth>\z@% + \SB@dimen\ht#1% + \SB@dimenii\dp#1% + \advance\SB@dimen% + \ifSB@chorustop\ifchorded\else2\fi\fi\SB@dimenii% + \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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@computess} +% \changes{v1.14}{2005/05/15}{Added} +% This computes the stretchability or shrinkability of a vbox and stores +% the result in the skip register given by \argp{1}. +% If $\argp{2}=1$ and \argp{3} is ``\texttt{plus}'', then the stretchability +% of box \argp{4} is added to the plus component of \argp{1}. +% If $\argp{2}=-1$ and \argp{3} is ``\texttt{minus}'', then the shrinkability +% of the box is added to the minus component of \argp{1}. +% If the stretchability or shrinkability is infinite, then we guess 1fil +% for that component. +% \begin{macrocode} +\newcommand\SB@computess[4]{% + \begingroup% + \vbadness\@M\vfuzz\maxdimen% + \SB@dimen4096\p@% + \setbox\SB@box\vbox spread#2\SB@dimen{\unvcopy#4}% + \ifnum\badness=\z@% + \global\advance#1\z@#31fil\relax% + \else% + \SB@dimenii\SB@dimen% + \loop% + \SB@dimenii.5\SB@dimenii% + \ifnum\badness<100 % + \advance\SB@dimen\SB@dimenii% + \else + \advance\SB@dimen-\SB@dimenii% + \fi% + \setbox\SB@box\vbox spread#2\SB@dimen{\unvcopy#4}% + \ifnum\badness=100 \SB@dimenii\z@\fi% + \ifdim\SB@dimenii>.1\p@\repeat% + \ifdim\SB@dimen<.1\p@\SB@dimen\z@\fi% + \global\advance#1\z@#3\SB@dimen\relax% + \fi% + \endgroup% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\brk}\MainImpl{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. +% +% 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. +% \begin{macrocode} +\newcommand\brk{% + \ifSB@insong% + \ifhmode\penalty-5 \else% + \unpenalty% + \ifSB@inchorus% + \ifdim\cbarwidth=\z@% + \ifrepchorus\marks\SB@cmarkclass{}\fi% + \SB@breakpoint\brkpenalty% + \else% + \endgroup\egroup% + \ifrepchorus\ifSB@gotchorus\else% + \global\setbox\SB@chorusbox\vbox{% + \unvbox\SB@chorusbox% + \SB@chorusbar\SB@box% + \unvcopy\SB@box% + \SB@breakpoint\brkpenalty% + }% + \fi\fi% + \SB@chorusbar\SB@box% + \unvbox\SB@box% + \SB@breakpoint\brkpenalty% + \SB@chorustopfalse% + \SB@@beginchorus% + \fi% + \else% + \SB@breakpoint\brkpenalty% + \fi% + \fi% + \else% + \ifpartiallist\else\SB@nextcol\@ne\colbotglue\fi% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@boxup[1]{% + \setbox\SB@box\hbox{{\notefont#1}}% + \SB@dimen\wd\SB@box% + \advance\SB@dimen6\p@% + \advance\SB@dimen\leftskip% + \advance\SB@dimen\rightskip% + \ifdim\SB@dimen>\hsize% + \vbox{{% + \advance\hsize-6\p@% + \advance\hsize-\leftskip% + \advance\hsize-\rightskip% + \notejustify% + \unhbox\SB@box\par% + \kern\z@% + }}% + \else% + \vbox{\box\SB@box\kern\z@}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\textnote}\MainImpl{textnote} +% \changes{v1.12}{2005/05/10}{Defined unset paragraph parameters} +% 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. +% \begin{macrocode} +\newcommand\textnote[1]{% + \ifhmode\par\fi% + \ifnum\lastpenalty=12345\else% + \ifSB@inverse% + \vskip2\p@\relax% + \else\ifSB@inchorus% + \vskip2\p@\relax% + \else\ifSB@stanza% + \nobreak\vskip\versesep% + \fi\fi\fi% + \fi% + \begingroup% + \everypar{}% + \ifchorded\chordedfalse\SB@setbaselineskip\chordedtrue\fi% + \placenote{\SB@colorbox\notebgcolor{\SB@boxup{#1}}}% + \endgroup% + \nobreak% + \ifSB@inverse% + \vskip2\p@\relax% + \else\ifSB@inchorus% + \vskip2\p@\relax% + \else\ifSB@stanza\else% + \nobreak\vskip\versesep% + \fi\fi\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\musicnote}\MainImpl{musicnote} +% \changes{v1.12}{2005/05/10}{Now just (conditionally) calls \cs{textnote} for consistency} +% Create a textual note for musicians. +% \begin{macrocode} +\newcommand\musicnote[1]{\ifchorded\textnote{#1}\fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\echo}\MainImpl{echo} +% \begin{macro}{\SB@echo} +% \begin{macro}{\SB@@echo} +% \changes{v1.21}{2006/09/17}{Customized fonts now preserved.} +% \changes{v2.1}{2007/08/02}{Toggles instead of forces slanted font.} +% 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. +% +% 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 $\varepsilon$-\TeX\ then the solution is easy: we use +% |\scantokens| to re-scan 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 +% \emph{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.) +% \begin{macrocode} +\ifSB@etex + \newcommand\echo{\begingroup\@sanitize\SB@echo} + \newcommand\SB@echo[1]{% + \endgroup% + \begingroup% + \ifdim\fontdimen\@ne\font>\z@\upshape\else\slshape\fi% + \endlinechar\m@ne% + \scantokens{(#1)}% + \endgroup% + } +\else +% \end{macrocode} +% If we're not using $\varepsilon$-\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 $\varepsilon$-\TeX\ compatible. +% \begin{macrocode} + \newcommand\echo{% + \begingroup% + \ifdim\fontdimen\@ne\font>\z@\upshape\else\slshape\fi% + \afterassignment\SB@echo% + \setbox\SB@box\hbox% + } + \newcommand\SB@echo{\aftergroup\SB@@echo(} + \newcommand\SB@@echo{\unhbox\SB@box)\endgroup} +\fi +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\rep}\MainImpl{rep} +% \changes{v1.21}{2006/09/17}{Changed to avoid math mode.} +% Place |\rep{|\meta{n}|}| at the end of a line to indicate that it should be +% sung \meta{n} times. +% \begin{macrocode} +\newcommand\rep[1]{% + (\raise.25ex\hbox{% + \fontencoding{OMS}\fontfamily{cmsy}\selectfont\char\tw@% + }#1)% +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Scripture Quotations} +% +% The macros in this section typeset scripture quotations and other +% between-songs environments. +% +% \begin{environment}{songgroup}\MainEnvImpl{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. +% \begin{macrocode} +\newenvironment{songgroup}{% + \ifnum\SB@grouplvl=\z@% + \edef\SB@sgroup{\thesongnum}% + \global\SB@groupcnt\m@ne% + \fi% + \advance\SB@grouplvl\@ne% +}{% + \advance\SB@grouplvl\m@ne% + \ifnum\SB@grouplvl=\z@\let\SB@sgroup\@empty\fi% +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\SB@grouplvl} +% Count the |songgroup| environment nesting depth. +% \begin{macrocode} +\newcount\SB@grouplvl +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{intersong}\MainEnvImpl{intersong} +% 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. +% \begin{macrocode} +\newenvironment{intersong}{% + \ifSB@insong\SB@errbro\SB@closeall\fi% + \ifSB@intersong\SB@errbrr\SB@closeall\fi% + \setbox\SB@chorusbox\box\voidb@x% + \SB@intersongtrue% + \def\SB@closeall{\end{intersong}}% + \setbox\SB@songbox\vbox\bgroup\begingroup% + \ifnum\SB@numcols>\z@\hsize\SB@colwidth\fi% + \ifdim\sbarheight>\z@% + \hrule\@height\sbarheight\@width\hsize% + \nobreak% + \fi% +}{% + \ifSB@intersong + \ifdim\sbarheight>\z@% + \ifhmode\par\fi% + \SB@skip\lastskip% + \unskip\nobreak\vskip\SB@skip% + \hbox{\vrule\@height\sbarheight\@width\hsize}% + \fi% + \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% +} +% \end{macrocode} +% The starred form contributes page-spanning vertical material directly to +% the top of the nearest fresh page. +% \begin{macrocode} +\newenvironment{intersong*}{% + \ifSB@insong\SB@errbro\SB@closeall\fi% + \ifSB@intersong\SB@errbrr\SB@closeall\fi% + \setbox\SB@chorusbox\box\voidb@x% + \SB@intersongtrue% + \def\SB@closeall{\end{intersong*}}% + \setbox\SB@songbox\vbox\bgroup\begingroup% +}{% + \ifSB@intersong% + \endgroup\egroup% + \ifSB@omitscrip% + \setbox\SB@songbox\box\voidb@x% + \else% + \def\SB@stype{\SB@styppage}% + \SB@submitsong% + \def\SB@stype{\SB@stypcol}% + \fi% + \SB@intersongfalse% + \else% + \ifSB@insong\SB@errero\SB@closeall\else\SB@errert\fi% + \fi% +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\SB@srbox} +% The following box register holds the citation information that is to be +% typeset at the end of a scripture quotation. +% \begin{macrocode} +\newbox\SB@srbox +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{scripture}\MainEnvImpl{scripture} +% \begin{macro}{\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. +% \begin{macrocode} +\newenvironment{scripture}{\beginscripture}{\SB@endscripture} +\newcommand\beginscripture[1]{% + \begin{intersong}% + \SB@parsesrefs{#1}% + \setbox\SB@srbox\hbox{{\printscrcite\songrefs}}% + \def\SB@closeall{\endscripture}% + \nobreak\vskip5\p@% + \SB@parindent\parindent\parindent\z@% + \parskip\z@skip\parfillskip\@flushglue% + \leftskip\SB@parindent\rightskip\SB@parindent\relax% + \scripturefont% + \baselineskip\f@size\p@\@plus\p@\relax% + \advance\baselineskip\p@\relax% + \emergencystretch.3em% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@endscripture} +% End a scripture quotation. +% \begin{macrocode} +\newcommand\SB@endscripture{% + \ifSB@intersong + \scitehere% + \ifhmode\par\fi% + \vskip-3\p@% + \end{intersong}% + \fi% +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% +% \begin{macro}{\scitehere}\MainImpl{scitehere} +% \changes{v2.1}{2007/08/02}{Added} +% 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 \TeX book. +% 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. +% \begin{macrocode} +\newcommand\scitehere{% + \ifSB@intersong% + \ifvoid\SB@srbox\else% + \ifvmode% + \setbox\SB@box\lastbox% + \nointerlineskip\noindent\hskip-\leftskip% + \unhbox\SB@box\unskip% + \fi% + \unskip\nobreak\hfil\penalty50\hskip.8em\null\nobreak\hfil% + \box\SB@srbox\kern-\SB@parindent% + {\parfillskip\z@\finalhyphendemerits2000\par}% + \fi% + \else% + \SB@errscrip\scitehere% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\Acolon}\MainImpl{Acolon} +% \begin{macro}{\Bcolon}\MainImpl{Bcolon} +% \changes{v1.13}{2005/05/12}{Added} +% Typeset a line of poetry in a scripture quotation. +% \begin{macrocode} +\newcommand\Acolon{\SB@colon2\Acolon} +\newcommand\Bcolon{\SB@colon1\Bcolon} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@colon} +% Begin a group of temporary definitions that will end at the next +% \meta{return}. +% The \meta{return} will end the paragraph and close the local scope. +% \begin{macrocode} +\newcommand\SB@colon[2]{% + \ifSB@intersong\else% + \SB@errscrip#2% + \beginscripture{Unknown}% + \fi% + \ifhmode\par\fi% + \begingroup% + \rightskip\SB@parindent\@plus4em% + \advance\leftskip2\SB@parindent% + \advance\parindent-#1\SB@parindent% + \def\par{\endgraf\endgroup}% + \obeylines% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\strophe}\MainImpl{strophe} +% \changes{v1.13}{2005/05/12}{Added} +% Insert blank space indicative of a strophe division in a scripture quotation. +% \begin{macrocode} +\newcommand\strophe{% + \ifSB@intersong\else% + \SB@errscrip\strophe\beginscripture{Unknown}% + \fi% + \vskip.9ex\@plus.45ex\@minus.68ex\relax% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\scripindent}\MainImpl{scripindent} +% \begin{macro}{\scripoutdent}\MainImpl{scripoutdent} +% \begin{macro}{\SB@scripdent} +% \changes{v1.13}{2005/05/12}{Added} +% Create an indented sub-block within a scripture quotation. +% \begin{macrocode} +\newcommand\SB@scripdent[2]{% + \ifSB@intersong\else% + \SB@errscrip#2\beginscripture{Unknown}% + \fi% + \ifhmode\par\fi% + \advance\leftskip#1\SB@parindent\relax% +} +\newcommand\scripindent{\SB@scripdent1\scripindent} +\newcommand\scripoutdent{\SB@scripdent-\scripoutdent} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\shiftdblquotes}\MainImpl{shiftdblquotes} +% \changes{v1.13}{2005/05/12}{Added} +% \begin{macro}{\SB@ldqleft} +% \begin{macro}{\SB@ldqright} +% \begin{macro}{\SB@rdqleft} +% \begin{macro}{\SB@rdqright} +% \begin{macro}{\SB@scanlq} +% \begin{macro}{\SB@scanrq} +% \begin{macro}{\SB@dolq} +% \begin{macro}{\SB@dorq} +% The Zaph Chancery font used by default to typeset scripture quotations +% seems to have some kerning problems with double-quote ligatures. The +% |\shiftdblquotes| macro allows one to modify the spacing around all +% double-quotes until the current group ends. +% \begin{macrocode} +\newcommand\SB@quotesactive{% + \catcode`'\active% + \catcode``\active% +} +\newcommand\shiftdblquotes[4]{} +\newcommand\SB@ldqleft{} +\newcommand\SB@ldqright{} +\newcommand\SB@rdqleft{} +\newcommand\SB@rdqright{} +\newcommand\SB@scanlq{} +\newcommand\SB@scanrq{} +\newcommand\SB@dolq{} +\newcommand\SB@dorq{} +{ + \SB@quotesactive + \gdef\shiftdblquotes#1#2#3#4{% + \def\SB@ldqleft{\kern#1}% + \def\SB@ldqright{\kern#2}% + \def\SB@rdqleft{\kern#3}% + \def\SB@rdqright{\kern#4}% + \SB@quotesactive% + \def`{\futurelet\SB@next\SB@scanlq}% + \def'{\futurelet\SB@next\SB@scanrq}% + } + \gdef\SB@scanlq{% + \ifx\SB@next`% + \expandafter\SB@dolq% + \else% + \expandafter\lq% + \fi% + } + \gdef\SB@scanrq{% + \ifx\SB@next'% + \expandafter\SB@dorq% + \else% + \expandafter\rq% + \fi% + } + \gdef\SB@dolq`{% + \ifvmode\leavevmode\else\/\fi% + \vadjust{}% + \SB@ldqleft\lq\lq\SB@ldqright% + \vadjust{}% + } + \gdef\SB@dorq'{% + \ifvmode\leavevmode\else\/\fi% + \vadjust{}% + \SB@rdqleft\rq\rq\SB@rdqright% + \vadjust{}% + } +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \subsection{Transposition} +% +% The macros that transpose chords are contained in this section. +% +% \begin{macro}{\SB@transposefactor} +% This counter identifies the requested number of halfsteps by which chords are +% to be transposed (from $-11$ to $+11$). +% \begin{macrocode} +\newcount\SB@transposefactor +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifSB@convertnotes} +% 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. +% \begin{macrocode} +\newif\ifSB@convertnotes +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\notenameA} +% \begin{macro}{\notenameB} +% \begin{macro}{\notenameC} +% \begin{macro}{\notenameD} +% \begin{macro}{\notenameE} +% \begin{macro}{\notenameF} +% \begin{macro}{\notenameG} +% Reserve a control sequence for each note of the diatonic scale. +% These will be used to identify which token sequences the input file uses +% to denote the seven scale degrees. +% Their eventual definitions \emph{must} consist entirely of uppercase +% letters, and they must be assigned using |\def|, but that comes later. +% \begin{macrocode} +\newcommand\notenameA{} +\newcommand\notenameB{} +\newcommand\notenameC{} +\newcommand\notenameD{} +\newcommand\notenameE{} +\newcommand\notenameF{} +\newcommand\notenameG{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\printnoteA} +% \begin{macro}{\printnoteB} +% \begin{macro}{\printnoteC} +% \begin{macro}{\printnoteD} +% \begin{macro}{\printnoteE} +% \begin{macro}{\printnoteF} +% \begin{macro}{\printnoteG} +% These control sequences are what the transposition logic actually +% outputs to denote each scale degree. +% They can include any \LaTeX\ code that is legal in horizontal mode. +% \begin{macrocode} +\newcommand\printnoteA{} +\newcommand\printnoteB{} +\newcommand\printnoteC{} +\newcommand\printnoteD{} +\newcommand\printnoteE{} +\newcommand\printnoteF{} +\newcommand\printnoteG{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\notenamesin}\MainImpl{notenamesin} +% Set the note names used by the input file. +% \begin{macrocode} +\newcommand\notenamesin[7]{% + \def\notenameA{#1}% + \def\notenameB{#2}% + \def\notenameC{#3}% + \def\notenameD{#4}% + \def\notenameE{#5}% + \def\notenameF{#6}% + \def\notenameG{#7}% + \SB@convertnotestrue% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\notenamesout}\MainImpl{notenamesout} +% Set the note names that are output by the transposition logic. +% \begin{macrocode} +\newcommand\notenamesout[7]{% + \def\printnoteA{#1}% + \def\printnoteB{#2}% + \def\printnoteC{#3}% + \def\printnoteD{#4}% + \def\printnoteE{#5}% + \def\printnoteF{#6}% + \def\printnoteG{#7}% + \SB@convertnotestrue% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\notenames}\MainImpl{notenames} +% Set an identical input name and output name for each scale degree. +% \begin{macrocode} +\newcommand\notenames[7]{% + \notenamesin{#1}{#2}{#3}{#4}{#5}{#6}{#7}% + \notenamesout{#1}{#2}{#3}{#4}{#5}{#6}{#7}% + \SB@convertnotesfalse% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\alphascale}\MainImpl{alphascale} +% \begin{macro}{\solfedge}\MainImpl{solfedge} +% Predefine scales for alphabetic names and solfedge names, and +% set alphabetic scales to be the default. +% \begin{macrocode} +\newcommand\alphascale{\notenames ABCDEFG} +\newcommand\solfedge{\notenames{LA}{SI}{DO}{RE}{MI}{FA}{SOL}} +\alphascale +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\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$\flat$?) +% 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. +% \begin{macrocode} +\newif\ifSB@prefshrps +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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 if the current +% chord is the first one seen in the song, and should therefore be used to +% guess the key of the song. +% \begin{macrocode} +\newif\ifSB@needkey +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\transpose}\MainImpl{transpose} +% 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. +% \begin{macrocode} +\newcommand\transpose[1]{% + \advance\SB@transposefactor by#1\relax% + \SB@cnt\SB@transposefactor% + \divide\SB@cnt12 % + \multiply\SB@cnt12 % + \advance\SB@transposefactor-\SB@cnt% + \SB@needkeytrue% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\capo}\MainImpl{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. +% \begin{macrocode} +\newcommand\capo[1]{% + \iftranscapos\transpose{#1}\else\musicnote{capo #1}\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\prefersharps}\MainImpl{prefersharps} +% \begin{macro}{\preferflats}\MainImpl{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. +% \begin{macrocode} +\newcommand\prefersharps{\SB@prefshrpstrue\SB@needkeyfalse} +\newcommand\preferflats{\SB@prefshrpsfalse\SB@needkeyfalse} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\transposehere}\MainImpl{transposehere} +% If automatic transposition has been requested, yield the given chord +% transposed by the requested amount. +% Otherwise return the given chord verbatim. +% \begin{macrocode} +\newcommand\transposehere[1]{% + \ifnum\SB@transposefactor=\z@% + \ifSB@convertnotes% + \SB@dotranspose{#1}% + \the\SB@toks% + \else% + #1% + \fi% + \else% + \ifSB@convertnotes% + {\SB@transposefactor\z@% + \SB@dotranspose{#1}% + \xdef\SB@tempv{\the\SB@toks}}% + \else% + \def\SB@tempv{#1}% + \fi% + \SB@dotranspose{#1}% + \expandafter\trchordformat\expandafter{\SB@tempv}{\the\SB@toks}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\notrans}\MainImpl{notrans} +% Suppress chord transposition without suppressing note name conversion. +% When a |\notrans{|\meta{text}|}| 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. +% \begin{macrocode} +\newcommand\notrans[1]{% + \begingroup% + \SB@transposefactor\z@% + \transposehere{#1}% + \endgroup% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@dotranspose} +% Parse the argument to a chord macro, yielding the transposed equivalent in +% the |\SB@toks| token register. +% \begin{macrocode} +\newcommand\SB@dotranspose[1]{% + \SB@toks{}% + \let\SB@dothis\SB@trmain% + \SB@trscan#1\SB@trend% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\trchordformat}\MainImpl{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|. +% \begin{macrocode} +\newcommand\trchordformat[2]{#2} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@trscan{\futurelet\SB@next\SB@dothis} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@trmain} +% Test to see if 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. +% \begin{macrocode} +\newcommand\SB@trmain{% + \ifx\SB@next\bgroup% + \let\SB@donext\SB@trgroup% + \else\ifx\SB@next\egroup% + \SB@toks\expandafter{\the\SB@toks\egroup}% + \let\SB@donext\SB@trskip% + \else\ifcat\noexpand\SB@next\noexpand\@sptoken% + \SB@appendsp\SB@toks% + \let\SB@donext\SB@trskip% + \else% + \let\SB@donext\SB@trstep% + \fi\fi\fi% + \SB@donext% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@trgroup[1]{% + \SB@toks\expandafter{\the\SB@toks{#1}}% + \SB@trscan% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@trskip{% + \afterassignment\SB@trscan% + \let\SB@next= } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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 if 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. +% \begin{macrocode} +\newcommand\SB@trstep[1]{% + \let\SB@donext\SB@trscan% + \ifcat\noexpand\SB@next A% + \ifnum\uccode`#1=`#1% + \def\SB@temp{#1}% + \let\SB@dothis\SB@trnote% + \else% + \SB@toks\expandafter{\the\SB@toks#1}% + \fi% + \else\ifx\SB@next\SB@trend + \let\SB@donext\relax% + \else% + \SB@toks\expandafter{\the\SB@toks#1}% + \fi\fi% + \SB@donext% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@trnote} +% We're in the midst of processing a sequence of uppercase letters that +% might comprise a note name. +% Check to see if the next token is an accidental (sharp or flat), or yet +% another letter. +% \begin{macrocode} +\newcommand\SB@trnote{% + \ifcat\noexpand\SB@next A% + \let\SB@donext\SB@trnotestep% + \else\ifnum\SB@transposefactor=\z@% + \SB@cnt\z@% + \let\SB@donext\SB@trtrans% + \else\ifx\SB@next\flt% + \SB@cnt\m@ne% + \let\SB@donext\SB@tracc% + \else\ifx\SB@next\shrp% + \SB@cnt\@ne% + \let\SB@donext\SB@tracc% + \else% + \SB@cnt\z@% + \let\SB@donext\SB@trtrans% + \fi\fi\fi\fi% + \SB@donext% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@trnotestep} +% The next token is a letter. +% Consume it and test to see if 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. +% \begin{macrocode} +\newcommand\SB@trnotestep[1]{% + \ifnum\uccode`#1=`#1% + \expandafter\def\expandafter\SB@temp\expandafter{\SB@temp#1}% + \expandafter\SB@trscan% + \else% + \SB@cnt\z@% + \expandafter\SB@trtrans\expandafter#1% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@tracc[1]{\futurelet\SB@next\SB@trtrans} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@trtrans{% + \advance\SB@cnt% + \ifx\SB@temp\notenameA\z@% + \else\ifx\SB@temp\notenameB\tw@% + \else\ifx\SB@temp\notenameC\thr@@% + \else\ifx\SB@temp\notenameD5 % + \else\ifx\SB@temp\notenameE7 % + \else\ifx\SB@temp\notenameF8 % + \else\ifx\SB@temp\notenameG10 % + \else-99 \fi\fi\fi\fi\fi\fi\fi% + \ifnum\SB@cnt<\m@ne% + \SB@toks\expandafter\expandafter\expandafter{% + \expandafter\the\expandafter\SB@toks\SB@temp}% + \else% + \advance\SB@cnt\SB@transposefactor% + \ifnum\SB@cnt<\z@\advance\SB@cnt12 \fi% + \ifnum\SB@cnt>11 \advance\SB@cnt-12 \fi% + \ifSB@needkey\ifnum\SB@transposefactor=\z@\else\SB@setkeysig\fi\fi% + \edef\SB@temp{% + \the\SB@toks% + \ifSB@prefshrps% + \ifcase\SB@cnt\printnoteA\or\printnoteA\noexpand\shrp\or% + \printnoteB\or\printnoteC\or\printnoteC\noexpand\shrp\or% + \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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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). +% \begin{macrocode} +\newcommand\SB@setkeysig{% + \global\SB@needkeyfalse% + \ifcase\SB@cnt% + \global\SB@prefshrpstrue\or% A + \global\SB@prefshrpsfalse\or% Bb + \global\SB@prefshrpstrue\or% B + \ifx\SB@next m% C + \global\SB@prefshrpsfalse% + \else% + \global\SB@prefshrpstrue% + \fi\or% + \global\SB@prefshrpstrue\or% C# + \ifx\SB@next m% D + \global\SB@prefshrpsfalse% + \else% + \global\SB@prefshrpstrue% + \fi\or% + \global\SB@prefshrpsfalse\or% Eb + \global\SB@prefshrpstrue\or% E + \global\SB@prefshrpsfalse\or% F + \global\SB@prefshrpstrue\or% F# + \ifx\SB@next m% G + \global\SB@prefshrpsfalse% + \else% + \global\SB@prefshrpstrue% + \fi\or% + \global\SB@prefshrpsfalse\else% Ab + \global\SB@needkeytrue% non-chord + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@trend{% + \SB@Error{Internal Error: Transposition failed}% + {This error should not occur.}% +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Measure Bars} +% +% The following code handles the typesetting of measure bars. +% +% \begin{macro}{\SB@metertop} +% \begin{macro}{\SB@meterbot} +% These macros remember the current numerator and denominator of the meter. +% \begin{macrocode} +\newcommand\SB@metertop{} +\newcommand\SB@meterbot{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\meter}\MainImpl{meter} +% Set the current meter without producing an actual measure bar yet. +% \begin{macrocode} +\newcommand\meter[2]{\gdef\SB@metertop{#1}\gdef\SB@meterbot{#2}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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 if this measure bar immediately follows another measure bar +% by using |\vsplit| on |\lastbox|. +% \begin{macrocode} +\newcommand\SB@measuremark{SB@IsMeasure} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@makembar}\MainImpl{mbar} +% Typeset a measure bar. If provided, \argp{1} is the numerator and \argp{2} 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. +% \begin{macrocode} +\newcommand\SB@makembar[2]{% + \ifSB@inverse\else% + \ifSB@inchorus\else\SB@errmbar\fi% + \fi% + \ifhmode% + \SB@skip\lastskip\unskip% + \setbox\SB@box\lastbox% + \copy\SB@box% + \ifvbox\SB@box% + \begingroup% + \setbox\SB@boxii\copy\SB@box% + \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% + }% + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mbar} +% The |\mbar| macro invokes |\SB@mbar|, which gets redefined by macros and +% options that turn measure bars on and off. +% \begin{macrocode} +\newcommand\mbar{\SB@mbar} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\measurebar}\MainImpl{measurebar} +% 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. +% \begin{macrocode} +\newcommand\measurebar{% + \mbar\SB@metertop\SB@meterbot% + \meter{}{}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@repcolon} +% Create the colon that preceeds or follows a repeat sign. +% \begin{macrocode} +\newcommand\SB@repcolon{{% + \usefont{OT1}{cmss}{m}{n}\selectfont% + \ifchorded% + \baselineskip.5\SB@dimen% + \vbox{\hbox{:}\hbox{:}\kern.5\p@}% + \else% + \raise.5\p@\hbox{:}% + \fi% +}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\lrep}\MainImpl{lrep} +% Create a begin-repeat sign. +% \begin{macrocode} +\newcommand\lrep{% + \SB@dimen\baselineskip% + \advance\SB@dimen-2\p@% + \vrule\@width1.5\p@\@height\SB@dimen\@depth\p@% + \kern1.5\p@% + \vrule\@width.5\p@\@height\SB@dimen\@depth\p@% + \SB@repcolon% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\rrep}\MainImpl{rrep} +% Create an end-repeat sign. +% \begin{macrocode} +\newcommand\rrep{% + \SB@dimen\baselineskip% + \advance\SB@dimen-2\p@% + \SB@repcolon% + \vrule\@width.5\p@\@height\SB@dimen\@depth\p@% + \kern1.5\p@% + \vrule\@width1.5\p@\@height\SB@dimen\@depth\p@% +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Lyric Scanning}\label{sec:lyricscan} +% +% 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{|\meta{chordname}|{|\meta{lyric}|}|. +% 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 \meta{lyric} parameter and +% what part should be typed after the closing brace. +% To avoid separating a word from its trailing punctuation, the +% \meta{lyric} 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. +% +% \begin{macro}{\ifSB@wordends} +% \begin{macro}{\ifSB@brokenword} +% Chord macros must look ahead in the input stream to see if 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. +% \begin{macrocode} +\newif\ifSB@wordends +\newif\ifSB@brokenword +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@lyric} +% Lyrics appearing after a chord are scanned into the following token list +% register. +% \begin{macrocode} +\newtoks\SB@lyric +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@numhyps} +% 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. +% \begin{macrocode} +\newcount\SB@numhyps +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@lyricnohyp} +% 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. +% \begin{macrocode} +\newtoks\SB@lyricnohyp +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@lyricbox} +% \begin{macro}{\SB@chordbox} +% 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. +% \begin{macrocode} +\newbox\SB@lyricbox +\newbox\SB@chordbox +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@chbstok} +% \changes{v1.22}{2007/05/15}{Added.} +% When |\MultiwordChords| is active, the following reserved control +% sequence remembers the first (space) token not yet included into the +% |\SB@lyricbox| box. +% \begin{macrocode} +\newcommand\SB@chbstok{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@setchord} +% \changes{v2.3}{2007/09/23}{Support replayed chords over ligatures} +% \changes{v2.7}{2009/01/08}{Extend rather than replace chordbox} +% 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. +% \begin{macrocode} +\newcommand\SB@setchord{} +{ + \catcode`^\active + \catcode`!7 + \gdef\SB@setchord#1{% + \SB@gettabindtrue\SB@nohattrue% + \setbox\SB@chordbox\hbox{% + \unhbox\SB@chordbox% + \begingroup% + \ifSB@trackch% + \def\SB@activehat{\ifmmode!\else\global\SB@nohatfalse\fi}% + \else% + \def\SB@activehat{% + \ifmmode!\else\SB@lop\SB@ctail\SB@toks\the\SB@toks\fi% + }% + \fi% + \let^\SB@activehat% + \printchord{% + \ifSB@firstchord\else\kern.15em\fi% + \vphantom/% + \transposehere{#1}% + \kern.2em% + }% + \endgroup% + }% + \SB@gettabindfalse% + \ifSB@trackch\ifSB@nohat% + \global\SB@creg\expandafter{\the\SB@creg#1\\}% + \fi\fi% + \let\SB@noreplay\@firstofone% + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@outertest} +% \begin{macro}{\SB@@outertest} +% The lyric-scanning code must preemptively determine if 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 if a +% token is |\outer| is a delicate process. +% The following does so by consulting |\meaning|. +% \begin{macrocode} +\newcommand\SB@outertest{} +\edef\SB@outertest#1{% + \noexpand\SB@@outertest#1% + \string\outer% + \noexpand\SB@@outertest% +} +\newcommand\SB@@outertest{} +\expandafter\def\expandafter\SB@@outertest% +\expandafter#\expandafter1\string\outer#2\SB@@outertest{% + \def\SB@temp{#2}% + \ifx\SB@temp\@empty\else\SB@testtrue\fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@UTFtest} +% \begin{macro}{\SB@two} +% \begin{macro}{\SB@three} +% \begin{macro}{\SB@four} +% \begin{macro}{\SB@UTFtester} +% \changes{v1.22}{2007/05/15}{Added.} +% 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@|$\ldots$|@octets| in the top-level expansion of the macro. +% \begin{macrocode} +\newcommand\SB@UTFtest{} +\edef\SB@UTFtest#1{% + \noexpand\SB@UTFtester#1% + \string\UTFviii@zero@octets% + \noexpand\SB@UTFtester% +} +\begingroup + \escapechar\m@ne + \xdef\SB@two{\string\two} + \xdef\SB@three{\string\three} + \xdef\SB@four{\string\four} + \xdef\SB@temp{\string\@octets} +\endgroup +\edef\SB@temp{##1\string\UTFviii@##2\SB@temp##3} +\expandafter\def\expandafter\SB@UTFtester\SB@temp\SB@UTFtester{% + \def\SB@temp{#2}% + \ifx\SB@temp\SB@two% + \SB@cnt\tw@% + \else\ifx\SB@temp\SB@three% + \SB@cnt\thr@@% + \else\ifx\SB@temp\SB@four% + \SB@cnt4 % + \else% + \SB@cnt\z@% + \fi\fi\fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\DeclareLyricChar}\MainImpl{DeclareLyricChar} +% \begin{macro}{\DeclareNonLyric}\MainImpl{DeclareNonLyric} +% \begin{macro}{\DeclareNoHyphen}\MainImpl{DeclareNoHyphen} +% \begin{macro}{\SB@declare} +% \changes{v1.22}{2007/05/15}{Added \cs{DeclareLyricChar}.} +% \changes{v2.1}{2007/08/02}{Added \cs{DeclareNonLyric} and \cs{DeclareNoHyphen}.} +% \changes{v2.6}{2008/03/27}{Macro tests made name-based instead of def-based} +% 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 lyric-ending. +% \begin{macrocode} +\newcommand\SB@declare[3]{% + \afterassignment\iffalse\let\SB@next= #3\relax\fi% + \expandafter\SB@UTFtest\expandafter{\meaning\SB@next}% + \ifcase\SB@cnt% + \ifcat\noexpand#3\relax% + \SB@addNtest\SB@macrotests#1#2#3% + \else\ifcat\noexpand#3.% + \SB@addDtest\SB@othertests#1#2#3% + \else\ifcat\noexpand#3A% + \SB@addDtest\SB@lettertests#1#2#3% + \else% + \SB@addDtest\relax0#2#3% + \fi\fi\fi% + \or% + \SB@addNtest\SB@macrotests#1#2#3% + \else% + \SB@addMtest\SB@multitests#1#2{#3}% + \fi% +} +\newcommand\DeclareLyricChar{\SB@declare\SB@testtrue0} +\newcommand\DeclareNonLyric{% + \SB@declare\SB@testfalse\SB@testfalse% +} +\newcommand\DeclareNoHyphen{% + \SB@declare\SB@testfalse\SB@testtrue% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@lettertests} +% \begin{macro}{\SB@macrotests} +% \begin{macro}{\SB@multitests} +% \begin{macro}{\SB@othertests} +% \begin{macro}{\SB@hyphtests} +% For speed, token tests introduced by |\DeclareLyricChar| and friends +% are broken out into separate macros based on category codes. +% \begin{macrocode} +\newcommand\SB@lettertests{} +\newcommand\SB@macrotests{} +\newcommand\SB@multitests{} +\newcommand\SB@othertests{} +\newcommand\SB@hyphtests{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% The following macros add tests to the test macros defined above. +% In each, \argp{1} is the test macro to which the test should be added, +% \argp{2} and \argp{3} 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 \argp{4} is the token to which the currently scanned +% token should be compared to determine if it matches. +% +% \begin{macro}{\SB@addtest} +% Append the top-level expansion of \argp{2} to the control sequence name +% given by \argp{1}. +% \begin{macrocode} +\newcommand\SB@addtest[2]{% + \expandafter\gdef\expandafter#1\expandafter{#1#2}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@addDtest} +% A definition-test: The test succeeds if the \emph{definition} at test-time +% of the next lyric token matches the \emph{definition at test-time} of +% the control sequence that was given to the |\Declare| macro. +% \begin{macrocode} +\newcommand\SB@addDtest[4]{% + \ifx0#2\else\SB@addtest#1{\ifx\SB@next#4#2\fi}\fi% + \ifx0#3\else\SB@addtest\SB@hyphtests{\ifx\SB@next#4#3\fi}\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@addNtest} +% A name-test: The test succeeds if the next token is a non-|\outer| +% macro or active character and its |\string|ified name matches the +% |\string|ified name of the control sequence that was given to the +% |\Declare| macro. +% \begin{macrocode} +\newcommand\SB@addNtest[4]{% + \ifx0#2\else% + \SB@addtest#1{% + \edef\SB@temp{\string#4}\ifx\SB@temp\SB@nextname#2\fi% + }% + \fi% + \ifx0#3\else% + \SB@addtest\SB@hyphtests{% + \edef\SB@temp{\string#4}\ifx\SB@temp\SB@nextname#3\fi% + }% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@addMtest[4]{% + \ifx0#2\else% + \SB@addtest#1{\def\SB@temp{#4}\ifx\SB@next\SB@temp#2\fi}% + \fi% + \ifx0#3\else\SB@addtest\SB@hyphtests{% + \def\SB@temp{#4}\ifx\SB@next\SB@temp#3\fi}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% The following code declares the common intra-word macros provided by +% \TeX\ (as listed on p.~52 of The \TeX book) to be lyric-continuing. +% \begin{macrocode} +\DeclareLyricChar\` +\DeclareLyricChar\' +\DeclareLyricChar\^ +\DeclareLyricChar\" +\DeclareLyricChar\~ +\DeclareLyricChar\= +\DeclareLyricChar\. +\DeclareLyricChar\u +\DeclareLyricChar\v +\DeclareLyricChar\H +\DeclareLyricChar\t +\DeclareLyricChar\c +\DeclareLyricChar\d +\DeclareLyricChar\b +\DeclareLyricChar\oe +\DeclareLyricChar\OE +\DeclareLyricChar\ae +\DeclareLyricChar\AE +\DeclareLyricChar\aa +\DeclareLyricChar\AA +\DeclareLyricChar\o +\DeclareLyricChar\O +\DeclareLyricChar\l +\DeclareLyricChar\L +\DeclareLyricChar\ss +\DeclareLyricChar\i +\DeclareLyricChar\j +\DeclareLyricChar\/ +\DeclareLyricChar\- +\DeclareLyricChar\discretionary +% \end{macrocode} +% +% 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. +% \begin{macrocode} +\DeclareNoHyphen\par +% \end{macrocode} +% +% \begin{macro}{\SB@bracket} +% This macro gets invoked by the |\[|\eat\] macro whenever a chord begins. +% It gets redefined by code that turns chords on and off, so its initial +% definition doesn't matter. +% \begin{macrocode} +\newcommand\SB@bracket{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chord} +% 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. +% \begin{macrocode} +\newcommand\SB@chord{\SB@begincname\SB@@chord} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@begincname} +% \begin{macro}{\SB@endcname} +% 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 \meta{return} 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 +% \textsf{Babel} French package and the |\gtab| macro. +% \begin{macrocode} +\newcommand\SB@begincname{} +{\catcode`\^^M\active + \gdef\SB@begincname{% + \begingroup% + \catcode`##\active\catcode`&\active% + \catcode`:12\relax% + \catcode`\^^M\active\SB@outer\def^^M{}% + \SB@outer\def\[{}% + \chordlocals% + } +} +\newcommand\SB@endcname{} +\let\SB@endcname\endgroup +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\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 \textsf{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 +% |~|. +% \begin{macrocode} +\newcommand\SB@nbsp{} +\def\SB@nbsp{\nobreakspace{}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@firstchord} +% The following conditional is true when the current chord is the first +% chord in a sequence of one or more chord macros. +% \begin{macrocode} +\newif\ifSB@firstchord\SB@firstchordtrue +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@@chord} +% 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. +% \begin{macrocode} +\newcommand*\SB@@chord{} +\def\SB@@chord#1]{% + \SB@endcname% + \ifSB@firstchord% + \setbox\SB@lyricbox\hbox{\kern\SB@tabindent}% + \global\SB@tabindent\z@% + \SB@lyric{}% + \SB@numhyps\z@% + \SB@spcinit% + \setbox\SB@chordbox\box\voidb@x% + \fi% + \SB@setchord{#1}% + \SB@firstchordfalse% + \let\SB@dothis\SB@chstart% + \SB@chscan% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\MultiwordChords}\MainImpl{MultiwordChords} +% \begin{macro}{\SB@spcinit} +% \changes{v1.22}{2007/05/15}{Added.} +% 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. +% \begin{macrocode} +\newcommand\SB@spcinit{} +\newcommand\MultiwordChords{% + \def\SB@spcinit{% + \let\SB@chdone\SB@chlyrdone% + \def\SB@chimpspace{\let\SB@donext\SB@chdone}% + \def\SB@chexpspace{\let\SB@donext\SB@chdone}% + \let\SB@chespace\SB@chendspace% + }% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@chscan} +% \begin{macro}{\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|). +% \begin{macrocode} +\newcommand\SB@chscan{% + \let\SB@nextname\relax% + \futurelet\SB@next\SB@chmain% +} +\newcommand\SB@chmain{\SB@dothis\SB@donext} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% Warning: In the lyric-scanner macros that follow, |\SB@next| +% might be a macro declared |\outer|. +% This means that it must \emph{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. +% +% \begin{macro}{\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 \emph{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. +% \begin{macrocode} +\newcommand\SB@chstart{% + \ifx\SB@next\[% + \let\SB@donext\relax% + \else\ifx\SB@next\SB@activehat% + \let\SB@donext\relax% + \else\ifx\SB@next\ch% + \let\SB@donext\relax% + \else\ifx\SB@next\mch% + \let\SB@donext\relax% + \else\ifx\SB@next`% + \let\SB@donext\SB@chstep% + \else\ifx\SB@next'% + \let\SB@donext\SB@chstep% + \else\ifx\SB@next"% + \let\SB@donext\SB@chstep% + \else% + \the\SB@lyric% + \SB@lyric{}% + \SB@firstchordtrue% + \let\SB@dothis\SB@chnorm% + \SB@chnorm% + \fi\fi\fi\fi\fi\fi\fi% +} +% \end{macrocode} +% \end{macro} +% \eat\] +% +% \begin{macro}{\SB@chnorm} +% \changes{v2.0}{2007/06/18}{Rewritten for speed} +% First, check to see if the lyric token is a letter. +% Since that's the most common case, we do this check first for speed. +% \begin{macrocode} +\newcommand\SB@chnorm{% + \ifcat\noexpand\SB@next A% + \SB@testtrue\SB@lettertests% + \ifSB@test% + \SB@chespace\let\SB@donext\SB@chstep% + \else% + \let\SB@donext\SB@chdone% + \fi% + \else% + \SB@chtrymacro% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chtrymacro} +% Next, check to see if 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. +% \begin{macrocode} +\newcommand\SB@chtrymacro{% + \ifcat\noexpand\SB@next\relax% + \SB@chmacro% + \else% + \SB@chother% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@chother{% + \ifcat\noexpand\SB@next\noexpand\@sptoken% + \SB@chexpspace% + \else\ifcat\noexpand\SB@next\noexpand\bgroup% + \SB@chespace\let\SB@donext\SB@chbgroup% + \else\ifcat\noexpand\SB@next\noexpand\egroup% + \SB@chespace\let\SB@donext\SB@chegroup% + \else\ifx\SB@next-% + \SB@numhyps\@ne\relax% + \SB@lyricnohyp\expandafter{\the\SB@lyric}% + \let\SB@dothis\SB@chhyph% + \SB@chespace\let\SB@donext\SB@chstep% + \else\ifcat\noexpand\SB@next.% + \SB@testtrue\SB@othertests% + \ifSB@test% + \SB@chespace\let\SB@donext\SB@chstep% + \else% + \let\SB@donext\SB@chdone% + \fi% + \else% + \SB@chespace\let\SB@donext\SB@chstep% + \fi\fi\fi\fi\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chmacro} +% \changes{v1.22}{2007/05/15}{Added support for UTF-8.} +% 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. +% \begin{macrocode} +\newcommand\SB@chmacro{% + \SB@testfalse% + \expandafter\SB@outertest\expandafter{\meaning\SB@next}% + \ifSB@test% + \let\SB@donext\SB@chdone% + \else% + \let\SB@donext\SB@chgetname% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@chgetname[1]{% + \edef\SB@nextname{\string#1}% + \SB@@chmacro\SB@donext#1% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@@chmacro} +% The lyric-scanner has encountered a non-|\outer| macro or active character. +% Its |\string|ified name has been stored in |\SB@nextname|. +% Test to see if 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. +% \begin{macrocode} +\newcommand\SB@@chmacro{% + \ifx\SB@next\SB@activehat% + \let\SB@donext\SB@chdone% + \else\ifx\SB@next\SB@par% + \let\SB@donext\SB@chdone% + \else\ifx\SB@next\measurebar% + \SB@chmbar% + \else\ifx\SB@next\mbar% + \SB@chmbar% + \else\ifx\SB@next\ch% + \SB@chespace\let\SB@donext\SB@chlig% + \else\ifx\SB@next\mch% + \SB@chespace\let\SB@donext\SB@mchlig% + \else\ifx\SB@next\ % + \SB@chimpspace% + \else\ifx\SB@next\SB@nbsp% + \SB@chimpspace% + \else% + \expandafter\SB@UTFtest\expandafter{\meaning\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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chothermac} +% \changes{v2.6}{2008/03/26}{All active chars now included in lyrics by default.} +% 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 if 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. +% \begin{macrocode} +\newcommand\SB@chothermac{% + \SB@testfalse% + \afterassignment\iffalse% + \SB@cnt\expandafter`\SB@nextname x\fi% + \ifnum\the\catcode\SB@cnt=\z@\else\SB@testtrue\fi% + \SB@macrotests% + \ifSB@test% + \SB@chespace\let\SB@donext\SB@chstep% + \else% + \let\SB@donext\SB@chdone% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chstep} +% \begin{macro}{\SB@chsteptwo} +% \begin{macro}{\SB@chstepthree} +% \begin{macro}{\SB@chstepfour} +% \begin{macro}{\SB@chmulti} +% \begin{macro}{\SB@chmstop} +% We've encountered one or more tokens that should be included in the +% lyric text. +% (More than one means we've encountered a multibyte encoding of an +% international character.) +% Consume them (as arguments to this macro) and add them to the list +% of tokens we've already consumed. +% \begin{macrocode} +\newcommand\SB@chstep[1]{% + \SB@lyric\expandafter{\the\SB@lyric#1}% + \SB@chscan% +} +\newcommand\SB@chsteptwo[2]{\SB@chmulti{#1#2}} +\newcommand\SB@chstepthree[3]{\SB@chmulti{#1#2#3}} +\newcommand\SB@chstepfour[4]{\SB@chmulti{#1#2#3#4}} +\newcommand\SB@chmulti[1]{% + \def\SB@next{#1}% + \let\SB@nextname\relax% + \SB@testtrue\SB@multitests% + \ifSB@test% + \SB@lyric\expandafter{\the\SB@lyric#1}% + \expandafter\SB@chscan% + \else% + \expandafter\SB@chmstop% + \fi% +} +\newcommand\SB@chmstop{\expandafter\SB@chdone\SB@next} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@chhyph} +% We've encountered a hyphen. +% Continue to digest hyphens, but terminate as soon as we see anything +% else. +% \begin{macrocode} +\newcommand\SB@chhyph{% + \ifx\SB@next-% + \advance\SB@numhyps\@ne\relax% + \let\SB@donext\SB@chstep% + \else% + \let\SB@donext\SB@chdone% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chimpspace} +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@chimpspace{\let\SB@donext\SB@chdone} +\newcommand\SB@chexpspace{\let\SB@donext\SB@chdone} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@chespace} +% \begin{macro}{\SB@chendspace} +% \changes{v1.22}{2007/05/15}{Added.} +% The |\SB@chespace| macro gets invoked by the lyric-scanner just before a +% non-space 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. +% \begin{macrocode} +\newcommand\SB@chespace{} +\newcommand\SB@chendspace{% + \let\SB@chdone\SB@chlyrdone% + \def\SB@chexpspace{\SB@chbspace\SB@chexpspace}% + \def\SB@chimpspace{\SB@chbspace\SB@chimpspace}% + \def\SB@chespace{}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@chbspace} +% \begin{macro}{\SB@chgetspace} +% \changes{v1.22}{2007/05/15}{Added.} +% 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. +% \begin{macrocode} +\newcommand\SB@chbspace{% + \setbox\SB@lyricbox\hbox{% + \unhbox\SB@lyricbox% + \the\SB@lyric% + }% + \SB@lyric{}% + \ifdim\wd\SB@lyricbox<\wd\SB@chordbox% + \let\SB@chbstok= \SB@next% + \def\SB@chexpspace{\let\SB@donext\SB@chgetspace}% + \def\SB@chimpspace{\let\SB@donext\SB@chstep}% + \let\SB@chespace\SB@chendspace% + \let\SB@chdone\SB@chspcdone% + \else% + \def\SB@chimpspace{\let\SB@donext\SB@chdone}% + \def\SB@chexpspace{\let\SB@donext\SB@chdone}% + \fi% +} +\newcommand\SB@chgetspace{% + \SB@appendsp\SB@lyric% + \let\SB@nextname\relax% + \afterassignment\SB@chscan% + \let\SB@next= } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@chmbar} +% We've encountered a measure bar. +% Either ignore it or end the lyric text, depending on whether +% measure bars are being displayed. +% \begin{macrocode} +\newcommand\SB@chmbar{% + \ifmeasures% + \let\SB@donext\SB@chdone% + \else% + \SB@chespace\let\SB@donext\SB@chstep% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@chbgroup[1]{% + \SB@lyric\expandafter{\the\SB@lyric{#1}}% + \SB@chscan% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chegroup} +% \begin{macro}{\SB@chegrpscan} +% \begin{macro}{\SB@chegrpmacro} +% \begin{macro}{\SB@chegrpouter} +% \begin{macro}{\SB@chegrpname} +% \begin{macro}{\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 |\string|ified 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. +% \begin{macrocode} +\newcommand\SB@chegroup{% + \let\SB@nextname\relax% + \afterassignment\SB@chegrpscan% + \let\SB@next= } +\newcommand\SB@chegrpscan{% + \futurelet\SB@next\SB@chegrpmacro% +} +\newcommand\SB@chegrpmacro{% + \ifcat\noexpand\SB@next\relax% + \expandafter\SB@chegrpouter% + \else% + \expandafter\SB@chegrpdone% + \fi% +} +\newcommand\SB@chegrpouter{% + \SB@testfalse% + \expandafter\SB@outertest\expandafter{\meaning\SB@next}% + \ifSB@test% + \expandafter\SB@chegrpdone% + \else% + \expandafter\SB@chegrpname% + \fi% +} +\newcommand\SB@chegrpname[1]{% + \edef\SB@nextname{\string#1}% + \SB@chegrpdone#1% +} +\newcommand\SB@chegrpdone{\SB@chdone\egroup} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@chlig} +% \begin{macro}{\SB@mchlig} +% We've encountered a |\ch| chord-over-ligature macro, or an +% |\mch| measurebar-and-chord-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 if we decide to add hyphenation.) +% Then end the lyric text here. +% \begin{macrocode} +\newcommand\SB@chlig[5]{% + \gdef\SB@ligpre{{#3}}% + \gdef\SB@ligpost{\[#2]{#4}}% + \gdef\SB@ligfull{\[\SB@noreplay{\hphantom{{\lyricfont#3}}}#2]{#5}}% + \SB@chdone% +} +\newcommand\SB@mchlig[5]{% + \SB@lyric\expandafter{\the\SB@lyric#3}% + \let\SB@next\measurebar% + \edef\SB@nextname{\string\measurebar}% + \gdef\SB@ligpost{\measurebar\[#2]{#4}}% + \gdef\SB@ligfull{\measurebar\[#2]{#4}}% + \SB@chdone% +} +% \end{macrocode} +% \eat\] +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@chdone} +% \begin{macro}{\SB@chlyrdone} +% \begin{macro}{\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|. +% \begin{macrocode} +\newcommand\SB@chlyrdone{% + \setbox\SB@lyricbox\hbox{% + \unhbox\SB@lyricbox% + \ifnum\SB@numhyps=\@ne% + \the\SB@lyricnohyp% + \else% + \the\SB@lyric% + \fi% + }% + \SB@emitchord% +} +\newcommand\SB@chspcdone{% + \let\SB@nextname\relax% + \let\SB@next= \SB@chbstok% + \expandafter\SB@emitchord\the\SB@lyric% +} +\newcommand\SB@chdone{} +\let\SB@chdone\SB@chlyrdone +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@ligpre} +% \begin{macro}{\SB@ligpost} +% \begin{macro}{\SB@ligfull} +% The following three macros record arguments passed to a |\ch| macro that +% concludes the lyric text of the |\[]|\eat\] macro currently being processed. +% \begin{macrocode} +\newcommand\SB@ligpre{} +\newcommand\SB@ligpost{} +\newcommand\SB@ligfull{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@clearlig} +% Clear all ligature-chord registers. +% \begin{macrocode} +\newcommand\SB@clearlig{% + \gdef\SB@ligpre{}% + \gdef\SB@ligpost{}% + \gdef\SB@ligfull{}% +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Chords} +% +% \begin{macro}{\SB@emitchord}\MainImpl{[} +% \changes{v1.12}{2005/05/10}{Inhibited hyphenation of trailing punctuation} +% \changes{v1.13}{2005/05/12}{Added code to preserve the spacefactor} +% \changes{v1.16}{2005/07/23}{Chord macros massively reorganized to take lyrics as implicit rather than explicit arguments} +% 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 \S\ref{sec:lyricscan} to the token that immediately +% follows the lyric under this chord, to determine whether the lyric text +% ends on a word boundary. +% \begin{macrocode} +\newcommand\SB@emitchord{% + \ifSB@inverse\else\ifSB@inchorus\else\SB@errchord\fi\fi% + \SB@testfalse% + \ifcat\noexpand\SB@next\noexpand\@sptoken\SB@testtrue\fi% + \ifcat\noexpand\SB@next.\SB@testtrue\fi% + \ifx\SB@next\SB@par\SB@testtrue\fi% + \ifx\SB@next\egroup\SB@testtrue\fi% + \ifx\SB@next\endgroup\SB@testtrue\fi% + \SB@hyphtests% + \ifSB@test\SB@wordendstrue\else\SB@wordendsfalse\fi% +% \end{macrocode} +% Next, compare the width of the lyric to the width of the chord to +% determine if 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. +% \begin{macrocode} + \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% + \fi% + \fi% +% \end{macrocode} +% If lyrics are suppressed on this line (e.g., by using |\nolyrics|), then just +% typeset the chord text on the natural baseline. +% \begin{macrocode} + \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% +% \end{macrocode} +% Otherwise, typeset the chord above the lyric on a double-height line. +% \begin{macrocode} + \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% + }% +% \end{macrocode} +% 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. +% \begin{macrocode} + \ifSB@wordends% + \ifdim\wd\SB@lyricbox>\z@\else\nobreak\fi% + \else% + \penalty% + \ifnum\SB@numhyps>\z@\exhyphenpenalty% + \else\ifSB@brokenword\hyphenpenalty% + \else\@M\fi\fi% + \spacefactor\SB@cnt% + \fi% + \fi% +% \end{macrocode} +% 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. +% \begin{macrocode} + \SB@temp% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@accidental[1]{{% + \/% + \m@th#1% + \SB@dimen-\fontdimen\@ne\font% + \advance\SB@dimen.088142\p@% + \ifdim\SB@dimen<\z@% + \kern\f@size\SB@dimen% + \fi% +}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sharpsymbol}\MainImpl{sharpsymbol} +% \begin{macro}{\flatsymbol}\MainImpl{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. +% \begin{macrocode} +\newcommand\sharpsymbol{\ensuremath{^\#}} +\newcommand\flatsymbol{\raise.5ex\hbox{{\SB@flatsize$\flat$}}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\shrp}\MainImpl{shrp} +% \begin{macro}{\flt}\MainImpl{flt} +% \changes{v2.10}{2009/08/18}{Font size made relative} +% These macros typeset sharp and flat symbols. +% \begin{macrocode} +\newcommand\shrp{\SB@accidental\sharpsymbol} +\newcommand\flt{\SB@accidental\flatsymbol} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\DeclareFlatSize[2]{% + \expandafter\xdef\csname SB@flatsize@#1\endcsname{#2}% +} +\DeclareFlatSize\@vpt\@vpt +\DeclareFlatSize\@vipt\@vipt +\DeclareFlatSize\@viipt\@vipt +\DeclareFlatSize\@viiipt\@viipt +\DeclareFlatSize\@ixpt\@viiipt +\DeclareFlatSize\@xpt\@ixpt +\DeclareFlatSize\@xipt\@xpt +\DeclareFlatSize\@xiipt\@xipt +\DeclareFlatSize\@xivpt\@xiipt +\DeclareFlatSize\@xviipt\@xivpt +\DeclareFlatSize\@xxpt\@xviipt +\DeclareFlatSize\@xxvpt\@xxpt +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@flatsize} +% Select the correct flat symbol size based on the current font size. +% \begin{macrocode} +\newcommand\SB@flatsize{% + \@ifundefined{SB@flatsize@\f@size}{}{% + \expandafter\fontsize% + \csname SB@flatsize@\f@size\endcsname\f@baselineskip% + \selectfont% + }% +} +% \end{macrocode} +% \end{macro} +% +% In the following code, the |\ch|, |\mch|, |\[|\eat\], 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 lyric-scanning 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. +% +% \begin{macro}{\ch}\MainImpl{ch} +% \begin{macro}{\SB@ch} +% \begin{macro}{\SB@ch@on} +% \begin{macro}{\SB@@ch} +% \begin{macro}{\SB@@@ch} +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\ch{\SB@ch} +\newcommand\SB@ch{} +\newcommand\SB@ch@on{\SB@begincname\SB@@ch} +\newcommand*\SB@@ch[1]{\SB@endcname\SB@@@ch{#1}} +\newcommand*\SB@@@ch[4]{\[\SB@noreplay{\hphantom{#2}}#1]#4} +\newcommand*\SB@ch@off[4]{#4} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \eat\] +% +% \begin{macro}{\mch}\MainImpl{mch} +% \begin{macro}{\SB@mch} +% \begin{macro}{\SB@mch@m} +% \begin{macro}{\SB@mch@on} +% \begin{macro}{\SB@@mch} +% \begin{macro}{\SB@@@mch} +% The |\mch| macro is like |\ch| except that it also introduces a measure +% bar. +% \begin{macrocode} +\newcommand\mch{\SB@mch} +\newcommand\SB@mch{} +\newcommand*\SB@mch@m[4]{#2\measurebar#3} +\newcommand\SB@mch@on{\SB@begincname\SB@@mch} +\newcommand*\SB@@mch[1]{\SB@endcname\SB@@@mch{#1}} +\newcommand*\SB@@@mch[4]{#2\measurebar\[#1]#3} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \eat\] +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@activehat{% + \ifmmode^\else\expandafter\SB@rechord\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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]|\eat\] +% to typeset chords. +% \begin{macrocode} +\newcommand\SB@loadactives{} +{ + \catcode`&\active + \catcode`#\active + \catcode`|\active + \catcode`^\active + \global\let&\flt + \global\let#\shrp + \global\let|\measurebar + \global\let^\SB@activehat + \gdef\SB@loadactives{% + \catcode`^\ifchorded\active\else9 \fi% + \catcode`|\ifmeasures\active\else9 \fi% + \def\[{\SB@bracket}% + } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Chord Replaying} +% +% \begin{macro}{\SB@trackch} +% While inside a verse where the chord history is being remembered for future +% verses, |\SB@trackch| is true. +% \begin{macrocode} +\newif\ifSB@trackch +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@cr@} +% Reserve token registers to record a history of the chords seen in a verse. +% \begin{macrocode} +\newtoks\SB@cr@ +\newtoks\SB@ctail +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@creg} +% The following control sequence equals the token register being memorized +% into or replayed from. +% \begin{macrocode} +\newcommand\SB@creg{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\newchords}\MainImpl{newchords} +% \changes{v2.6}{2008/02/23}{Added} +% Allocate a new chord-replay register to hold memorized chords. +% \begin{macrocode} +\newcommand\newchords[1]{% + \@ifundefined{SB@cr@#1}{% + \expandafter\newtoks\csname SB@cr@#1\endcsname% + \global\csname SB@cr@#1\endcsname{\\}% + }{\SB@errdup{#1}}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\memorize}\MainImpl{memorize} +% \begin{macro}{\SB@memorize} +% \changes{v2.6}{2008/02/23}{Optional argument added} +% Saying |\memorize| throws out any previously memorized list of chords and +% starts memorizing chords until the end of the current verse or chorus. +% \begin{macrocode} +\newcommand\memorize{% + \@ifnextchar[\SB@memorize{\SB@memorize[]}% +} +\newcommand\SB@memorize{} +\def\SB@memorize[#1]{% + \@ifundefined{SB@cr@#1}{\SB@errreg{#1}}{% + \SB@trackchtrue% + \global\expandafter\let\expandafter\SB@creg% + \csname SB@cr@#1\endcsname% + \global\SB@creg{\\}% + }% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\replay}\MainImpl{replay} +% \begin{macro}{\SB@replay} +% \begin{macro}{\SB@@replay} +% \changes{v2.6}{2008/02/23}{Added} +% Saying |\replay| stops any memorization and begins replaying memorized +% chords. +% \begin{macrocode} +\newcommand\replay{\@ifnextchar[\SB@replay\SB@@replay} +\newcommand\SB@replay{} +\def\SB@replay[#1]{% + \@ifundefined{SB@cr@#1}{\SB@errreg{#1}}{% + \SB@trackchfalse% + \global\expandafter\let\expandafter\SB@creg% + \csname SB@cr@#1\endcsname% + \global\SB@ctail\SB@creg% + }% +} +\newcommand\SB@@replay{% + \SB@trackchfalse% + \global\SB@ctail\SB@creg% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@rechord} +% \begin{macro}{\SB@@rechord} +% Replay the same chord that was in a previous verse. +% \begin{macrocode} +\newcommand\SB@rechord{} +\newcommand\SB@@rechord{% + \SB@ifempty\SB@ctail{% + \SB@errreplay% + \SB@toks{}% + \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]% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newif\ifSB@nohat +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@noreplay} +% 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. +% \begin{macrocode} +\newcommand\SB@noreplay{} +\let\SB@noreplay\@firstofone +% \end{macrocode} +% \end{macro} +% +% \subsection{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. +% +% \begin{macro}{\SB@fretwidth} +% Set the width of each vertical string in the tablature diagram. +% \begin{macrocode} +\newlength\SB@fretwidth +\setlength\SB@fretwidth{6\p@} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@fretnum} +% Typeset a fret number to appear to the left of the diagram. +% \begin{macrocode} +\newcommand\SB@fretnum[1]{{% + \sffamily\fontsize\@xpt\@xpt\selectfont#1% +}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@onfret} +% Typeset one string of one fret with \argp{1} typeset overtop of it (usually +% a dot or nothing at all). +% \begin{macrocode} +\newcommand\SB@onfret[1]{% + \rlap{\hbox to\SB@fretwidth{\hfil\vrule\@height6\p@\hfil}}% + \hbox to\SB@fretwidth{\hfil#1\hfil}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@atopfret} +% Typeset material (given by \argp{1}) to be placed above a string in the +% tablature diagram. +% \begin{macrocode} +\newcommand\SB@atopfret[1]{% + \hbox to\SB@fretwidth{\hfil#1\hfil}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@fretbar} +% Typeset a horizontal fret bar of width |\SB@dimen|. +% \begin{macrocode} +\newcommand\SB@fretbar{% + \nointerlineskip% + \hbox to\SB@dimen{% + \advance\SB@dimen-\SB@fretwidth% + \advance\SB@dimen.4\p@% + \hfil% + \vrule\@width\SB@dimen\@height.4\p@\@depth\z@% + \hfil% + }% + \nointerlineskip% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@topempty} +% \begin{macro}{\SB@topX} +% \begin{macro}{\SB@topO} +% Above a string in a tablature diagram there can be nothing, +% an $\times$, or an $\circ$. +% \begin{macrocode} +\newcommand\SB@topempty{\SB@atopfret\relax} +\newcommand\SB@topX{\SB@atopfret{% + \hbox{% + \kern-.2\p@% + \fontencoding{OMS}\fontfamily{cmsy}% + \fontseries{m}\fontshape{n}% + \fontsize\@viipt\@viipt\selectfont\char\tw@% + \kern-.2\p@% + }% +}} +\newcommand\SB@topO{\SB@atopfret{% + \vrule\@width\z@\@height4.3333\p@\@depth.8333\p@% + \lower.74\p@\hbox{% + \fontencoding{OMS}\fontfamily{cmsy}% + \fontseries{m}\fontshape{n}% + \fontsize\@xpt\@xpt\selectfont\char14% + }% +}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@fretempty} +% \begin{macro}{\SB@frethit} +% On a string in a fret diagram there can be nothing or a filled circle. +% \begin{macrocode} +\newcommand\SB@fretempty{\SB@onfret\relax} +\newcommand\SB@frethit{\SB@onfret{% + \hbox{% + \fontencoding{OMS}\fontfamily{cmsy}% + \fontseries{m}\fontshape{n}% + \fontsize\@xiipt\@xiipt\selectfont\char15% + }% +}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@finger} +% If we're including fingering info in the tablature diagram, then below +% each string there might be a number. +% \begin{macrocode} +\newcommand\SB@finger[1]{% + \SB@atopfret{\sffamily\fontsize\@vipt\@vipt\selectfont#1}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ifSB@gettabind} +% \begin{macro}{\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. +% \begin{macrocode} +\newif\ifSB@gettabind\SB@gettabindfalse +\newdimen\SB@tabindent +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@targfret} +% \begin{macro}{\SB@targstr} +% \begin{macro}{\SB@targfing} +% 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 \meta{strings} +% info, and the last is for the \meta{fingering} info. +% \begin{macrocode} +\newcommand\SB@targfret{} +\newcommand\SB@targstr{} +\newcommand\SB@targfing{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% 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 +% $\varepsilon$-\TeX). +% +% We therefore adopt the alternative strategy of converting each token +% in the \meta{strings} and \meta{fingering} 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. +% +% \begin{macro}{\SB@csify} +% \begin{macro}{\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|. +% \begin{macrocode} +\newcommand\SB@csify[2]{% + \SB@toks{}% + \SB@cnt\z@% + \SB@@csify#2\SB@@csify% + \edef#1{\the\SB@toks}% +} +\newcommand\SB@@csify[1]{% + \ifx#1\SB@@csify\else% + \advance\SB@cnt\@ne% + \SB@toks\expandafter{\the\SB@toks\csname#1\endcsname}% + \expandafter\SB@@csify% + \fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\SB@gttop} +% \begin{macro}{\SB@gtinit} +% \begin{macro}{\SB@gtinc} +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@gttop{% + \let\X\SB@topX\let\0\SB@topO\let\O\0\let\1\SB@topempty% + \let\2\1\let\3\1\let\4\1\let\5\1% + \let\6\1\let\7\1\let\8\1\let\9\1% +} +\newcommand\SB@gtinit{% + \let\X\SB@fretempty\let\0\X\let\O\X\let\1\SB@frethit% + \let\2\X\let\3\X\let\4\X\let\5\X% + \let\6\X\let\7\X\let\8\X\let\9\X% +} +\newcommand\SB@gtinc{% + \let\9\8\let\8\7\let\7\6\let\6\5\let\5\4% + \let\4\3\let\3\2\let\2\1\let\1\0% +} +\newcommand\SB@gtset[2]{% + \let\X#1\let\0\X\let\O\X% + \def\1{#21}\def\2{#22}\def\3{#23}% + \def\4{#24}\def\5{#25}\def\6{#26}% + \def\7{#27}\def\8{#28}\def\9{#29}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@gtmax} +% To compute the height of the tablature diagram, we must identify the +% maximum fret number in the \meta{strings} argument. +% This is accomplished by using the following macro in combination with +% |\SB@gtset| above. +% \begin{macrocode} +\newcommand\SB@gtmax[1]{\ifnum\SB@cnt<#1\SB@cnt#1\fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\gtab} +% \begin{macro}{\SB@gtab} +% \changes{v2.9}{2009/03/27}{Fixed compatibility issue with Babel French} +% 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 \textsf{Babel} French. +% \begin{macrocode} +\newcommand\gtab{\SB@begincname\SB@gtab} +\newcommand*\SB@gtab[1]{% + \SB@endcname% + \begingroup% + \catcode`:12\relax% + \SB@@gtab{#1}% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\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!). +% \begin{macrocode} +\newcommand*\SB@@gtab[2]{% + \endgroup% + \ifnum\SB@transposefactor=\z@% + \SB@@@gtab{#1}{#2}% + \else% + \begingroup% + \let\gtab\SB@@@gtab% + \gtabtrans{#1}{#2}% + \endgroup% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\gtabtrans}\MainImpl{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. +% \begin{macrocode} +\newcommand\gtabtrans[2]{\transposehere{#1}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@@@gtab}\MainImpl{gtab} +% \changes{v2.13}{2011/04/16}{Added transposition for chord names} +% Typeset a full tablature diagram. +% Text \argp{1} is a chord name placed above the diagram. +% Text \argp{2} 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 $\times$ above the string), +% |0| or |O| (to place an $\circ$ 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). +% \begin{macrocode} +\newcommand\SB@@@gtab[2]{% + \let\SB@targfret\@empty% + \let\SB@targstr\@empty% + \let\SB@targfing\@empty% + \SB@tabargs#2:::\SB@tabargs% + \ifx\SB@targstr\@empty% + \def\SB@targstr{\0\0\0\0\0\0}% + \fi% + \ifvmode\leavevmode\fi% + \vbox{% + \normalfont\normalsize% + \setbox\SB@box\hbox{% + \thinspace{\printchord{\transposehere{#1}\strut}}\thinspace% + }% + \setbox\SB@boxii\hbox{\SB@fretnum{\SB@targfret}}% + \setbox\SB@boxiii\hbox{{\SB@gttop\SB@targstr}}% + \hsize\wd\SB@box% + \ifSB@gettabind% + \global\SB@tabindent\wd\SB@boxii% + \global\advance\SB@tabindent.5\SB@fretwidth% + \global\advance\SB@tabindent-.5\p@% + \fi% + \SB@dimen\wd\SB@boxii% + \advance\SB@dimen\wd\SB@boxiii% + \ifdim\hsize<\SB@dimen% + \hsize\SB@dimen% + \else\ifSB@gettabind% + \SB@dimenii\hsize% + \advance\SB@dimenii-\SB@dimen% + \divide\SB@dimenii\tw@% + \global\advance\SB@tabindent\SB@dimenii% + \fi\fi% + \hbox to\hsize{\hfil\unhbox\SB@box\hfil}% + \kern-\p@\nointerlineskip% + \hbox to\hsize{% + \hfil% + \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@% + }% + \SB@gettabindfalse% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@tabargs} +% \begin{macro}{\SB@ctoken} +% Break the second argument to a |\gtab| macro into three sub-arguments. +% The possible forms are: +% (a) \meta{strings}, +% (b) \meta{fret}|:|\meta{strings}, +% (c) \meta{strings}|:|\meta{fingering}, or +% (d) \meta{fret}|:|\meta{strings}|:|\meta{fingering}. +% 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). +% \begin{macrocode} +\newcommand\SB@ctoken{} \def\SB@ctoken{:} +\newcommand\SB@tabargs{} +\def\SB@tabargs#1:#2:#3:#4\SB@tabargs{% + \def\SB@temp{#4}% + \ifx\SB@temp\@empty% + \SB@csify\SB@targstr{#1}% + \else\ifx\SB@temp\SB@ctoken% + \SB@csify\SB@targstr{#1}% + \ifnum\SB@cnt>\@ne% + \SB@cntii\SB@cnt% + \SB@csify\SB@targfing{#2}% + \SB@cnt\SB@cntii% + \else% + \def\SB@targfret{#1}% + \SB@csify\SB@targstr{#2}% + \fi% + \else% + \def\SB@targfret{#1}% + \SB@csify\SB@targfing{#3}% + \SB@csify\SB@targstr{#2}% + \fi\fi% +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \subsection{Book Sectioning} +% +% The following macros divide the song book into distinct sections, each with +% different headers, different song numbering styles, different indexes, etc. +% +% \begin{macro}{\songchapter}\MainImpl{songchapter} +% \changes{v1.19}{2005/10/24}{Added} +% 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. +% \begin{macrocode} +\newcommand\songchapter{% + \let\SB@temp\@seccntformat% + \def\@seccntformat##1{}% + \@startsection{chapter}{0}{\z@}% + {3.5ex\@plus1ex\@minus.2ex}% + {.4ex\let\@seccntformat\SB@temp}% + {\sffamily\bfseries\LARGE\centering}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\songsection}\MainImpl{songsection} +% \changes{v1.19}{2005/10/24}{Section headers changed to omit numbers} +% Format the section header for a section in a song book. +% This is the same as for chapter headers except at the section level. +% \begin{macrocode} +\newcommand\songsection{% + \let\SB@temp\@seccntformat% + \def\@seccntformat##1{}% + \@startsection{section}{1}{\z@}% + {3.5ex\@plus1ex\@minus.2ex}% + {.4ex\let\@seccntformat\SB@temp}% + {\sffamily\bfseries\LARGE\centering}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{songs}\MainEnvImpl{songs} +% \changes{v1.19}{2005/10/24}{Song numbers now starts at one instead of zero} +% Begin and end a book section. +% The argument is a list of indexes with which to associate songs in this +% section. +% \begin{macrocode} +\newenvironment{songs}[1]{% + \ifSB@songsenv\SB@errnse\fi% + \gdef\SB@indexlist{#1}% + \SB@chkidxlst% + \stepcounter{SB@songsnum}% + \setcounter{songnum}{1}% + \let\SB@sgroup\@empty% + \ifinner\else\ifdim\pagetotal>\z@% + \null\nointerlineskip% + \fi\fi% + \songcolumns\SB@numcols% + \SB@songsenvtrue% +}{% + \commitsongs% + \global\let\SB@indexlist\@empty% + \ifinner\else\clearpage\fi% + \SB@songsenvfalse% +} +% \end{macrocode} +% \end{environment} +% +% Each |songs| section needs a unique number to aid in hyperlinking. +% \begin{macrocode} +\newcounter{SB@songsnum} +% \end{macrocode} +% +% \subsection{Index Generation} +% \label{sec:indexgen} +% +% The following macros generate the various types of indexes. At present there +% are four types: +% \begin{enumerate} +% \item A ``large'' index has a separate section for each capital letter and +% is printed in two columns. +% \item A ``small'' index has only a single column, centered, and has no +% sections. +% \item A ``scripture'' index has three columns and each entry has a +% comma-separated list of references. +% \item An ``author'' index is like a large index except in bold and without +% the sectioning. +% \end{enumerate} +% ``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 \emph{four} step process to move +% the index data from the source |.tex| file to the |.sxd| data files. +% \begin{enumerate} +% \item While the current song box is in the midst of construction, +% the data is stored in a box of non-immediate write whatsit nodes. +% \item The whatsits are migrated out to the top of the song box when +% it is finalized at |\endsong|. +% \item 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. +% \item At the |\end{document}| line, the |.sxc| is processed multiple +% times---once for each index---to split the data into the respective +% |.sxd| files. +% \end{enumerate} +% 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. +% +% \begin{macro}{\SB@indexlist} +% This macro records the comma-separated list of the identifiers of indexes +% associated with the current book section. +% \begin{macrocode} +\newcommand\SB@indexlist{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@allindexes} +% This macro records a comma-separated list of all the index identifiers +% for the entire document. +% \begin{macrocode} +\newcommand\SB@allindexes{} +\let\SB@allindexes\@empty +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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.) +% \begin{macrocode} +\newcommand\SB@out{} +\let\SB@out\relax +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@newindex} +% Initialize a new title, author, or scripture index. +% \begin{macrocode} +\newcommand\SB@newindex[4]{% + \expandafter\newcommand\csname SB@idxfilename@#3\endcsname{#4}% + \expandafter\newcommand\csname SB@idxsel@#3\endcsname[3]{###1}% + \expandafter\newcommand\csname SB@idxref@#3\endcsname{\thesongnum}% + \xdef\SB@allindexes{% + \ifx\SB@allindexes\@empty\else\SB@allindexes,\fi#3% + }% + \if@filesw% + \ifx\SB@out\relax% + \newwrite\SB@out% + \immediate\openout\SB@out=\jobname.sxc\relax% + \fi% + \immediate\write\SB@out{\noexpand\SB@iwrite{#3}{#2}}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\newindex}\MainImpl{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 \argp{2}|.sxd| is +% where the index data is stored at the end of processing. +% \begin{macrocode} +\newcommand\newindex{\SB@newindex1{TITLE INDEX DATA FILE}} +\@onlypreamble\newindex +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\newscripindex}\MainImpl{newscripindex} +% Define a new scripture index. This is exactly like |\newindex| except that +% scripture references are added to the auxiliary file instead of titles. +% \begin{macrocode} +\newcommand\newscripindex{\SB@newindex2{SCRIPTURE INDEX DATA FILE}} +\@onlypreamble\newscripindex +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\newauthorindex}\MainImpl{newauthorindex} +% Define a new author index. This is exactly like |\newindex| except that +% author info is added to the auxiliary file instead of titles. +% \begin{macrocode} +\newcommand\newauthorindex{\SB@newindex3{AUTHOR INDEX DATA FILE}} +\@onlypreamble\newauthorindex +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@cwrite} +% 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. +% \begin{macrocode} +\newcommand\SB@cwrite[2]{% + \ifx\SB@out\relax\else% + \protected@write\SB@out{}{\protect\SB@iwrite{#1}{#2}}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@iwrite[2]{% + \def\SB@tempii{#1}% + \ifx\SB@temp\SB@tempii% + \SB@toks{#2}% + \immediate\write\SB@out{\the\SB@toks}% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@uncombine{% + \ifx\SB@out\relax\else% + \immediate\closeout\SB@out% + \ifsongindexes% + \@for\SB@temp:=\SB@allindexes\do{% + \immediate\openout\SB@out=% + \csname SB@idxfilename@\SB@temp\endcsname.sxd\relax% + \begingroup\makeatletter\catcode`\%12\relax% + \input{\jobname.sxc}\endgroup% + \immediate\closeout\SB@out% + }% + \fi% + \fi% +} +\AtEndDocument{\SB@uncombine} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@songwrites} +% The following box register stores index data until it can be migrated to +% the top of the song box currently under construction. +% \begin{macrocode} +\newbox\SB@songwrites +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@addtoindex} +% \changes{v2.8}{2009/02/03}{Writes made non-immediate} +% Queue data \argp{2} associated with the current song for eventual writing +% to the index whose identifier is given by \argp{1}. +% \begin{macrocode} +\newcommand\SB@addtoindex[2]{% + \protected@edef\SB@tempii{#2}% + \ifx\SB@tempii\@empty\else% + \global\setbox\SB@songwrites\vbox{% + \unvbox\SB@songwrites% + \SB@cwrite{#1}{#2}% + \SB@cwrite{#1}{\csname SB@idxref@#1\endcsname}% + \SB@cwrite{#1}{song\theSB@songsnum-\thesongnum.% + \ifnum\c@section=\z@1\else2\fi}% + }% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@addtoindexes} +% Add \argp{1} to all title indexes, \argp{2} to all scripture indexes, and +% \argp{3} to all author indexes. +% \begin{macrocode} +\newcommand\SB@addtoindexes[3]{% + \@for\SB@temp:=\SB@indexlist\do{% + \SB@addtoindex\SB@temp% + {\csname SB@idxsel@\SB@temp\endcsname{#1}{#2}{#3}}% + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@addtotitles} +% Add \argp{1} to all title indexes, but leave other indexes unaffected. +% \begin{macrocode} +\newcommand\SB@addtotitles[1]{% + \@for\SB@temp:=\SB@indexlist\do{% + \csname SB@idxsel@\SB@temp\endcsname% + {\SB@addtoindex\SB@temp{#1}}{}{}% + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@chkidxlst} +% \changes{v2.3}{2007/09/23}{Added.} +% Check the current list of indexes and flag an error if any are undefined. +% \begin{macrocode} +\newcommand\SB@chkidxlst{% + \let\SB@temp\SB@indexlist% + \let\SB@indexlist\@empty% + \@for\SB@tempii:=\SB@temp\do{% + \@ifundefined{SB@idxsel@\SB@tempii}{\SB@errnoidx\SB@tempii}{% + \ifx\SB@indexlist\@empty% + \SB@toks\expandafter{\SB@tempii}% + \else% + \SB@toks\expandafter\expandafter\expandafter{% + \expandafter\SB@indexlist\expandafter,\SB@tempii}% + \fi% + \edef\SB@indexlist{\the\SB@toks}% + }% + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\indexentry}\MainImpl{indexentry} +% \changes{v2.3}{2007/09/23}{Optional argument added} +% \begin{macro}{\SB@idxentry} +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\indexentry{\@ifnextchar[{\SB@idxentry*}{\SB@@idxentry*}} +\newcommand\SB@idxentry{} +\def\SB@idxentry#1[#2]#3{{% + \def\SB@indexlist{#2}% + \SB@chkidxlst% + \SB@addtoindexes{#1#3}{#3}{#3}% +}} +\newcommand\SB@@idxentry[2]{\SB@addtotitles{#1#2}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\indextitleentry}\MainImpl{indextitleentry} +% \changes{v2.3}{2007/09/23}{Optional argument added} +% |\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.) +% \begin{macrocode} +\newcommand\indextitleentry{% + \@ifnextchar[{\SB@idxentry{}}{\SB@@idxentry{}}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\indexsongsas}\MainImpl{indexsongsas} +% \changes{v2.8}{2009/02/03}{Added.} +% 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. +% \begin{macrocode} +\newcommand\indexsongsas[1]{% + \@ifundefined{SB@idxref@#1}% + {\SB@errnoidx{#1}\@gobble}% + {\expandafter\renewcommand\csname SB@idxref@#1\endcsname}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@idxcmd} +% \begin{macro}{\SB@@idxcmd} +% \begin{macro}{\authsepword}\MainImpl{authsepword} +% \begin{macro}{\authbyword}\MainImpl{authbyword} +% \begin{macro}{\authignoreword}\MainImpl{authignoreword} +% \begin{macro}{\titleprefixword}\MainImpl{titleprefixword} +% \changes{v2.0}{2007/06/18}{Added.} +% The |songidx| index-generation program understands several different +% directives that each dictate various aspects of how index entries are +% parsed, sorted, and displayed. +% Such directives should typically appear at the start of the |.sxd| +% file just after the header line that identifies the type of index. +% \begin{macrocode} +\newcommand\SB@idxcmd[3]{% + \ifx\SB@out\relax\else% + \@for\SB@temp:=\SB@allindexes\do{% + \csname SB@idxsel@\SB@temp\endcsname% + {\SB@@idxcmd{#1}}{\SB@@idxcmd{#2}}{\SB@@idxcmd{#3}}% + }% + \fi% +} +\newcommand\SB@@idxcmd[1]{% + \def\SB@tempii{#1}% + \ifx\SB@tempii\@empty\else% + \immediate\write\SB@out{% + \noexpand\SB@iwrite{\SB@temp}{#1}% + }% + \fi% +} +\newcommand\authsepword[1]{} +\newcommand\authbyword[1]{} +\newcommand\authignoreword[1]{} +\newcommand\titleprefixword[1]{} +{\catcode`\%=12 + \gdef\authsepword#1{\SB@idxcmd{}{%sep #1}{}} + \gdef\authbyword#1{\SB@idxcmd{}{%after #1}{}} + \gdef\authignoreword#1{\SB@idxcmd{}{%ignore #1}{}} + \gdef\titleprefixword#1{\SB@idxcmd{%prefix #1}{}{}}} +\@onlypreamble\authsepword +\@onlypreamble\authbyword +\@onlypreamble\authignoreword +\@onlypreamble\titleprefixword +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@idxtitlebox} +% Define a box to hold the index title. +% \begin{macrocode} +\newbox\SB@idxtitlebox +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@idxlineskip} +% Set the spacing between lines in an index. +% \begin{macrocode} +\newcommand\SB@idxlineskip[1]{% + \vskip#1\p@\@plus#1\p@\@minus#1\p@% +} +% \end{macrocode} +% \end{macro} +% +% When rendering an index entry $X\ldots 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 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. +% +% \begin{macro}{\SB@ellipspread} +% Typeset an index entry of the form $X\ldots 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. +% \begin{macrocode} +\newcommand\SB@ellipspread[2]{% + \begingroup% + \SB@dimen\z@% + \def\SB@temp{#1}% + \SB@toks{#2}% + \setbox\SB@box\hbox{{% + \SB@temp% + \leaders\hbox to.5em{\hss.\hss}\hskip2em\@plus1fil% + {\the\SB@toks}% + }}% + \ifdim\wd\SB@box>\hsize% + \SB@balancerows% + \else% + \hbox to\hsize{\unhbox\SB@box}\par% + \fi% + \endgroup% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@balancerows} +% Typeset an index entry of the form $X\ldots 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 $w_1$ 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 $w_2$, we must insert leaders of width +% $c-w_1-w_2$ into the paragraph between $X$ and $Y$, where $c$ is the column +% width. +% +% Computing this width $w_1$ 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. +% \begin{macrocode} +\newcommand\SB@balancerows{% + \edef\SB@tempii{\the\SB@toks}% + \setbox\SB@box\vbox{% + \SB@toks\expandafter{\expandafter\\\the\SB@toks\\}% + \SB@lop\SB@toks\SB@toks% + \settowidth\SB@dimen{\the\SB@toks}% + \advance\SB@dimen-.5em% + \leftskip.5cm% + {\hbadness\@M\hfuzz\maxdimen% + \hskip-.5cm\relax\SB@temp\unskip\nobreak% + \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% + }% + \expandafter\SB@dimenii\the\wd\SB@box\relax% +% \end{macrocode} +% Next, compute the smallest width $w_2$ such that the index entry text +% produced by |\SB@multiline| with |\SB@dimen|=$w_2$ has no more lines than +% with |\SB@dimen| set to the maximum available width for the right-hand side. +% This effectively horizontal-balances the right-hand side of the index entry +% text, making all lines of $Y$ roughly equal in width without introducing +% any extra lines. +% \begin{macrocode} + \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% +% \end{macrocode} +% Finally, typeset the results based on the quantities computed above. +% \begin{macrocode} + \SB@multiline\relax% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@multiline} +% Create a paragraph containing text $X\ldots 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 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! +% \begin{macrocode} +\newcommand\SB@multiline[1]{% + \begingroup% + \SB@dimen-\SB@dimen% + \advance\SB@dimen\hsize% + \SB@dimenii-\SB@dimenii% + \advance\SB@dimenii\SB@dimen% + {#1\hskip-.5cm\relax\SB@temp\unskip\nobreak% + \SB@maxmin\SB@dimenii<{1.5em}% + \leftskip.5cm\rightskip2em\@plus1fil% + \interlinepenalty\@M% + \leaders\hbox to.5em{\hss.\hss}\hskip\SB@dimenii\@plus1fill% + \nobreak{\SB@tempii\kern-2em}% + \par\global\SB@cnt\badness}% + \endgroup% +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@idxitemsep} +% \changes{v1.11}{2005/04/21}{Changed macro name to avoid a name clash} +% If text $Y$ in index entry $X\ldots 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|. +% \begin{macrocode} +\newcommand\SB@idxitemsep{% + ,\kern-2em\penalty-8\hskip2.33em\@minus.11em% + \hskip-\SB@dimen\@plus-1fill% + \vadjust{}\nobreak% + \hskip\SB@dimen\@plus1fill\relax% +} +% \end{macrocode} +% \end{macro} +% +% 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. +% +% \begin{environment}{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). +% \begin{macrocode} +\newenvironment{idxblock}[1]{}{} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\idxentry} +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\idxentry[2]{} +\newcommand\idxaltentry[2]{} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{environment}{SB@lgidx} +% \begin{environment}{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. +% \begin{macrocode} +\newenvironment{SB@lgidx}[1]{}{} +\newenvironment{SB@smidx}[1]{}{} +% \end{macrocode} +% \end{environment} +% \end{environment} +% +% \begin{macro}{\SB@idxsetup} +% Set various parameters for a column of an index environment. +% \begin{macrocode} +\newcommand\SB@idxsetup{% + \hsize\SB@colwidth% + \parskip\z@skip\parfillskip\z@skip\parindent\z@% + \baselineskip\f@size\p@\@plus\p@\@minus\p@% + \lineskiplimit\z@\lineskip\p@\@plus\p@\@minus\p@% + \hyphenpenalty\@M\exhyphenpenalty\@M% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@makeidxcolumn} +% Break off enough material from |\SB@box| to create one column of the +% index. +% \begin{macrocode} +\newcommand\SB@makeidxcolumn{% + \ifdim\ht\SB@box=\z@% + \hskip\hsize\relax% + \else% + \splittopskip\z@skip\splitmaxdepth\maxdepth% + \vsplit\SB@box to\SB@dimen% + \global\setbox\SB@box\vbox{% + \SB@idxsetup% + \splitbotmark% + \unvbox\SB@box% + }% + \fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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. +% \begin{macrocode} +\newcommand\SB@oneidxpage{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@displayindex} +% \changes{v1.11}{2005/04/21}{Item separator macro now localized in scope to the index file} +% \changes{v2.0}{2007/06/18}{Removed hyperref dependency} +% \changes{v2.6}{2008/02/16}{Balance columns on final page} +% \changes{v2.8}{2009/03/06}{Changed argument order} +% Create an index with title \argp{2} and with \argp{1} columns (must be a +% literal constant). Input the index contents from external file \argp{3}, +% which is expected to be a \TeX\ file. +% \begin{macrocode} +\newcommand\SB@displayindex[3]{% + \ifsongindexes\begingroup% + \SB@colwidth\hsize% + \advance\SB@colwidth-#1\columnsep% + \advance\SB@colwidth\columnsep% + \divide\SB@colwidth#1% + \setbox\SB@idxtitlebox\vbox{% + \let\SB@temp\songsection% + \ifx\chapter\undefined\else% + \ifx\chapter\relax\else% + \let\SB@temp\songchapter% + \fi% + \fi% + \SB@temp{#2}% + }% +% \end{macrocode} +% 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). +% \begin{macrocode} + \IfFileExists{\csname SB@idxfilename@#3\endcsname.sbx}{% + \ifx\hyperlink\undefined\let\hyperlink\@secondoftwo\fi% + \ifx\hyperlink\relax\let\hyperlink\@secondoftwo\fi% + \ifsepindexes% + \global\setbox\SB@box\vbox{% + \null% + \vfil% + \unvcopy\SB@idxtitlebox% + \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% + }% +% \end{macrocode} +% Test whether the resulting small index fits within one page. +% If not, re-typeset it as a large index. +% \begin{macrocode} + {\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% + }% +% \end{macrocode} +% 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. +% \begin{macrocode} + {% + \ifsepindexes% + \vbox to\textheight{% + \vfil% + \unvbox\SB@idxtitlebox% + \vskip1em\relax% + \hbox to\hsize{\hfil[Index not yet generated.]\hfil}% + \vskip\z@\@plus2fil\relax% + }% + \else% + \unvbox\SB@idxtitlebox% + \hbox to\hsize{\hfil[Index not yet generated.]\hfil}% + \fi% + }% + \ifsepindexes\clearpage\fi% + \endgroup\fi% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@lgindex} +% Typeset a large-style index. +% We begin by typesetting the entire index into a box. +% \begin{macrocode} +\newcommand\SB@lgindex[2]{% + \global\setbox\SB@box\vbox{% + \renewenvironment{idxblock}[1]% + {\begin{SB@lgidx}{##1}}{\end{SB@lgidx}}% + \let\\\SB@idxitemsep% + \SB@idxsetup% + \input{\csname SB@idxfilename@#2\endcsname.sbx}% + \unskip% + }% +% \end{macrocode} +% Next, we split the box into columns and pages until the last page is reached. +% \begin{macrocode} + \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@idxtitlebox% + \vskip.2in\relax% + \nointerlineskip% + \null% + \nointerlineskip% + \SB@cnt\vbadness\vbadness\@M% + \SB@dimenii\vfuzz\vfuzz\maxdimen% + \loop% + \SB@dimen\textheight% + \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% +% \end{macrocode} +% 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. +% \begin{macrocode} + \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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\showindex}\MainImpl{showindex} +% \changes{v2.8}{2009/03/06}{Added optional argument} +% Create an index with title \argp{2} based on the data associated with index +% identifier \argp{3} (which was passed to |\newindex|). +% Optional argument \argp{1} specifies the number of columns. +% This macro calls the appropriate index-creation macro depending on the type +% of index that \argp{3} was declared to be. +% \begin{macrocode} +\newcommand\showindex[3][0]{% + \@ifundefined{SB@idxsel@#3}{\SB@errnoidx{#3}}{% + \expandafter\let\expandafter\SB@temp\csname SB@idxsel@#3\endcsname% + \SB@cnt#1\relax% + \ifnum\SB@cnt<\@ne\SB@cnt\SB@temp232\relax\fi% + \expandafter\SB@temp% + \expandafter\SB@maketitleindex% + \expandafter\SB@makescripindex% + \expandafter\SB@makeauthorindex% + \expandafter{\the\SB@cnt}% + {#2}{#3}% + }% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@maketitleindex} +% \changes{v2.8}{2009/03/06}{Added columns argument} +% Create a song title index. +% \argp{1} is a column count, +% \argp{2} is the title, and +% \argp{3} is the index identifier (which was passed to |\newindex|). +% \begin{macrocode} +\newcommand\SB@maketitleindex{% + \renewenvironment{SB@lgidx}[1]{ + \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@}% + \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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\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)''. +% \begin{macrocode} +\newcommand\SB@idxcolhead{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@idxheadsep} +% Add vertical space following the header line that begins (or continues) a +% section of a scripture index. +% \begin{macrocode} +\newcommand\SB@idxheadsep{{% + \SB@dimen4\p@% + \advance\SB@dimen-\prevdepth% + \SB@maxmin\SB@dimen<\z@% + \SB@dimenii\SB@dimen% + \SB@maxmin\SB@dimenii>\p@% + \vskip\SB@dimen\@plus\p@\@minus\SB@dimenii% +}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@idxcont} +% Typeset the ``Bookname (continued)'' line that continues a scripture +% index section when it spans a column break. +% \begin{macrocode} +\newcommand\SB@idxcont[1]{% + \hbox to\hsize{{\idxcont{#1}}\hfil}% + \nobreak% + \SB@idxheadsep\nointerlineskip% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@makescripindex} +% \changes{v2.4}{2007/10/08}{Scripture index spacing made more uniform} +% \changes{v2.8}{2009/03/06}{Added columns argument} +% Create a scripture index. +% \argp{1} is a column count, +% \argp{1} is the title, and +% \argp{2} is the index identifier (which was passed to |\newscripindex|). +% \begin{macrocode} +\newcommand\SB@makescripindex{% + \renewenvironment{SB@lgidx}[1]{% + \gdef\SB@idxcolhead{##1}% + \hbox to\hsize{{\idxbook{##1}}\hfil}% + \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% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@makeauthorindex} +% \changes{v2.8}{2009/03/06}{Added columns argument} +% Create an author index. +% \argp{1} is a column count, +% \argp{2} is the title, and +% \argp{2} is the index identifier (which was passed to |\newauthindex|). +% \begin{macrocode} +\newcommand\SB@makeauthorindex{% + \renewenvironment{SB@lgidx}[1]{}{}% + \renewenvironment{SB@smidx}[1]{}{}% + \renewcommand\idxentry[2]{% + \SB@ellipspread{{\idxauthfont\relax\sfcode`.\@m##1}}% + {{\idxrefsfont##2}}% + }% + \renewcommand\idxaltentry[2]{\SB@erridx{an author}}% + \SB@displayindex% +} +% \end{macrocode} +% \end{macro} +% +% \subsection{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. +% +% \begin{macro}{\SB@Error} +% \begin{macro}{\SB@Warn} +% All errors and warnings will be reported as coming from package ``songs''. +% \begin{macrocode} +\newcommand\SB@Error{\PackageError{songs}} +\newcommand\SB@Warn{\PackageWarning{songs}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\SB@errspos} +% \begin{macrocode} +\newcommand\SB@errspos{% + \SB@Error{Illegal \protect\songpos\space argument}{The argume% + nt to \protect\songpos\space must be a number from 0 to 3.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errnse} +% \begin{macrocode} +\newcommand\SB@errnse{% + \SB@Error{Nested songs environments are not supported}{End th% + e previous songs environment before beginning the next one.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errpl} +% \begin{macrocode} +\newcommand\SB@errpl{% + \SB@Error{\protect\includeonlysongs\space not permitted with% + in a songs environment}{\protect\includeonlysongs\space can o% + nly be used in the document preamble or between songs environ% + ments in the document body.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errrtopt} +% \begin{macrocode} +\newcommand\SB@errrtopt{% + \SB@Error{Cannot display chords in a rawtext dump}{You have u% + sed the rawtext option in the \protect\usepackage\space lin% + e and have either used the chorded option as well or have use% + d the \protect\chordson\space macro subsequently.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@warnrc} +% \begin{macrocode} +\newcommand\SB@warnrc{% + \SB@Warn{The \protect\repchoruses\space feature will not wor% + k when the number of columns is set to zero}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errboo} +% \begin{macrocode} +\newcommand\SB@errboo{% + \SB@Error{Encountered \protect\beginsong\space without seein% + g an \protect\endsong\space for the previous song}% + {Song \thesongnum\space might be missing a% + n \protect\endsong\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbor} +% \begin{macrocode} +\newcommand\SB@errbor{% + \SB@Error{Encountered \protect\beginsong\space without seein% + g an \protect\endscripture\space for the preceding scriptur% + e quotation}{A scripture quotation appearing after son% + g \thesongnum\space might be missing a% + n \protect\endscripture\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@erreov} +% \begin{macrocode} +\newcommand\SB@erreov{% + \SB@Error{Encountered \protect\endsong\space without seein% + g an \protect\endverse\space for the preceding verse}{Son% + g \thesongnum\space has a \protect\beginverse\space% + line with no matching \protect\endverse\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@erreoc} +% \begin{macrocode} +\newcommand\SB@erreoc{% + \SB@Error{Encountered \protect\endsong\space without seein% + g an \protect\endchorus\space for the preceding chorus}{Son% + g \thesongnum\space has a \protect\beginchorus\space% + line with no matching \protect\endchorus\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@erreor} +% \begin{macrocode} +\newcommand\SB@erreor{% + \SB@Error{Encountered \protect\endsong\space without seein% + g an \protect\endscripture for the preceding scripture quot% + e}{A scripture quote appearing before song \thesongnum\space% + ended with \protect\endsong\space instead of wit% + h \protect\endscripture.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@erreot} +% \begin{macrocode} +\newcommand\SB@erreot{% + \SB@Error{Encountered \protect\endsong\space with no matchin% + g \protect\beginsong}{Before song \thesongnum\space there wa% + s an \protect\endsong\space with no matchin% + g \protect\beginsong.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbvv} +% \begin{macrocode} +\newcommand\SB@errbvv{% + \SB@Error{Encountered \protect\beginverse\space without seein% + g an \protect\endverse\space for the preceding verse}{Son% + g \thesongnum\space might have a verse that has n% + o \protect\endendverse\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbvc} +% \begin{macrocode} +\newcommand\SB@errbvc{% + \SB@Error{Encountered \protect\beginverse\space without seein% + g an \protect\endchorus\space for the preceding chorus}{Son% + g \thesongnum\space might have a chorus that has n% + o \protect\endchorus\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbvt} +% \begin{macrocode} +\newcommand\SB@errbvt{% + \SB@Error{Encountered \protect\beginverse\space without firs% + t seeing a \protect\beginsong\space line}{Before son% + g \thesongnum, there is a \protect\beginverse\space line no% + t contained in any song.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errevc} +% \begin{macrocode} +\newcommand\SB@errevc{% + \SB@Error{Encountered \protect\endverse\space while process% + ing a chorus}{Song \thesongnum\space might hav% + e a \protect\beginchorus\space concluded by a% + n \protect\endverse\space instead of an \protect\endchorus.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errevo} +% \begin{macrocode} +\newcommand\SB@errevo{% + \SB@Error{Encountered \protect\endverse\space without firs% + t seeing a \protect\beginverse}{Song \thesongnum\space m% + ight have an \protect\endverse\space with no matchin% + g \protect\beginverse.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errevt} +% \begin{macrocode} +\newcommand\SB@errevt{% + \SB@Error{Encountered an \protect\endverse\space outside o% + f any song}{Before song \thesongnum, there is a% + n \protect\endverse\space line not preceded b% + y a \protect\beginsong\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@erretex} +% \begin{macrocode} +\newcommand\SB@erretex{% + \SB@Error{The \protect\repchoruses\space feature requires e-% + TeX compatibility}{Your version of LaTeX2e does not appear t% + o be e-TeX compatible. Find a distribution that includes e-T% + eX support in order to use this feature.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbcv} +% \begin{macrocode} +\newcommand\SB@errbcv{% + \SB@Error{Encountered \protect\beginchorus\space without see% + ing an \protect\endverse\space for the preceding verse}{Son% + g \thesongnum\space might hav% + e a \protect\beginverse\space with no match% + ing \protect\endverse.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbcc} +% \begin{macrocode} +\newcommand\SB@errbcc{% + \SB@Error{Encountered \protect\beginchorus\space without see% + ing an \protect\endchorus\space for the preceding chorus}% + {Song \thesongnum\space might have a \protect\beginchorus% + \space with no matching \protect\endchorus.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbct} +% \begin{macrocode} +\newcommand\SB@errbct{% + \SB@Error{Encountered \protect\beginchorus\space without see% + ing a \protect\beginsong\space line first}{After son% + g \thesongnum\space there is a \protect\beginchorus\space% + line outside of any song.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errecv} +% \begin{macrocode} +\newcommand\SB@errecv{% + \SB@Error{Encountered an \protect\endchorus\space while proc% + essing a verse}{Song \thesongnum\space might hav% + e a \protect\beginverse\space concluded by \protect\endchorus% + \space instead of \protect\endverse.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@erreco} +% \begin{macrocode} +\newcommand\SB@erreco{% + \SB@Error{Encountered \protect\endchorus\space without firs% + t seeing a \protect\beginchorus}{Song \thesongnum\space m% + ight have an \protect\endchorus\space with no match% + ing \protect\beginchorus.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errect} +% \begin{macrocode} +\newcommand\SB@errect{% + \SB@Error{Encountered an \protect\endchorus\space outside o% + f any song}{Before song \thesongnum, there is a% + n \protect\endchorus\space line not preceded b% + y a \protect\beginsong\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbro} +% \begin{macrocode} +\newcommand\SB@errbro{% + \SB@Error{Missing \protect\endsong}% + {Nested song and intersong environments are not supported% + . Song \thesongnum\space might be missing a% + n \protect\endsong\space line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errbrr} +% \begin{macrocode} +\newcommand\SB@errbrr{% + \SB@Error{Nested intersong environments are not supported}% + {A scripture quote or other intersong environment before s% + ong \thesongnum\space is missing its ending line.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errero} +% \begin{macrocode} +\newcommand\SB@errero{% + \SB@Error{Encountered an \protect\endscripture\space whil% + e processing a song}{Song \thesongnum\space ends wit% + h \protect\endscripture\space when it should end wit% + h \protect\endsong.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errert} +% \begin{macrocode} +\newcommand\SB@errert{% + \SB@Error{Encountered an \protect\endscripture\space with% + out first seeing a \protect\beginscripture}{Before son% + g \thesongnum, there is an \protect\endscripture\space w% + ith no matching \protect\beginscripture.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errscrip} +% \begin{macrocode} +\newcommand\SB@errscrip[1]{% + \SB@Error{Encountered a \protect#1\space outside a scriptu% + re quote}{\protect#1\space can only appear betwee% + n \protect\beginscripture\space an% + d \protect\endscripture\space lines.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errchord} +% \begin{macrocode} +\newcommand\SB@errchord{% + \SB@Error{Song \thesongnum\space seems to have chord% + s that appear outside of any verse or chorus}{All chords a% + nd lyrics should appear between \protect\beginverse\space% + and \protect\endverse, or between \protect\beginchorus\space% + and \protect\endchorus.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errreplay} +% \begin{macrocode} +\newcommand\SB@errreplay{% + \SB@Error{Replayed chord has no matching chord}{Son% + g \thesongnum\space uses \protect^ more times than the% + re are chords in the previously memorized verse.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errreg} +% \begin{macrocode} +\newcommand\SB@errreg[1]{% + \SB@Error{Unknown chord-replay register name: #1}{Chord-re% + play registers must be declared with \protect\newchords.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errdup} +% \begin{macrocode} +\newcommand\SB@errdup[1]{% + \SB@Error{Duplicate definition of chord-replay register% + : #1}{\protect\newchords\space was used to declare the sa% + me chord-replay register twice.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errmbar} +% \begin{macrocode} +\newcommand\SB@errmbar{% + \SB@Error{Song \thesongnum\space seems to have measur% + e bars that appear outside of any verse or chorus}{All mea% + sure bars (produced with \protect\mbar\space or |) must ap% + pear between \protect\beginverse\space an% + d \protect\endverse, or between \protect\beginchorus\space% + and \protect\endchorus.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errtab} +% \begin{macrocode} +\newcommand\SB@errtab{% + \SB@Error{Invalid argument to \protect\gtab\space macro. R% + eplacing it with \protect\0.}{Valid arguments consist onl% + y of: X, O, 0, 1, 2, 3, or 4.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@errnoidx} +% \begin{macrocode} +\newcommand\SB@errnoidx[1]{% + \SB@Error{Unknown index identifier: #1}{This index identifie% + r was never declared using \protect\newindex.}% +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\SB@erridx} +% \begin{macrocode} +\newcommand\SB@erridx[1]{% + \SB@Error{\protect\idxaltentry\space not allowed in #1 index}% + {This error should not occur. The index generation routines ha% + ve malfunctioned. Try deleting all temporary files and then re% + compiling.}% +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Option Processing}\label{sec:optproc} +% +% \begin{macro}{\ifchorded} +% \begin{macro}{\iflyric} +% \begin{macro}{\ifslides} +% \begin{macro}{\ifmeasures} +% \begin{macro}{\ifpartiallist} +% \begin{macro}{\ifrepchorus} +% \begin{macro}{\iftranscapos} +% \begin{macro}{\ifnolyrics} +% \begin{macro}{\ifrawtext} +% \begin{macro}{\ifpdfindex} +% \begin{macro}{\ifsongindexes} +% \begin{macro}{\ifsepindexes} +% \begin{macro}{\ifSB@colorboxes} +% \begin{macro}{\ifSB@omitscrip} +% Reserve conditionals for all of the various option settings. +% We wait to define these since if any are used earlier than this, it is +% an error in the package code, and we'd rather get an error than continue. +% \begin{macrocode} +\newif\ifchorded +\newif\iflyric\lyrictrue +\newif\ifslides +\newif\ifmeasures +\newif\ifpartiallist +\newif\ifrepchorus +\newif\iftranscapos +\newif\ifnolyrics +\newif\ifrawtext +\newif\ifpdfindex\pdfindextrue +\newif\ifsongindexes\songindexestrue +\newif\ifsepindexes\sepindexestrue +\newif\ifSB@colorboxes\SB@colorboxestrue +\newif\ifSB@omitscrip +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\nolyrics} +% The |\nolyrics| macro is just shorthand for |\nolyricstrue|. +% \begin{macrocode} +\newcommand\nolyrics{} +\let\nolyrics\nolyricstrue +% \end{macrocode} +% \end{macro} +% +% 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. +% \begin{macrocode} +\SB@chordson +\ProcessOptions\relax +% \end{macrocode} +% +% If we're not generating a pdf, then don't generate the pdf index. +% \begin{macrocode} +\ifSB@pdf\else\pdfindexfalse\fi +% \end{macrocode} +% +% \begin{macro}{\SB@colorbox} +% Include the colors package and define colors, if requested. +% \begin{macrocode} +\ifSB@colorboxes + \RequirePackage{color} + \definecolor{SongbookShade}{gray}{.80} + \newcommand\SB@colorbox[2]{% + \ifx\@empty#1% + \vbox{% + \kern3\p@% + \hbox{\kern3\p@{#2}\kern3\p@}% + \kern3\p@% + }% + \else% + \colorbox{#1}{#2}% + \fi% + } +\else + \newcommand\SB@colorbox[2]{\vbox{% + \kern3\p@% + \hbox{\kern3\p@{#2}\kern3\p@}% + \kern3\p@% + }} +\fi +% \end{macrocode} +% \end{macro} +% +% \subsection{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. +% \begin{macrocode} +\ifrawtext + \newwrite\SB@txtout + \immediate\openout\SB@txtout=\jobname.txt + \newif\ifSB@doEOL + {\catcode`\^^M12 % + \catcode`\^^J12 % + \gdef\SB@printEOL{\ifSB@doEOL^^M^^J\fi}} + {\catcode`#12\gdef\SB@hash{#}} + {\catcode`&12\gdef\SB@amp{&}} + \renewcommand\SB@@@beginsong{% + \begingroup% + \def\'{}\def\`{}\def\v{}\def\u{}\def\={}\def\^{}% + \def\.{}\def\H{}\def\~{}\def\"{}\def\t{}% + \def\copyright{(c)}% + \let~\space% + \let\par\SB@printEOL% + \let\#\SB@hash% + \let\&\SB@amp% + \catcode`|9 % + \catcode`*9 % + \catcode`^9 % + \def\[##1]{}% + \resettitles% + \immediate\write\SB@txtout{\thesongnum. \songtitle}% + \nexttitle% + \foreachtitle{\immediate\write\SB@txtout{(\songtitle)}}% + \ifx\songauthors\@empty\else% + \immediate\write\SB@txtout{\songauthors}% + \fi% + \ifx\SB@rawrefs\@empty\else% + \immediate\write\SB@txtout{\SB@rawrefs}% + \fi% + \immediate\write\SB@txtout{}% + \SB@doEOLfalse% + \obeylines% + } + \renewcommand\SB@endsong{% + \SB@doEOLtrue% + \immediate\write\SB@txtout{\songcopyright\space% + \songlicense\SB@printEOL}% + \endgroup% + \SB@insongfalse% + \stepcounter{songnum}% + } + \def\SB@parsesrefs#1{\def\songrefs{#1}} + \long\def\beginverse#1#2\endverse{% + \SB@doEOLtrue\begingroup% + \def\textnote##1{##1}% + \def\SB@temp{#1}% + \def\SB@star{*}% + \ifx\SB@temp\SB@star% + \immediate\write\SB@txtout{\@gobble#2}% + \else% + \immediate\write\SB@txtout{#2}% + \fi% + \endgroup\SB@doEOLfalse} + \long\def\beginchorus#1\endchorus{% + \SB@doEOLtrue\begingroup% + \def\textnote##1{##1}% + \immediate\write\SB@txtout{Chorus:#1}% + \endgroup\SB@doEOLfalse} + \long\def\beginscripture#1\endscripture{} + \def\musicnote#1{} + \def\textnote#1{% + \SB@doEOLtrue% + \immediate\write\SB@txtout{#1\SB@printEOL}% + \SB@doEOLfalse} + \def\brk{} + \def\rep#1{(x#1)} + \def\echo#1{(#1)} + \def\mbar#1#2{} + \def\lrep{} + \def\rrep{} + \def\nolyrics{} + \renewcommand\memorize[1][]{} + \renewcommand\replay[1][]{} +\fi +% \end{macrocode} +% +% \Finale +\endinput + diff --git a/Master/texmf-dist/source/latex/songs/songs.ins b/Master/texmf-dist/source/latex/songs/songs.ins new file mode 100644 index 00000000000..f6f4cdbd77e --- /dev/null +++ b/Master/texmf-dist/source/latex/songs/songs.ins @@ -0,0 +1,61 @@ +%% Copyright (C) 2012 Kevin W. Hamlen +%% +%% This program is free software; you can redistribute it and/or +%% modify it under the terms of the GNU General Public License +%% as published by the Free Software Foundation; either version 2 +%% of the License, or (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +%% MA 02110-1301, USA. +%% +%% The latest version of this program can be obtained from +%% http://songs.sourceforge.net. + +\input docstrip.tex +\keepsilent + +\usedir{tex/latex/songs} + +\preamble + +This is a generated file. + +Copyright (C) 2012 by Kevin W. Hamlen + +This file may be distributed and/or modified under the conditions of +the LaTeX Project Public License, either version 1.3a of this license +or (at your option) any later version. The latest version of this +license is in: + + http://www.latex-project.org/lppl.txt + +and version 1.3a or later is part of all distributions of LaTeX version +2004/10/01 or later. + +\endpreamble + +\generate{\file{songs.sty}{\from{songs.dtx}{package}}} + +\obeyspaces +\Msg{*************************************************************} +\Msg{* *} +\Msg{* To finish the installation you have to move the following *} +\Msg{* file into a directory searched by TeX: *} +\Msg{* *} +\Msg{* songs.sty *} +\Msg{* *} +\Msg{* To produce the documentation run the file songbook.dtx *} +\Msg{* through LaTeX. *} +\Msg{* *} +\Msg{* Happy TeXing! *} +\Msg{* *} +\Msg{*************************************************************} + +\endbatchfile |