% \iffalse meta-comment % % Copyright (C) 2018 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, 5th 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} % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{songs} %<*package> [2018/09/12 v3.1 Songs package] % % %<*driver> \documentclass{ltxdoc} % This documentation compiles as part of the Songs self-installer, so it % needs to work even on tiny LaTeX installations with few packages. We % therefore try to be especially robust to missing package failures. \newcommand\trypackage[4][]{\IfFileExists{#2.sty}{\usepackage[#1]{#2}#3}{#4}} \trypackage{microtype}{\linepenalty=20 \parfillskip=0pt plus\textwidth\relax}{} \trypackage{lmodern}{\usepackage[T1]{fontenc}}{} \trypackage{ifpdf}{}{\expandafter\newif\csname ifpdf\endcsname\pdffalse} \trypackage{color}{}{} \ifpdf \trypackage[bookmarks,linkbordercolor={.6 0 0}]{hyperref}{}{} \fi \usepackage[nopdfindex]{songs} % Provide back-up hyperlinking and color macros that do nothing, % in case the hyperref and/or color packages are absent. \providecommand\href[2]{#2} \providecommand\url[1]{#1} \providecommand\pdfbookmark[3][]{} \providecommand\hyperdef[3]{} \providecommand\hyperlink[2]{#2} \providecommand\texorpdfstring[2]{#1} \providecommand\definecolor[3]{} \providecommand\color[1]{} \providecommand\textcolor[2]{#2} \providecommand\microtypesetup[1]{} % Configure the document: \let\oldSE\StopEventually \EnableCrossrefs \CodelineIndex \RecordChanges %\OnlyDescription % Create the \Songs logo, if the musix13 font is available: \newcommand\Songs{\texorpdfstring{{\sffamily songs}}{songs}} \newcount\imode \imode=\interactionmode \batchmode \newfont\musicfont{musix13} \interactionmode=\imode \ifx\musicfont\nullfont\else \newdimen\msize \newcommand\wholenote{% \msize4ex \expandafter\ifx\csname musicfont\the\msize\endcsname\relax \expandafter\newfont\csname musicfont\the\msize\endcsname {musix13 at \the\msize}% \fi \kern.13ex \raise.5ex\hbox{{\csname musicfont\the\msize\endcsname\symbol9}}% \kern1.53ex } \renewcommand\Songs{\texorpdfstring{{\sffamily s\wholenote ngs}}{songs}} \fi % Create the logo for Christopher Rath's Songbook package: \newcommand{\Rath}{{\sffamily Song$\flat$ook}} % Colors \definecolor{myred}{rgb}{0.6,0,0} \definecolor{myblu}{rgb}{0,0,0.6} \definecolor{mygra}{gray}{0.33} \def\PrintDescribeMacro#1{\strut{\MacroFont\color{myred}\string#1}\ } \let\PrintMacroName\PrintDescribeMacro \def\PrintDescribeEnv#1{\strut{\MacroFont\color{myred}#1}\ } \let\PrintEnvName\PrintDescribeEnv {\makeatletter\gdef\verbatim@font{\normalfont\color{myblu}\ttfamily}} % For some reason, doc.sty removes the \verbatim@font customization hook % for \verb|...|. (Why??) That's not nice, so we put it back: {\makeatletter \gdef\verb {\relax\ifmmode\hbox\else\leavevmode\null\fi \bgroup \let\do\do@noligs \verbatim@nolig@list \verbatim@font \verb@eol@error \let\do\@makeother \dospecials \@ifstar{\@sverb}{\@vobeyspaces \frenchspacing \@sverb}} } % 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: \newcommand\pfs{\parfillskip0pt plus1fil\relax} \newenvironment{codeblock}{% \medskip \begingroup \ifdim\parindent=0pt \parindent=20pt\fi \indent\vbox\bgroup \hsize\linewidth \advance\hsize-\parindent \rightskip=0pt plus1fil\pfs \parindent=0pt \color{myblu}% \obeylines }{% \egroup\endgroup \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 \pfs }{% \egroup{\pfs\par}\medskip } % Typeset a sample lyric book fragment: \newenvironment{lyrics}{% \medskip \noindent\hfil \vbox\bgroup\begingroup \hsize=.7\textwidth \leftskip=20pt\rightskip=0pt plus1fil\pfs \parindent=-20pt \likeverse\obeylines }{% \par\endgroup\egroup \hfil{\pfs\par} \medskip } % Typeset a sample chord book fragment: \newenvironment{chorded}{% \medskip \noindent\hfil \vbox\bgroup\begingroup \hsize=.7\textwidth \leftskip=20pt\rightskip=0pt plus1fil\pfs \parindent=-20pt \likeverse\obeylines \versesep=5pt\chordheight }{% \par\endgroup\egroup \hfil{\pfs\par} \medskip } % Typeset a " produces " example: \newlength\prodlen \setlength{\prodlen}{2.7in} \newbox\prodbox \newcommand{\example}{% \medskip\setbox\prodbox\hbox\bgroup\begingroup\color{myblu}% } \newcommand{\produces}{% \endgroup\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{\pfs\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\mybookmark[2]{% \ifnum\value{subsection}=0 \seclevel=2 \else\ifnum\value{subsubsection}=0 \seclevel=3 \else\seclevel=4 \fi\fi \setcounter{tocdepth}{4}% \pdfbookmark[\the\seclevel]{#1}{#2}% \setcounter{tocdepth}{3}% } {\makeatletter \xdef\bschar{\@backslashchar} \global\let\For\@for} \newcommand\DescMacro[1]{% \ifhmode\unskip\fi \mybookmark{\bschar\bschar#1}{macdef-#1}% \expandafter\DescribeMacro\expandafter{\csname#1\endcsname}% \hyperdef{macro}{#1}{}\unpenalty \ignorespaces } \newcommand\DescMacroGroup[3]{% \ifhmode\unskip\fi \mybookmark{\bschar\bschar#2}{macdef-#1}% \expandafter\DescribeMacro\expandafter{\csname#2\endcsname}% \For\temp:=#3\do{\hyperdef{macro}{\temp}{}}\unpenalty \ignorespaces } \newcommand\MainImpl[1]{% \pdfbookmark[3]{\bschar\bschar#1}{mimpl-#1}% } \newcommand{\DescEnv}[1]{% \ifhmode\unskip\fi \mybookmark{#1}{envdef-#1}% \DescribeEnv{#1}% \hyperdef{env}{#1}{}\unpenalty \ignorespaces } \newcommand{\MainEnvImpl}[1]{% \mybookmark{#1}{eimpl-#1}% } % Create macros to hyperlink macro and environment names to their % documentation points. \newcommand{\mac}[1]{{\tt\hyperlink{macro.#1}{\textcolor{myblu}{\char92 #1}}}} \newcommand{\env}[1]{{\tt\hyperlink{env.#1}{\textcolor{myblu}{#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 to obtain the decimal % ascii number d of the symbol, then do some math (implemented in \octal) % to compute and tokenize each octal digit of d into the bookmark text. \newcount\cnta \newcount\cntb \newcommand\ooo{} \newcommand\octal{% \cntb\cnta \divide\cnta8 \multiply\cnta-8 \advance\cntb\cnta \edef\ooo{\the\cntb\ooo}% \divide\cnta-8 } \newcommand{\DescChar}[2]{% \ifhmode\unskip\fi \expandafter\let\csname string#1\expandafter\endcsname \expandafter=\string#2% \cnta\expandafter`\string#2% \def\ooo{}\octal\octal\octal \mybookmark{\bschar\ooo}{#1def}% {\def\SpecialUsageIndex##1{}% \expandafter\DescribeMacro\string#2}% \hyperdef{env}{#1}{}\unpenalty \ignorespaces } \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}% Underlined numbers refer to the code line where the corresponding entry is defined; other numbers refer to the code lines where the entry is used.} {\makeatletter \gdef\IndexParms{% \sfcode`,=1750 \parindent0pt \columnsep15pt \parskip0pt plus1pt \rightskip0pt \mathsurround0pt \parfillskip0pt \small \microtypesetup{protrusion=false}% \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 white-space} % 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\Meta[1]{{\color{mygra}\meta{#1}}} \newcommand\argp[1]{\Meta{arg#1}} \newcommand\Metarm[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} % % \fi % % \CheckSum{8935} % % \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 manual documents % \textsf{songs}~\fileversion, dated~\filedate, % \copyright~2018 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 details. % A copy of the license can also be obtained by writing to the % Free Software Foundation, Inc., 51 Franklin Street, 5th Floor, % Boston, MA 02110-1301, USA. % % \medskip % % \noindent % This software is copyright \copyright~2018 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. % 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. % % \begingroup\color{myblu} % \begin{verbatim} % \documentclass{article} % \usepackage[chorded]{songs} % % \noversenumbers % % \begin{document} % % \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 % \end{songs} % % \end{document} % \end{verbatim} % \endgroup\nointerlineskip\vskip-6pt plus0pt minus0pt % % To compile this book, run \LaTeX{} (|pdflatex| is recommended): % % \begin{codeblock} % |pdflatex mybook.tex| % \end{codeblock} % % \noindent % (where |mybook.tex| is the name of the source document above). % The final document is named |mybook.pdf| if you use |pdflatex| or % |mybook.dvi| if you use regular |latex|. % % Note that compiling a document that includes indexes requires extra steps. % See \S\ref{sec:compiling} for details. % % \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. % The |slides| and |chorded| options can be used together to create chorded % slides. % If no output options 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 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} % PDF bookmark entries and hyperlinks can be suppressed with the |nopdfindex| % option. % For finer control of PDF indexes, see \S\ref{sec:idxcust}. % % \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{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 \Meta{id}'s % (see \S\ref{sec:indexes})---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 only songs (see below) or inter-song environments % (see \S\ref{sec:between}) may appear. % No text in a |songs| environment may appear 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}} % {\pfs\par}\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 script (see \S\ref{sec:compiling}) 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 % \Metarm{refs}&\Metarm{nothing}\OR\Metarm{ref};\SPC\Metarm{ref};$\ldots$;\SPC\Metarm{ref}\cr % \Metarm{ref}&\Metarm{many-chptr-book}\SPC\Metarm{chapters}\OR\Metarm{one-chptr-book}\SPC\Metarm{verses}\cr % \Metarm{many-chptr-book}&Genesis\OR Exodus\OR Leviticus\OR Numbers\OR $\ldots$\cr % \Metarm{one-chptr-book}&Obadiah\OR Philemon\OR 2 John\OR 3 John\OR Jude\cr % \Metarm{chapters}&\Metarm{chref},\SPC\Metarm{chref},$\ldots$,\SPC\Metarm{chref}\cr % \Metarm{chref}&\Metarm{chapter}\OR\Metarm{chapter}-\Metarm{chapter}\OR\Metarm{chapter}:\Metarm{verses}\OR\cr % \omit&\quad\Metarm{chapter}:\Metarm{verse}-\Metarm{chapter}:\Metarm{verse}\cr % \Metarm{verses}&\Metarm{vref},\Metarm{vref},$\ldots$,\Metarm{vref}\cr % \Metarm{vref}&\Metarm{verse}\OR\Metarm{verse}-\Metarm{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|. % % \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 and Choruses}\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 chords 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. % % \paragraph{Replaying 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 subsequent 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} % Writing |\norepchoruses| turns off chorus repetition for subsequent songs. % % If you need finer control over where replayed choruses appear, use the % conditional macros covered in \S\ref{sec:conditionals} instead of % |\repchoruses|. % For example, to manually insert a chorus into only slide books at a % particular point (without affecting other versions of your book), % you could write: % % \begin{codeblock} % \mac{ifslides} % \mac{beginchorus} % $\vdots$ % \mac{endchorus} % |\fi| % \end{codeblock} % % \noindent % and copy and paste the desired chorus into the middle. % % \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{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 typographical 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{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 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:}}} % % To create a barre chord in which one finger is extended across multiple % strings, use parentheses |()| or brackets |[]| in the \Meta{strings} % argument to group the barred strings. % Each such group will draw a barre on the lowest numbered fret it contains. % For example: % % \example|\gtab{C7}{X(3535X):013140}|\produces{\vcenterbox{\gtab{C7}{{\hphantom{4}}:X(3535X):013140}}} % % \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. % % \paragraph{Tablatures Within Macros} % Macros that produce tablatures must not bury the colons that separate the % \Meta{fret}, \Meta{strings}, and \Meta{fingering} arguments within other % macros, and it's safest to always include both colons to avoid ambiguities % related to optional argument parsing. % For example, % % \begin{codeblock} % |\newcommand{\mystrings}{X4412X}| % |\newcommand{\myfingers}{X3412X}| % |\newcommand{\mychord}{|\mac{gtab}|{C|\mac{shrp}|}{:\mystrings:\myfingers}}| % \end{codeblock} % % \noindent % works as expected. % But omitting the colon before |\mystrings| in the definition of |\mychord| % confuses \mac{gtab} into thinking |\mystrings| is the \Meta{fret} % argument, and writing code like |\gtab{C\shrp}{\allargs}| with |\allargs| % defined to something with colons results in an error, because it confuses % \mac{gtab} into thinking that |\allargs| is only 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 does not 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{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{Chapters and Sections}\label{sec:sectioning} % % \DescMacro{songsection} % \DescMacro{songchapter} % Song books can be divided into chapters and sections using all the usual % macros provided by \LaTeX{} (e.g., |\chapter|, |\section|, etc.) and by % other macro packages. % In addition, the \Songs{} package provides two helpful built-in sectioning % macros: % % \begin{codeblock} % |\songchapter{|\Meta{title}|}| % |\songsection{|\Meta{title}|}| % \end{codeblock} % % \noindent % which act like \LaTeX's |\chapter| and |\section| commands except that they % center the \Meta{title} text in sans serif font and omit the chapter/section % number. % The |\songchapter| macro only works in document classes that support % |\chapter| (e.g., the |book| class). % % \section{Indexes} % % \subsection{Index Creation}\label{sec: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} % % \subsection{Index Entries}\label{sec:ientry} % % Every song automatically gets entries in the current \env{songs} % environment's list of title index(es) (see \S\ref{sec:songs}). % 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{Compiling}\label{sec:compiling} % % As with a typical \LaTeX{} document, compiling a song book document with % indexes 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.lua| script to generate an index for each index that % you declared with \mac{newindex}, \mac{newauthorindex}, or % \mac{newscripindex}. % The script can be launched using Lua\TeX, using the following syntax: % % \begin{codeblock} % |texlua songidx.lua |\textcolor{black}{[}|-b| \Meta{canon}|.can|\textcolor{black}{]} \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 to generate indexes sorted according to a Christian English bible, % execute: % % \begin{codeblock} % |texlua songidx.lua titlfile.sxd titlfile.sbx| % |texlua songidx.lua authfile.sxd authfile.sbx| % |texlua songidx.lua -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{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), with minimal line spacing. % You can change this default by redefining |\stitlefont|. % For example, to cause titles to be typeset in a roman font with lines % spaced 20 points apart, you could define % % \begin{codeblock} % |\renewcommand{\stitlefont}{| % | \rmfont\Large\baselineskip=20pt\lineskiplimit=0pt| % |}| % \end{codeblock} % % \DescMacro{versefont} % \DescMacro{chorusfont} % \DescMacro{meterfont} % \DescMacro{echofont} % \DescMacro{notefont} % You can apply additional font changes to verses, choruses, meter numbers, % echo parts produced with \mac{echo}, and textual notes produced with % \mac{textnote} and \mac{musicnote}, by redefining |\versefont|, % |\chorusfont|, |\meterfont|, |\echofont|, 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. % % As a simple example, the following causes each song to start with its % number and title(s), centered, in a large, boldface font, and then centers % the rest of the prelude material (e.g., references and authors) below that % (using \mac{extendprelude}). % % \begin{codeblock} % |\renewcommand\makeprelude{%| % | |\mac{resettitles} % | \centering| % | {\Large\bfseries|\mac{thesongnum}|. |\mac{songtitle}|\par| % | |\mac{nexttitle}\mac{foreachtitle}|{(|\mac{songtitle}|)\par}}%| % | |\mac{extendprelude} % |}| % \end{codeblock} % % \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 left-justify or center the lines of verses or choruses, redefine % |\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,ifrawtext,iftranscapos,ifnolyrics,ifpagepreludes,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}} % \newlength\oldbaselineskip \oldbaselineskip\baselineskip % \newlength\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 % &|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 % &|pagepreludes|&&the \mac{pagepreludes} 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{pagepreludes} % Song preludes (i.e., the material atop each song, including the title) are % typeset by default at column width. % Writing |\pagepreludes| typesets subsequent preludes at page width atop % fresh pages, with the rest of the song in multiple columns beneath its title. % (To prohibit separation of songs from their preludes, it also sets % \mac{songpos} to 0.) % % \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} % % \subsubsection{Index Appearance} % % \paragraph{Index Titles.} % To customize the appearance of index titles, redefine the \mac{songsection} % and/or \mac{songchapter} macros from \S\ref{sec:sectioning}. % For example, to use \LaTeX's built-in |\section| and |\chapter| macros % instead, you could write: % % \begin{codeblock} % |\renewcommand{|\mac{songchapter}|}{\chapter}| % |\renewcommand{|\mac{songsection}|}{\section}| % \end{codeblock} % % \paragraph{Layout and page divisions.} % \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{idxheadwidth} % The |\idxheadwidth| length defines the width of the shaded boxes that % begin each alphabetic block of a large title index. % Setting it to 0pt suppresses the boxes entirely. % For example, to set the width of those boxes to 1 centimeter, you could % define % % \begin{codeblock} % |\setlength{\idxheadwidth}{1cm}| % \end{codeblock} % % \paragraph{Fonts and colors.} % \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{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} % % \subsubsection{Entry References} % % \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. % % \subsubsection{PDF Bookmarks and Links} % % \DescMacro{songtarget} % \DescMacro{songlink} % Each \mac{beginsong} environment adds a PDF bookmark (if generating a PDF) % and hyperlink target (if using the |hyperref| package) for the % song by invoking |\songtarget| with two arguments: % (1) a suggested PDF bookmark level, and (2) a link target name. % Links in indexes to these targets are created by |\songlink|, which % also gets two arguments: % (1) the link target name (same as the second argument to \mac{songtarget}), % and (2) the text to be linked. % % Redefine these macros to customize or suppress these bookmarks, targets, % and links. % For example, to enable both bookmarks and links (the default behavior) use: % % \begin{codeblock} % |\renewcommand{\songtarget}[2]| % | {\pdfbookmark[#1]{|\mac{thesongnum}|. |\mac{songtitle}|}{#2}}| % |\renewcommand{\songlink}[2]{\hyperlink{#1}{#2}}| % \end{codeblock} % % \noindent % To enable links but not bookmarks, use: % % \begin{codeblock} % |\renewcommand{\songtarget}[2]{\hypertarget{#2}{\relax}}| % |\renewcommand{\songlink}[2]{\hyperlink{#1}{#2}}| % \end{codeblock} % % \noindent % To disable both bookmarks and links, use: % % \begin{codeblock} % |\renewcommand{\songtarget}[2]{}| % |\renewcommand{\songlink}[2]{#2}| % \end{codeblock} % % \subsubsection{Sort Order} % % The alphabetic ordering of entries in title and author indexes is dictated % by the computer system on which the \Songs{} software is installed. % Different languages and regions have different sorting conventions, so the % |songidx| Lua script delegates decisions about order to your operating system. % If the default ordering proves inadequate, you can modify it by changing your % operating system's \emph{locale} (see your system's local help files). % Alternatively, you can explicitly tell the |songidx| program which locale to % use in one of three ways: % % \begin{itemize} % \item \emph{Windows:} % Edit the |generate.bat| file in the |Sample| folder (or your working folder) % with any plain text editor (e.g., Vim or Notepad). % Near the top, find the line that says |SET locale=|. % After the |=|, type any valid locale name. % For a list of valid locale names on Windows, please see the ``Language name % abbreviation'' column of Microsoft's online National Language Support (NLS) % API Reference: % % {\centering\url{http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx}\par} % % \item \emph{Unix:} % Create an environment variable named |SONGIDX_LOCALE| and set it equal to % the desired locale name. % The command |locale -a| lists all valid locale names on most Unix systems. % % \item \emph{Command-line:} % If you are executing the |songidx| script manually, use the |-l| option to % specify the locale: % % \begin{codeblock} % |texlua songidx -l sv_SE myindex.sxd myindex.sbx| % \end{codeblock} % % \end{itemize} % % \subsubsection{Special Words In Song Info} % % The following macros control how certain keywords are treated when parsing % and sorting index entries. % They only affect indexes that have already been declared, so put them % strictly after all your index creation commands (see \S\ref{sec:indexes}). % % \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. % % \DescMacro{authsepword} % When parsing author index entries, the word ``and'' is recognized by the % |songidx| script 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. % % \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{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 a daunting 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 whether $\varepsilon$-\TeX{} primitives are % available. % \begin{macrocode} \newif\ifSB@etex \ifx\eTeXversion\undefined\else \ifx\eTeXversion\relax\else \SB@etextrue \ifx\e@alloc\@undefined \IfFileExists{etex.sty}{\RequirePackage{etex}}{} \fi \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 \IfFileExists{ifpdf.sty}{\RequirePackage{ifpdf}\ifpdf\SB@pdftrue\fi}{ \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}{\ifSB@testii} % \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 \newif\ifSB@testii \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} % \end{macro} % % \begin{macro}{\SB@newcount} % \begin{macro}{\SB@newdimen} % \begin{macro}{\SB@newbox} % \begin{macro}{\SB@newtoks} % \begin{macro}{\SB@newwrite} % Create macros for safely allocating count, dimen, box, token, and write % registers with detection for name-clashes. % For some reason, the default allocation macros provided by the \LaTeX{} % kernel do not detect name-clashes(!), which means that packages that use them % might accidentally overwrite our registers, causing all sorts of problems. % But at least we can do our best to avoid overwriting their registers. % \begin{macrocode} \newcommand\SB@newcount[1]{\@ifdefinable#1{\newcount#1}} \newcommand\SB@newdimen[1]{\@ifdefinable#1{\newdimen#1}} \newcommand\SB@newbox[1]{\@ifdefinable#1{\newbox#1}} \newcommand\SB@newtoks[1]{\@ifdefinable#1{\newtoks#1}} \newcommand\SB@newwrite[1]{\@ifdefinable#1{\newwrite#1}} % \end{macrocode} % \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} \SB@newdimen\SB@dimen \SB@newdimen\SB@dimenii \SB@newdimen\SB@dimeniii \SB@newdimen\SB@dimeniv \SB@newbox\SB@box \SB@newbox\SB@boxii \SB@newbox\SB@boxiii \SB@newtoks\SB@toks \SB@newcount\SB@cnt \SB@newcount\SB@cntii \newlength\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} % % \begin{macro}{\SB@envbox} % Also reserve a slightly less volatile box register for per-environment use. % In scripture environments it holds the scripture citation. % In indexes it holds the index title text. % \begin{macrocode} \SB@newbox\SB@envbox % \end{macrocode} % \end{macro} % % Load David Carlisle's |keyval| package for processing % \Meta{key}=\Meta{value} style macro arguments. % \begin{macrocode} \RequirePackage{keyval} % \end{macrocode} % % \begin{macro}{\SB@app} % Utility macro: Append some text to the definition of another macro. % \begin{macrocode} \newcommand\SB@app[3]{% \expandafter#1\expandafter#2\expandafter{#2#3}% } % \end{macrocode} % \end{macro} % % \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{% \sffamily\ifslides\Huge\else\slshape\Large\fi% } % \end{macrocode} % \end{macro} % % \begin{macro}{\versefont}\MainImpl{versefont} % \begin{macro}{\chorusfont}\MainImpl{chorusfont} % \begin{macro}{\notefont}\MainImpl{notefont} % \begin{macro}{\meterfont}\MainImpl{meterfont} % \changes{v2.1}{2007/08/02}{Added} % By default, verses, choruses, and textual notes just allow the |\lyricfont| % style to continue. % Meter numbers are in tiny, sans-serif, upright font. % Echo parts toggle slanted and upright fonts. % \begin{macrocode} \newcommand\versefont{} \newcommand\chorusfont{} \newcommand\notefont{} \newcommand\meterfont{\tiny\sffamily\upshape} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\echofont}\MainImpl{echofont} % \changes{v2.18}{2014/06/28}{Added} % Echo parts 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. % \begin{macrocode} \newcommand\echofont{% \ifdim\fontdimen\@ne\font>\z@\upshape\else\slshape\fi% } % \end{macrocode} % \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} % % \begin{macro}{\chordlocals}\MainImpl{chordlocals} % \label{sec: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} \newlength\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} \newlength\afterpreludeskip \afterpreludeskip=2\p@\@plus4\p@ \newlength\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} \newlength\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} \SB@newcount\vvpenalty\vvpenalty200 \SB@newcount\ccpenalty\ccpenalty200 \SB@newcount\vcpenalty\vcpenalty200 \SB@newcount\cvpenalty\cvpenalty200 \SB@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} \SB@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} \SB@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} \SB@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}{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{option}{nopdfindex}\MainEnvImpl{nopdfindex} % \optdef{off} % Suppress creation of PDF bookmark entries and hyperlinks. % \begin{macrocode} \DeclareOption{nopdfindex}{% \let\songtarget\@gobbletwo% \let\songlink\@secondoftwo% } % \end{macrocode} % \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 whether % each of these options has been explicitly specified by the user or whether % 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} \SB@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} \SB@newcount\SB@numcols\SB@numcols\tw@ \SB@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} \SB@newbox\SB@colbox % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@pgbox} % Reserve a box register to hold the current page in progress. % \begin{macrocode} \SB@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} \SB@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 an integer (positive or zero) indicating whether box $b$ should be % fully emptied and committed as columns (if positive), or whether its % final less-than-column-height remainder should be reserved as an in-progress % column (if zero); % \item the box $b$ to split; % \item a count register $i$ equaling the 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. % If $b$ is emptied and the first argument is 0, 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. % Otherwise, if $b$ is emptied and the first argument is positive, the final % column is contributed and $i$ is set to one greater than the index of that % column. % (If $i$ reaches |\SB@numcols| before $b$ is emptied, the first argument is % ignored.) % % Box $b$ and count register $i$ are globally modified. % If |\SB@updatepage| is not redefined, boxes |\SB@pgbox| and |\SB@mrkbox| % are also globally modified based on the results of the split. % % The implementation takes two special steps to avoid pre-committing % in-progress columns (when the first macro argument is zero): % First, the final split that empties box $b$ is ``undone'' by reverting to a % backup copy made before each split. % Second, any underfull box warnings for this final split are suppressed by % temporarily adding infinite-stretch |\vfil| glue to the bottom of the box. % This strategy preserves underfull and overfull box warnings for the columns % that are actually committed, but suppresses faux warnings for the last split % that is undone. % \begin{macrocode} \newcommand\SB@mkpage[4]{% \ifvoid#2\else\begingroup% \edef\SB@temp{\ifnum#2=\SB@box\SB@boxii\else\SB@box\fi}% \edef\SB@tempii{\ifnum#2=\SB@boxiii\SB@boxii\else\SB@boxiii\fi}% \splitmaxdepth\maxdepth\splittopskip\z@skip% \ifnum#1=\z@\global\setbox#2\vbox{\unvbox#2\vfil}\fi% \loop\ifnum#3<\SB@numcols% \ifnum#1=\z@\setbox\SB@tempii\copy#2\fi% \setbox\SB@temp\vsplit#2to#4\relax% \ifvoid#2% \ifnum#1=\z@% \global\setbox#2\box\SB@tempii% \else% \SB@updatepage% \global\advance#3\@ne% \fi% #3\SB@numcols% \else% \SB@updatepage% \global\advance#3\@ne% \ifrepchorus\ifvoid\SB@chorusbox\else% \SB@insertchorus#2% \fi\fi% \fi% \repeat% \ifnum#1=\z@\global\setbox#2\vbox{\unvbox#2\unskip}\fi% \endgroup\fi% } % \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@temp% }% } % \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@temp\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. % If the macro argument is 0, this final, in-progress column is left % unfinished, pending future contributions. % If the argument is positive, the final material is committed as a column. % If the argument is two or greater, the entire in-progress page is also % committed and the column number reset. % \begin{macrocode} \newcommand\SB@output[1]{% \ifnum\SB@numcols>\z@\begingroup% \loop% \SB@dimen\textheight% \ifinner\else\advance\SB@dimen-\pagetotal\fi% \SB@mkpage#1\SB@colbox\SB@colnum\SB@dimen% \SB@testfalse\SB@testiitrue% \ifnum#1>\@ne\ifvoid\SB@colbox\ifnum\SB@colnum>\z@% \SB@testtrue\SB@testiifalse% \fi\fi\fi% \ifnum\SB@colnum<\SB@numcols\SB@testiifalse\else\SB@testtrue\fi% \ifSB@test% \unvbox\SB@mrkbox% \ifinner\else\kern\z@\fi% \box\SB@pgbox% \ifinner\else\vfil\break\vskip\vsize\relax\fi% \global\SB@colnum\z@% \fi% \ifSB@testii\repeat% \endgroup\else% \unvbox\SB@colbox\unskip% \fi% } % \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@output1% \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@mkpage0\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@mkpage0\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 whether 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@mkpage0\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 whether the song fits on a fresh double-page. % \begin{macrocode} \newcommand\SB@spextnew{% \SB@cntii\z@% \SB@mkpage0\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@mkpage0\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). % The |\SB@colbox| is tested for zero height and depth rather than voidness, % since sometimes it contains zero-length |\splittopskip| glue. % \begin{macrocode} \newcommand\SB@clearpage{% \SB@testtrue% \ifvoid\SB@pgbox% \ifdim\ht\SB@colbox=\z@\ifdim\dp\SB@colbox=\z@% \SB@testfalse% \fi\fi% \fi% \ifSB@test% \SB@cnt\SB@numcols% \advance\SB@cnt-\SB@colnum% \SB@nextcol\SB@cnt\lastcolglue% \SB@output2% \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% \SB@output2% \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@output0% \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. % % Implementation notes: % The |\null| is needed because the page builder consults |\pagetotal|, % which isn't updated by \TeX{} until a box is contributed (|\unvbox| doesn't % count). % Both |\nointerlineskip|s are needed because |\unvbox| fails to update % |\prevdepth|, and it doesn't make sense to inherit its value from whatever % preceeded this contribution. % Authors who want interline glue must therefore insert it explicitly at the % bottom of their contributed text. % \begin{macrocode} \newcommand\SB@styppage{% \ifnum\SB@numcols>\z@% \SB@clearpage% \unvbox\SB@songbox% \nointerlineskip\null% \else% \unvbox\SB@songbox% \fi% \nointerlineskip% } % \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} \SB@newcount\SB@groupcnt % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@clearpboxes} % This dynamically constructed macro clears the content of all boxes created % by the workings of |\includeonlysongs|. % \begin{macrocode} \newcommand\SB@clearpboxes{} % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@partbox} % Save a box of full-song or chorus material for later output when producing % a partial list using |\includeonlysongs|. % \begin{macrocode} \newcommand\SB@partbox[1]{% \SB@newbox#1% \SB@app\gdef\SB@clearpboxes{\setbox#1\box\voidb@x}% \global\setbox#1\box% } % \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% \SB@testfalse \@for\SB@temp:=\songlist\do{\ifx\SB@temp\SB@sgroup\SB@testtrue\fi}% \ifSB@test% \edef\SB@tempii{\SB@sgroup @\the\SB@groupcnt}% \expandafter\SB@partbox \csname songbox@\SB@tempii\endcsname\SB@songbox% \global\expandafter\let% \csname stype@\SB@tempii\endcsname\SB@stype% \ifrepchorus\ifvoid\SB@chorusbox\else% \expandafter\SB@partbox \csname chbox@\SB@tempii\endcsname\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@submitenv} % Submit the |\SB@envbox| box as a page-width contribution. % \begin{macrocode} \newcommand\SB@submitenv{% \begingroup% \let\SB@songbox\SB@envbox% \SB@styppage% \endgroup% } % \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{brk} \newcommand*\SB@songlistnc{nextcol} \newcommand*\SB@songlistcp{sclearpage} \newcommand*\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% \SB@clearpboxes% \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\copy% \csname songbox@\SB@tempii\endcsname% \expandafter\ifx\csname chbox@\SB@tempii\endcsname\relax% \repchorusfalse% \else% \repchorustrue% \setbox\SB@chorusbox\expandafter\copy% \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{\\} \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} \SB@newtoks\SB@titlelist \SB@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]{% \SB@app\gdef\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\relax% \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% \begingroup% \ifnum\SB@numcols>\z@% \hsize\ifpagepreludes\textwidth\else\SB@colwidth\fi% \fi% \leftskip\z@skip\rightskip\z@skip% \parfillskip\@flushglue\parskip\z@skip\parindent\z@% \global\setbox\SB@envbox\vbox{% \songmark% \unvbox\SB@songwrites% \ifpagepreludes\else\ifdim\sbarheight>\z@% \hrule\@height\sbarheight\@width\hsize% \nobreak\vskip5\p@\relax% \fi\fi% \resettitles% \begingroup% \songtarget{\ifnum\c@section=\z@1\else2\fi}% {song\theSB@songsnum-\thesongnum}% \endgroup% \vbox{\makeprelude}% \nobreak\vskip\SB@skip% \vskip\afterpreludeskip\relax% }% \ifnum\SB@numcols>\z@\hsize\SB@colwidth\fi% \global\setbox\SB@songbox\vbox{% \ifpagepreludes\else\unvbox\SB@envbox\fi% \unvbox\SB@songbox% \nobreak\vskip\SB@skip% \vskip\beforepostludeskip\relax% \nointerlineskip% \vbox{\makepostlude}% \ifdim\sbarheight>\z@% \nobreak\vskip2\p@\@plus\p@% \nointerlineskip% \hbox{\vrule\@height\sbarheight\@width\hsize}% \fi% }% \endgroup% \SB@insongfalse% \edef\SB@sgroup{\thesongnum}% \global\SB@groupcnt\z@% \ifpagepreludes\SB@submitenv\fi% \SB@submitsong% \ifnum\SB@grouplvl=\z@\let\SB@sgroup\@empty\fi% \stepcounter{songnum}% \else% \ifSB@intersong\SB@erreor\SB@closeall% \else\SB@erreot\fi% \fi% } % \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\relax% \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. % % Note that if you are redefining |\makeprelude|, you can probably replace % everything below with something much simpler. % The code below is lengthy because it accommodates all of the many different % options that various authors may adjust to customize their books. % If you redefine it, you can replace all of this with smaller, more % specialized programming that just outputs the prelude format you desire. % \begin{macrocode} \newcommand\makeprelude{% \resettitles% % \end{macrocode} % In slides mode, the title, references, and authors are simply centered on % the page with no song number. % Only the first of the song titles is included. % The references and authors only span the middle 50\% of the page, since % letting them span the whole page width stretches them out too much and makes % their fine print too hard to read. % \begin{macrocode} \ifslides% \hbox to\hsize{{\hfil\stitlefont\relax\songtitle\hfil}}% \vskip5\p@% \hbox to\hsize{% \hfil% \vbox{% \divide\hsize\tw@\parskip\p@\relax% \centering\small\extendprelude% }% \hfil% }% \else% % \end{macrocode} % In non-slides mode, we write the song number in a shaded box to the left % (if |\songnumwidth| is positive) and everything else in left-justified % paragraphs to the right of it (or centered if |\pagepreludes| is on). % The height of the shaded box that contains the song number depends on % which is higher: the natural height of the song number, or everything else % that goes to the right of it. % To find out which is higher, we start by putting the song number in its % own box (|\SB@boxii|). % \begin{macrocode} \ifdim\songnumwidth>\z@% \setbox\SB@boxii\hbox{{\SB@colorbox\snumbgcolor{% \hbox to\songnumwidth{% \printsongnum{\thesongnum}\hfil% }% }}}% \fi% % \end{macrocode} % Now we know the width $w$ of the song number box, so we typeset everything % else in a box (|\SB@box|) of width $c-w$, where $c$ is the column width. % (If |\pagepreludes| is on, we instead use width $c-2w$ so that the material % stays centered on the page.) % \begin{macrocode} \setbox\SB@box\vbox{% \ifdim\songnumwidth>\z@% \SB@dimen\wd\SB@boxii% \advance\SB@dimen3\p@% \ifpagepreludes\multiply\SB@dimen\tw@\fi% \advance\hsize-\SB@dimen% \fi% \ifpagepreludes\centering\else\SB@raggedright\fi% \offinterlineskip\lineskip\p@% {\stitlefont\relax% \songtitle\par% \nexttitle% \foreachtitle{(\songtitle)\par}}% \ifdim\prevdepth=\z@\kern\p@\fi% \parskip\p@\relax\tiny% \extendprelude% \kern\z@% }% % \end{macrocode} % If the song number is being printed (i.e., |\songnumwidth| is positive), % and its height is greater than the height of the other material, then we % just put |\SB@boxii| and |\SB@box| side-by-side. % If the song number is being printed but its height is less, then we % re-typeset it at height equal to the other material, and place the boxes % side-by-side. % Finally, if the song number is not being printed at all, we just unbox % |\SB@box| onto the vertical list. % \begin{macrocode} \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. % The default implementation just prints the copyright and licensing % information (if any) as a single, left-justified, non-indentended paragraph % in fine print. % \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 information in the prelude. % This macro is only called by |\extendprelude|, which is only called by % |\makeprelude|; so if you redefine either of those, you don't need this. % The default implementation prints the authors in boldface and shortens the % spacing after periods so that they don't look like ends of sentences. % \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. % This macro is only called by |\extendprelude|, which is only called by % |\makeprelude|; so if you redefine either of those, you don't need this. % The default implementation prints the scripture references in slanted % (oblique) font. % \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% \SB@pthead#1\SB@endparse% \endgroup% } % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@pthead} % \begin{macro}{\SB@@pthead} % \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{\futurelet\SB@next\SB@@pthead} \newcommand\SB@@pthead{% \ifcat\noexpand\SB@next\@sptoken% \expandafter\SB@@@pthead% \else% \expandafter\SB@ptmain% \fi% } \newcommand\SB@@@pthead{% \afterassignment\SB@pthead% \let\SB@next= } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\SB@ptloop} % The iterator of the title parser loop just scans the next token. % \begin{macrocode} \newcommand\SB@ptloop{\futurelet\SB@next\SB@ptmain} % \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\@sptoken% \let\SB@donext\SB@ptsp% \else\ifcat\noexpand\SB@next\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{}% \def\SB@donext{\SB@ptstep\SB@pthead}% \else% \def\SB@donext{\SB@ptstep\SB@ptloop}% \fi\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[2]{% \global\SB@titlelist\expandafter\expandafter\expandafter{% \expandafter\the\expandafter\SB@titlelist\the\SB@toks#2}% \SB@toks{}% #1} % \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\SB@ptloop{{#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@ptloop% \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@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\@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 descenders. % \begin{macrocode} \newcommand\SB@putbox[2]{% \begingroup% \SB@dimen\dp#2% #1#2% \setbox\SB@box\hbox{{\lyricfont\relax 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} \SB@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 whether this % verse should be numbered. % We use |\@ifstar| to scan ahead for the star, but this needs to be done % carefully because while scanning we might encounter tokens that % should be assigned different catcodes once the verse really begins. % Thus, we temporarily invoke |\SB@loadactives| for the duration of % |\@ifstar| so that everything gets the right catcode. % \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\relax\SB@setbaselineskip\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} \SB@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{SB@cmark} \newcommand*\SB@lastcmark{SB@lastcmark} \newcommand*\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\relax\SB@setbaselineskip\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\relax#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 are in a user-customizable font and parenthesized. % % 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% \echofont\relax% \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% \echofont\relax% \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} \SB@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{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@envbox\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\relax% \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@envbox\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@envbox\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} \SB@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 whether 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 whether the token was a begin-brace, end-brace, or space. % These tokens require special treatment because they cannot be % accepted as implicit arguments to macros. % \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\@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@trskip} % 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 whether % it's a note letter or some other recognized item. % If so, process it; otherwise just append it to the token list and continue % scanning. % \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 whether 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 whether it is an uppercase letter. % If so, add it to the note name being assembled; otherwise reinsert it into % the input stream and jump directly to the transposition logic. % \begin{macrocode} \newcommand\SB@trnotestep[1]{% \ifnum\uccode`#1=`#1% \SB@app\def\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 whether 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{{\meterfont\relax#1}}% \setbox\SB@boxii\hbox{{\meterfont\relax#2}}% \SB@dimen\wd\ifdim\wd\SB@box>\wd\SB@boxii\SB@box\else\SB@boxii\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% \let\SB@temp\relax% \ifdim\SB@dimen>\z@% \advance\SB@dimenii-.75\p@% \def\SB@temp{\kern.75\p@}% \fi% \SB@maxmin\SB@dimen<{.5\p@}% \SB@maxmin\SB@dimenii<\z@% \vbox{% \mark{\SB@measuremark}% \hbox to\SB@dimen{% \hfil% \box\SB@box% \hfil% }% \nointerlineskip% \hbox to\SB@dimen{% \hfil% \box\SB@boxii% \hfil% }% \SB@temp% \nointerlineskip% \hbox to\SB@dimen{% \hfil% \vrule\@width.5\p@\@height\SB@dimenii% \hfil% }% }% \meter{}{}% } % \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% } % \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 whether this chord % is immediately followed by whitespace or the remainder of a word. % If the latter, hyphenation might need to be introduced. % These macros keep track of the need for hyphenation, if any. % \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} \SB@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} \SB@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} \SB@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} \SB@newbox\SB@lyricbox \SB@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} % \changes{v3.0}{2017/04/19}{Fix transposition of replayed chord over ligature} % 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 \gdef\SB@setchord#1{% \SB@gettabindtrue\SB@nohattrue% \setbox\SB@chordbox\hbox{% \unhbox\SB@chordbox% \begingroup% \ifSB@trackch% \let\SB@activehat\SB@hat@tr% \else% \let\SB@activehat\SB@hat@notr% \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@otesta} % \begin{macro}{\SB@otestb} % The lyric-scanning code must preemptively determine whether the next token % is a macro declared |\outer| before it tries to accept that token as an % argument. % Otherwise \TeX{} will abort with a parsing error. % Macros declared |\outer| are not allowed in arguments, so determining % whether a token is |\outer| is a delicate process. % The following does so by consulting |\meaning|. % A macro can be identified as |\outer| if its meaning has the % word ``|\outer|'' before the first colon. % \begin{macrocode} \newcommand\SB@outertest{% \expandafter\SB@otesta\meaning\SB@next:\SB@otesta% } \newcommand\SB@otesta{} \edef\SB@otesta#1:#2\SB@otesta{% \noexpand\SB@otestb% #1\string\outer% \noexpand\SB@otestb% } \newcommand\SB@otestb{} \expandafter\def\expandafter\SB@otestb% \expandafter#\expandafter1\string\outer#2\SB@otestb{% \def\SB@temp{#2}% \ifx\SB@temp\@empty\SB@testfalse\else\SB@testtrue\fi% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\SB@UTFtest} % \begin{macro}{\SB@U@two} % \begin{macro}{\SB@U@three} % \begin{macro}{\SB@U@four} % \begin{macro}{\SB@@UTFtest} % \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\expandafter% \noexpand\SB@@UTFtest% \noexpand\meaning#1% \string\UTFviii@zero@octets% \noexpand\SB@@UTFtest% } \newcommand\SB@U@two{\global\SB@cnt\tw@} \newcommand\SB@U@three{\global\SB@cnt\thr@@} \newcommand\SB@U@four{\global\SB@cnt4\relax} \newcommand\SB@@UTFtest{} {\escapechar\m@ne \xdef\SB@temp{\string\@octets}} \edef\SB@temp{##1\string\UTFviii@##2\SB@temp} \expandafter\def\expandafter\SB@@UTFtest\SB@temp#3\SB@@UTFtest{% \SB@cnt\z@% {\csname SB@U@#2\endcsname}% } % \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% \SB@UTFtest\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% \else\ifcat\noexpand#3A% \SB@addDtest\SB@lettertests#1#2% \else% \SB@addDtest\relax0#2% \fi\fi\fi% \or% \SB@addNtest\SB@macrotests#1#2#3% \else% \SB@addMtest\SB@multitests#1#2#3\relax\relax\relax% \fi% } \newcommand\DeclareLyricChar{\SB@declare\SB@testtrue0} \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} % 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{} % \end{macrocode} % \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 whether it matches. % % \begin{macro}{\SB@addDtest} % A definition-test: The test succeeds if the next lyric token has the same % meaning (at test-time) of the non-macro, non-active character token that % was given to the |\Declare| macro. % \begin{macrocode} \newcommand\SB@addDtest[3]{% \ifx0#2\else% \def#1{{\csname SB@!\meaning\SB@next\endcsname}}% \expandafter\def\csname SB@!\meaning\SB@next\endcsname{\global#2}% \fi% \ifx0#3\else% \expandafter\def\csname SB@HT@\meaning\SB@next\endcsname{\global#3}% \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% \def#1{{\csname SB@!\SB@nextname\endcsname}}% \expandafter\def\csname SB@!\string#4\endcsname{\global#2}% \fi% \ifx0#3\else% \expandafter\def\csname SB@HT@\string#4\endcsname{\global#3}% \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[7]{% \edef\SB@temp{% \string#4% \ifx\relax#5\else\string#5\fi% \ifx\relax#6\else\string#6\fi% \ifx\relax#7\else\string#7\fi% }% \ifx0#2\else% \def#1{{\csname SB@!\SB@nextname\endcsname}}% \expandafter\def\csname SB@!\SB@temp\endcsname{\global#2}% \fi% \ifx0#3\else% \expandafter\def\csname SB@HT@\SB@temp\endcsname{\global#3}% \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\relax% } } \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{\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% \let\SB@chimpspace\SB@chnxtdone% \let\SB@chexpspace\SB@chnxtdone% \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} % % \begin{macro}{\SB@chnxtrelax} % \begin{macro}{\SB@chnxtstep} % \begin{macro}{\SB@chnxtdone} % To shorten the lyric parser macros that follow and thereby improve their % speed, we here define some abbreviations for common logic in untaken % branches. % \begin{macrocode} \newcommand\SB@chnxtrelax{\let\SB@donext\relax} \newcommand\SB@chnxtstep{\let\SB@donext\SB@chstep} \newcommand\SB@chnxtdone{\let\SB@donext\SB@chdone} % \end{macrocode} % \end{macro} % \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\[\SB@chnxtrelax% \else\ifx\SB@next\SB@activehat\SB@chnxtrelax% \else\ifx\SB@next\ch\SB@chnxtrelax% \else\ifx\SB@next\mch\SB@chnxtrelax% \else\ifx\SB@next`\SB@chnxtstep% \else\ifx\SB@next'\SB@chnxtstep% \else\ifx\SB@next"\SB@chnxtstep% \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 whether 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\SB@chnxtstep% \else% \SB@chnxtdone% \fi% \else% \SB@chtrymacro% \fi% } % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@chtrymacro} % Next, check to see whether it's a macro or active character. % We do these checks next because these are the only cases when the % token might be |\outer|. % Once we eliminate that ugly possibility, we can write the rest of % the code without having to worry about putting |\SB@next| in % places where |\outer| tokens are illegal. % \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\@sptoken% \SB@chexpspace% \else\ifcat\noexpand\SB@next\bgroup% \SB@chespace\let\SB@donext\SB@chbgroup% \else\ifcat\noexpand\SB@next\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\SB@chnxtstep% \else\ifcat\noexpand\SB@next.% \SB@testtrue\SB@othertests% \ifSB@test% \SB@chespace\SB@chnxtstep% \else% \SB@chnxtdone% \fi% \else% \SB@chespace\SB@chnxtstep% \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@outertest% \ifSB@test% \SB@chnxtdone% \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 whether it's a known macro or the beginning of a % multibyte-encoded international character. % If the former, dispatch some macro-specific code to handle it. % If the latter, grab the full multibyte sequence and include it in the lyric. % \begin{macrocode} \newcommand\SB@@chmacro{% \ifx\SB@next\SB@activehat% \SB@chnxtdone% \else\ifx\SB@next\SB@par% \SB@chnxtdone% \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% \SB@UTFtest\SB@next% \ifcase\SB@cnt\SB@chothermac% \or\or\SB@chespace\let\SB@donext\SB@chsteptwo% \or\SB@chespace\let\SB@donext\SB@chstepthree% \or\SB@chespace\let\SB@donext\SB@chstepfour\fi% \fi\fi\fi\fi\fi\fi\fi\fi% } % \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 whether it % begins with a non-escape character. % If so, it's probably an accenting or punctuation character made active % by the |inputenc| or |babel| packages. % Most such characters should be included in the lyric, so include it by % default; otherwise exclude it by default. % The user can override the defaults using |\DeclareLyricChar| and friends. % \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\SB@chnxtstep% \else% \SB@chnxtdone% \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}{\string#1\string#2}} \newcommand\SB@chstepthree[3]{% \SB@chmulti{#1#2#3}{\string#1\string#2\string#3}% } \newcommand\SB@chstepfour[4]{% \SB@chmulti{#1#2#3#4}{\string#1\string#2\string#3\string#4}% } \newcommand\SB@chmulti[2]{% \def\SB@next{#1}% \edef\SB@nextname{#2}% \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% \SB@chnxtstep% \else% \SB@chnxtdone% \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@chimpspace\SB@chnxtdone \newcommand\SB@chexpspace{} \let\SB@chexpspace\SB@chnxtdone % \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}% \let\SB@chimpspace\SB@chnxtstep% \let\SB@chespace\SB@chendspace% \let\SB@chdone\SB@chspcdone% \else% \let\SB@chimpspace\SB@chnxtdone% \let\SB@chexpspace\SB@chnxtdone% \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% \SB@chnxtdone% \else% \SB@chespace\SB@chnxtstep% \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@outertest% \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 whether 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\relax#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\@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% {\csname% SB@HT@\ifx\SB@nextname\relax\meaning\SB@next\else\SB@nextname\fi% \endcsname}% \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 whether hyphenation might be necessary. % The original lyric text might have ended in a string of one or more % explicit hyphens, enumerated by |\SB@numhyps|. % If it ended in exactly one, the lyric-scanning code suppresses that hyphen % so that we can here add a new hyphen that floats out away from the word % when the chord above it is long. % If it ended in more than one (e.g., the encoding of an en- or em-dash) then % the lyric-scanner leaves it alone; we must not add any hyphenation or float % the dash away from the word. % % There is also code here to insert a penalty that discourages linebreaking % immediately before lyricless chords. % Beginning a wrapped line with a lyricless chord is undesirable because it % makes it look as though the wrapped line is extra-indented (due to the % empty lyric space below the chord). % It should therefore happen only as a last resort. % \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 \ifnum\hyphenchar\font>\m@ne\char\hyphenchar\font\hfil\fi% }% \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@hat@tr} % In verses/choruses where chords are being memorized, |\SB@activehat| % gets set to this definition, which marks the current chord as immune to % memorization. % \begin{macrocode} \newcommand\SB@hat@tr{% \ifmmode^\else\global\SB@nohatfalse\fi% } % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@hat@notr} % In verses/choruses where chords are being replayed, |\SB@activehat| % get set to the following, which replays the next memorized chord and % subjects it to any required transposition and/or note conversion. % \begin{macrocode} \newcommand\SB@hat@notr{% \ifmmode^\else% \SB@lop\SB@ctail\SB@toks% \expandafter\transposehere\expandafter{\the\SB@toks}% \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} \SB@newtoks\SB@cr@ \SB@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\SB@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]{% \kern.5\SB@fretwidth\kern-.2\p@% \vrule\@height6\p@% \kern-.2\p@\kern-.5\SB@fretwidth% \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@doify} % \begin{macro}{\SB@@doify} % \begin{macro}{\SB@do} % Define the macro given in the first argument to equal the fully expanded % content of the second argument, but with |\SB@do| inserted before each token % or group. % \begin{macrocode} \newcommand\SB@do[1]{} \newcommand\SB@doify[2]{% \SB@toks{}% \edef#1{#2}% \expandafter\SB@@doify#1\SB@@doify% \edef#1{\the\SB@toks}% } \newcommand\SB@@doify[1]{% \ifx#1\SB@@doify\else% \SB@toks\expandafter{\the\SB@toks\SB@do{#1}}% \expandafter\SB@@doify% \fi% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\SB@allbarres} % \begin{macro}{\SB@dobarre} % Reserve a control sequence to remember all the stacks, start control % sequences, and end control sequences associated with barre delimiter pairs; % and a control sequence to perform an arbitrary action on them. % \begin{macrocode} \newcommand\SB@allbarres{} \newcommand\SB@dobarre{} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\SB@barreI} % \begin{macro}{\SB@barreN} % \begin{macro}{\SB@barreY} % As we process strings in order, barres in progress can be in one of three % states: initial (|\SB@barreI|), deactivated (|\SB@barreN|), or % tentatively activated (|\SB@barreY|). % \begin{macrocode} \newcommand\SB@barreI{\noexpand\SB@barreI} \newcommand\SB@barreN{\noexpand\SB@barreN} \newcommand\SB@barreY{\noexpand\SB@barreY} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\SB@lowfret} % \begin{macro}{\SB@@lowfret} % If we see a lower numbered fret than the current fret within a barre, % deactivate the barre. % (It has already been shown on an earlier fret.) % \begin{macrocode} \newcommand\SB@lowfret{% \let\SB@dobarre\SB@@lowfret\SB@allbarres% \SB@fretempty% } \newcommand\SB@@lowfret[3]{{% \let\SB@barreI\SB@barreN% \let\SB@barreY\SB@barreN% \xdef#1{#1}% }} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\SB@bactivate} % If we see the current fret within a barre, tentatively activate the barre % (unless it is already deactivated). % \begin{macrocode} \newcommand\SB@bactivate[3]{{% \let\SB@barreI\SB@barreY% \xdef#1{#1}% }} % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@bbarre} % Starting a barre group pushes it onto its stack in the initial state. % \begin{macrocode} \newcommand\SB@bbarre[1]{% \xdef#1{\SB@barreI{\the\SB@cntii}#1}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@ebarre} % \begin{macro}{\SB@@ebarre} % \begin{macro}{\SB@@@ebarre} % Ending a barre group pops it and draws it if it's active. % \begin{macrocode} \newcommand\SB@ebarre[3]{% \ifx#1\@empty% \ifnum\SB@cnt=\@ne\SB@errebar#2#3\fi% \else% \expandafter\SB@@ebarre#1\SB@@ebarre#1% \fi% } \newcommand\SB@@ebarre{} \def\SB@@ebarre#1#2#3\SB@@ebarre#4{{% \gdef#4{#3}% \let\SB@barreI\@gobble% \let\SB@barreN\@gobble% \let\SB@barreY\SB@barre% #1{#2}% }} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\SB@barreson} % \begin{macro}{\SB@barresoff} % Turn barre delimiters on or off, depending on whether we're typesetting % the interior or upper part of the tablature diagram. % \begin{macrocode} \newcommand\SB@barreson[3]{% \def#2{\SB@bbarre#1}% \def#3{\SB@ebarre#1#2#3}% } \newcommand\SB@barresoff[3]{\let#2\relax\let#3\relax} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\SB@fretempty} % \begin{macro}{\SB@fretdot} % \begin{macro}{\SB@@fretdot} % On a string in a fret diagram there can be nothing or a filled circle. % \begin{macrocode} \newcommand\SB@fretempty{% \advance\SB@cntii\@ne% \SB@onfret\relax% } \newcommand\SB@fretdot{% \advance\SB@cntii\@ne% \let\SB@dobarre\SB@bactivate\SB@allbarres% \SB@@fretdot% } \newcommand\SB@@fretdot{% \SB@onfret{% \fontencoding{OMS}\fontfamily{cmsy}% \fontseries{m}\fontshape{n}% \fontsize\@xiipt\@xiipt\selectfont\char15% }% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\SB@barre} % Draw a barre. % \begin{macrocode} \newcommand\SB@barre[1]{{% \SB@dimen\SB@fretwidth% \multiply\SB@dimen\SB@cntii% \advance\SB@dimen-#1\SB@fretwidth% \kern-\SB@dimen% \SB@@fretdot% \kern-.5\SB@fretwidth% \advance\SB@dimen-\SB@fretwidth% \raise.7pt\hbox{\vrule\@height4.6\p@\@width\SB@dimen}% \kern-.5\SB@fretwidth% \SB@@fretdot% }} % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@fretend} % At the end of a barred row in a tablature diagram, we auto-finish any % activated barres that weren't explicitly closed by the user. % \begin{macrocode} \newcommand\SB@fretend{{% \let\SB@barreI\@gobble% \let\SB@barreN\@gobble% \let\SB@barreY\SB@barre% \def\SB@dobarre##1##2##3{##1\gdef##1{}}\SB@allbarres% }} % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@finger} % \begin{macro}{\SB@X} % \begin{macro}{\SB@Z} % \begin{macro}{\SB@O} % If we're including fingering info in the tablature diagram, then below % each string there might be a number. % \begin{macrocode} \newcommand*\SB@X{X} \newcommand*\SB@Z{0} \newcommand*\SB@O{O} \newcommand\SB@finger[1]{% \def\SB@temp{#1}% \ifx\SB@temp\SB@X\SB@topempty\else% \ifx\SB@temp\SB@Z\SB@topempty\else% \ifx\SB@temp\SB@O\SB@topempty\else% \SB@atopfret{\sffamily\fontsize\@vipt\@vipt\selectfont#1}% \fi\fi\fi% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \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 \SB@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@gtinit} % \begin{macro}{\SB@gtinc} % Different meanings are assigned to digits, |X|'s, and |O|'s % as we typeset each row of the interior of the diagram. % These meanings are set by |\SB@gtinit| and |\SB@gtinc|. % \begin{macrocode} \newcommand\SB@gtinit{% \def\SB@do##1{\csname##1\endcsname}% \let\O\0% \let\3\2\let\4\2\let\5\2\let\6\2% \let\7\2\let\8\2\let\9\2% } \newcommand\SB@gtinc{% \advance\SB@cnt\@ne% \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\SB@lowfret% } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\BarreDelims} % \begin{macro}{\SB@bdelims} % Each pair of barre delimiters reserves a stack and augments the % initialization state to recognize those delimiters. % \begin{macrocode} \newcommand\BarreDelims[2]{% \expandafter\SB@bdelims\csname SB@bs@#1#2\expandafter\endcsname% \csname#1\expandafter\endcsname\csname#2\endcsname% } \newcommand\SB@bdelims[3]{% \newcommand*#1{}% \SB@app\def\SB@allbarres{\SB@dobarre#1#2#3}% } \BarreDelims() \BarreDelims[] % \end{macrocode} % \end{macro} % \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{{% \let\X\SB@topX\let\0\SB@topO% \let\1\SB@topempty\let\2\1% \SB@gtinit% \let\SB@dobarre\SB@barresoff\SB@allbarres% \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% \let\X\SB@fretempty\let\0\X% \let\1\SB@fretdot\def\2{\SB@fretempty\global\SB@testtrue}% \SB@gtinit% \let\SB@dobarre\SB@barreson\SB@allbarres% \SB@cnt\@ne% \loop% \SB@testfalse% \SB@fretbar\hbox{\SB@cntii\z@\SB@targstr\SB@fretend}% \ifnum\SB@cnt<\minfrets\SB@testtrue\fi% \ifSB@test\SB@gtinc\repeat% \SB@fretbar% \ifx\SB@targsfing\@empty\else% \kern1.5\p@% \hbox{\let\SB@do\SB@finger\SB@targfing}% \fi% }% \hfil% }% \kern3\p@% }% \SB@gettabindfalse% } % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@tabargs} % \begin{macro}{\SB@@tabargs} % \begin{macro}{\SB@ctoken} % \changes{v3.1}{2017/06/23}{Allow macros within 2nd gtab arg} % 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 or group, 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@doify\SB@targstr{#1}% \else\ifx\SB@temp\SB@ctoken% \SB@@tabargs#1\SB@@tabargs% \ifx\SB@temp\@empty% \def\SB@targfret{#1}% \SB@doify\SB@targstr{#2}% \else% \SB@doify\SB@targfing{#2}% \SB@doify\SB@targstr{#1}% \fi% \else% \def\SB@targfret{#1}% \SB@doify\SB@targfing{#3}% \SB@doify\SB@targstr{#2}% \fi\fi% } \newcommand\SB@@tabargs{} \def\SB@@tabargs#1#2\SB@@tabargs{\def\SB@temp{#2}} % \end{macrocode} % \end{macro} % \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}{\songtarget}\MainImpl{songtarget} % This macro is invoked by each \mac{beginsong} environment with two arguments: % (1) a suggested pdf bookmark index level, and % (2) a target name to which hyperlinks for this song in the index will refer. % The macro is expected to produce a suitable pdf bookmark entry and/or % link target. % The default definition tries to use |\pdfbookmark| if generating a PDF, % and resorts to |\hypertarget| (if it exists) otherwise. % The user can redefine the macro to customize how and whether bookmarks % and/or links are created. % \begin{macrocode} \newcommand\songtarget[2]{% \ifnum\@ne=0\ifSB@pdf\ifx\pdfbookmark\undefined\else% \ifx\pdfbookmark\relax\else1\fi\fi\fi\relax% \pdfbookmark[#1]{\thesongnum. \songtitle}{#2}% \else\ifx\hypertarget\undefined% \else\ifx\hypertarget\relax\else% \hypertarget{#2}{\relax}% \fi\fi\fi% } % \end{macrocode} % \end{macro} % % \begin{macro}{\songlink}\MainImpl{songlink} % This macro is invoked by the index code to produce a link to a song target % created by \mac{songtarget}. % Its two arguments are: % (1) the target name (same as the second argument to \mac{songtarget}, and % (2) the text that is to be linked. % The default implementation uses |\hyperlink| if it exists; otherwise it % just leaves the text unlinked. % \begin{macrocode} \newcommand\songlink{% \ifnum\@ne=0\ifx\hyperlink\undefined\else% \ifx\hyperlink\relax\else1\fi\fi\relax% \expandafter\hyperlink% \else% \expandafter\@gobble% \fi% } % \end{macrocode} % \end{macro} % % \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% \SB@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\SB@keepactive{\protect\SB@iwrite{#1}{#2}}% \fi% } % \end{macrocode} % \end{macro} % % \begin{macro}{\SB@keepactive} % By default, the |inputenc| package expands Unicode characters into macro % names when writing them to files. % This behavior must be inhibited when writing to the |.sxc| file, since % |songidx| needs the original Unicode characters for sorting. % To achieve this, we temporarily redefine most active characters so that % they expand to an unexpandable string version of themselves. % \begin{macrocode} \newcommand\SB@keepactive{} {\catcode`\~\active \catcode`\.12 \def\\#1#2{% \endgroup \SB@app\gdef\SB@keepactive{\def#1{#2}}% } \def\SB@temp#1#2{% \SB@cnt#1\relax \loop \begingroup \uccode`\~\SB@cnt \uccode`\.\SB@cnt \uppercase{\\~.} \ifnum\SB@cnt<#2\relax \advance\SB@cnt\@ne \repeat } \SB@temp{1}{8} \SB@temp{11}{11} \SB@temp{14}{91} \SB@temp{93}{255} } % \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} \SB@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 script 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@allindexes\@empty% \SB@warnnoidx% \else\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\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@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, its 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@envbox\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}{% \ifsepindexes% \global\setbox\SB@box\vbox{% \null% \vfil% \unvcopy\SB@envbox% \vskip.5in\@minus.3in\relax% \hbox to\hsize{% \hfil% \vbox{% \SB@idxsetup% \renewenvironment{idxblock}[1]% {\begin{SB@smidx}{####1}}{\end{SB@smidx}}% \let\\\SB@idxitemsep% \input{\csname SB@idxfilename@#3\endcsname.sbx}% }% \hfil% }% \vskip\z@\@plus2fil\relax% }% % \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@envbox% \vskip1em\relax% \hbox to\hsize{\hfil[Index not yet generated.]\hfil}% \vskip\z@\@plus2fil\relax% }% \else% \unvbox\SB@envbox% \hbox to\hsize{\hfil[Index not yet generated.]\hfil}% \fi% }% \ifsepindexes\clearpage\fi% \endgroup\fi% } % \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@envbox% \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{% \ifnum\idxheadwidth>\z@% \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@}% \else% \renewenvironment{SB@lgidx}[1]{}{}% \fi% \renewenvironment{SB@smidx}[1]{}{}% \renewcommand\idxentry[2]{% \SB@ellipspread{\idxtitlefont\relax\ignorespaces##1\unskip}% {{\idxrefsfont\relax##2}}% }% \renewcommand\idxaltentry[2]{% \SB@ellipspread{\idxlyricfont\relax\ignorespaces##1\unskip}% {{\idxrefsfont\relax##2}}% }% \SB@displayindex% } % \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@warnnoidx} % \begin{macrocode} \newcommand\SB@warnnoidx{% \SB@Warn{Index command has no effect since no indexes are ye% t declared}% } % \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@errebar} % \begin{macrocode} \newcommand\SB@errebar[2]{% \SB@Error{Ignoring unbalanced \expandafter\@gobble\string#2 i% n \protect\gtab}{Found no \expandafter\@gobble\string#1 to ma% tch the \expandafter\@gobble\string#2.}% } % \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}{\ifsongindexes} % \begin{macro}{\ifsepindexes} % \begin{macro}{\ifpagepreludes} % \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\ifsongindexes\songindexestrue \newif\ifsepindexes\sepindexestrue \newif\ifpagepreludes \newif\ifSB@colorboxes \IfFileExists{color.sty}\SB@colorboxestrue\SB@colorboxesfalse \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} % \begin{macro}{\pagepreludes} % The |\nolyrics| and |\pagepreludes| macros are just shorthand for % |\nolyricstrue| and |\pagepreludestrue|, respectively. % \begin{macrocode} \newcommand\nolyrics{} \let\nolyrics\nolyricstrue \newcommand\pagepreludes{\pagepreludestrue\songpos0} % \end{macrocode} % \end{macro} % \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} % % \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 \SB@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