%% file: chordbars.sty
%% Copyright 2018-2024 M. Sebastien Kramm
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3c
% of this license or (at your option) any later version.
% The latest version of this license is in
%   http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
% This work has the LPPL maintenance status `maintained'.
%
% The Current Maintainer of this work is M. Sebastien Kramm
%
% This work consists of the files chordbars.sty and chordbars_manual.tex

% Home page: https://github.com/skramm/chordbars


% LOG:
% - 20240302: bugfixes with ycoef (version 1.3.2)
% - 20230331: added "ycoeff" parameter (version 1.3.1)
% - 2020525
% - added \addMeasures command
% - added starred version of chordbar environment

% TODO define command to have 1 chord per beat

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{chordbars}[2024-03-02 version 1.3.2]

\RequirePackage{tikz}
\RequirePackage{pgfmath}
\RequirePackage{tkz-euclide}

\usetikzlibrary{math,shapes}

\RequirePackage{calc}
\RequirePackage{ifthen}
\RequirePackage{wasysym} % for \fullmoon

\RequirePackage{relsize} % added on 2020-01-18

\def\vspacebefore{1ex}
\def\vspaceafter{1ex}

% This \dim command is used for diminished chords (until we find a nicer alternative)
\def\dim{\fullmoon}

\def\MajS{$\Delta$}
\def\addN{\relscale{0.8}\mdseries add9}
\def\susF{\relscale{0.8}\mdseries sus4}
%\def\add4{\relscale{0.8}\mdseries add4}

\newcommand{\songtitle}
{
%\tikzstyle{block} = [draw, rectangle, fill=blue!50,, text centered, minimum height=8mm,node distance=10em]
 \begin{center}%
       \begin{tikzpicture}[line width=1.5pt]
       \tikzstyle{block} = [rectangle, draw, text width=30em, text centered, minimum height=4em]
%       \tikzstyle{block} = [rectangle, draw, text centered, minimum height=4em]
%       \tikzstyle{block} = [rectangle, draw, minimum height=4em]
       \node [block,font=\fontsize{20}{28}\selectfont\bfseries] (init) { \@title\\ \@author };
       \end{tikzpicture}
 \end{center}%
 \par
 \vskip 1.5em
}

\newcounter{NumMesure}
\newcounter{NumPart}
\newcounter{CurrentBarInLine}
\newcounter{CurrentBar}
\newcounter{CurrentLine}

\xdef\tempoBPM{100}

\newcommand{\bpm}[1]
{
       \xdef\tempoBPM{#1}
       \rightline{Tempo=#1 BPM}
}

% "Beats Per Bar"
% default value
\xdef\bpb{4}

\newcommand{\bpbfour}
{
       \xdef\bpb{4}
}
\newcommand{\bpbthree}
{
       \xdef\bpb{3}
}

\newcommand{\resetchordbars}
{
       \setcounter{NumMesure}{0}
       \setcounter{NumPart}{0}
       \setcounter{CurrentBarInLine}{0}
}

\newcommand{\addMeasures}[1]
{
       \addtocounter{NumMesure}{#1}
       \setcounter{NumPart}{0}
       \setcounter{CurrentBarInLine}{0}
}

\newcommand{\printNbBars}
{
       \ifthenelse{\boolean{printBarNumber}}
       {
               Total number of bars: \arabic{NumMesure}, duration=\pgfmathparse{\theNumMesure/\tempoBPM*60*\bpb}\pgfmathresult {} s.
       }{}
}

% This boolean will be used to adjust horizontal position of the
% number of repetitions when a half bar is added (see \addHalfBar)
\newboolean{hasHalfBar}
%\setboolean{hasHalfBar}{false}

\newboolean{printBarNumber}

\newcommand{\countbarsYes}
{
       \setboolean{printBarNumber}{true}
}

\newcommand{\countbarsNo}
{
       \setboolean{printBarNumber}{false}
}

\def\barsize{1.6}%
\def\ycoeff{0.8}%
\def\delta{0.36}

\def\chordFontSize{\normalsize \bfseries}
\def\titleFontSize{\large \bfseries}

\xdef\NumberOfBarsPerLine{4}

% arg1: chord
% arg2: number of bars
% arg3: title
\newcommand{\chordline}[3]
{
       {\fontfamily{phv}\selectfont
       \noindent\ignorespaces %
       \vspace{\vspacebefore}
       \refstepcounter{NumMesure}%
       \refstepcounter{NumPart}%
       \begin{tikzpicture}[line width=1pt,x=1cm,y=-1cm]

% draw part title
       \ifthenelse
               {\boolean{printBarNumber}}
               {
                       \draw (0,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize]
                               {- Part \theNumPart: #3};
                       \draw (-.3,.5*\barsize) node
                               {\bf \theNumMesure};
               }
               {
                       \draw (0,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize] {#3};
               }

       \draw (0,0) -- (#2*\barsize,0);               % horizontal lines
       \draw (0,\barsize*\ycoeff) -- (#2*\barsize,\barsize*\ycoeff);

       \draw (0,0) -- (0,\barsize*\ycoeff);                  % first vertical line
       \draw (\barsize,0) -- (\barsize,\barsize*\ycoeff);    % second vertical line
       \draw (\barsize/2,\ycoeff*\barsize/2) node [font=\chordFontSize]{#1};      % chord name

       \foreach \k in {2,...,{#2}}
       {
               \draw (\k*\barsize,0) -- (\k*\barsize,\barsize*\ycoeff);

               \pgfmathsetmacro{\Axa}{(\k-1)*\barsize+\delta*\barsize}
               \pgfmathsetmacro{\Axb}{\k*\barsize-\delta*\barsize}
               \pgfmathsetmacro{\Aya}{(1-\delta)*\barsize*\ycoeff}
               \pgfmathsetmacro{\Ayb}{\delta*\barsize*\ycoeff}

               \coordinate (A) at (\Axa,\Ayb);
               \coordinate (B) at (\Axb,\Aya);

               \fill (A) circle[radius=2pt];
               \fill (B) circle[radius=2pt];
               \draw [thick] (\Axa,\Aya) -- (\Axb,\Ayb); % Draw "repeat" symbol
       }

       \end{tikzpicture}
       }
       \addtocounter{NumMesure}{#2}
       \addtocounter{NumMesure}{-1}
}

%==========================================================================
% main environment, has 2 mandatory arguments
% arg 1 (#2 inside): total number of 4 beat bars (4, 8, ...)
% arg 2 {#3 inside}: part name (can be empty)
% optional arg: nb of repetitions (default is 1)

% starred version: does not print the grid ! Only does the counters update, and prints these
\newenvironment{chordbar*}[3][1]
{
       \refstepcounter{NumPart}
       \refstepcounter{NumMesure}

       \@ifundefined{c@TmpA}{\newcounter{TmpA}}{}
       \setcounter{TmpA}{#1*#2+\value{NumMesure}-1}

       \@ifundefined{c@TmpB}{\newcounter{TmpB}}{}
       \setcounter{TmpB}{#1*#2}

       \fontfamily{phv}\selectfont
       \noindent\ignorespaces %
%       \vspace{\vspacebefore}

       \begin{tikzpicture}
       \ifthenelse
               {\boolean{printBarNumber}}
               {\pgfmathsetmacro{\xpos}{0.6}}
               {\pgfmathsetmacro{\xpos}{0}}

       \draw (0,0) node {}; % to align with other environments of the page

       % if we have repetitions, we print it and also the total number of bars
       \ifnum#1=1
                       {\draw (\xpos,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize]
                               {- Part \theNumPart: #3, #2 bars, [ \theNumMesure {} $\rightarrow$ \theTmpA {} ] }; }
       \else
                       {\draw (\xpos,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize]
                               {- Part \theNumPart: #3, #2 bars $\times$ #1 (\theTmpB), [ \theNumMesure {} $\rightarrow$ \theTmpA {} ] }; }
       \fi

       \end{tikzpicture}

       \setcounter{NumMesure}{\value{TmpA}}
}


\newenvironment{chordbar}[3][1]
{
   % "newline" command: just switches to next line
       \newcommand{\newchordline}
       {
               \setcounter{CurrentBarInLine}{0}
               \refstepcounter{CurrentLine}
       }

       \newcommand{\chordf}[1]%
       {
               \ifthenelse
                       {\theCurrentBarInLine=\NumberOfBarsPerLine}
                       {
                               \refstepcounter{CurrentLine}
                               \setcounter{CurrentBarInLine}{0}
                       }
                       {}
               \refstepcounter{CurrentBarInLine}%
               \pgfmathsetmacro{\x}{-\barsize/2+\theCurrentBarInLine*\barsize}
               \pgfmathsetmacro{\y}{\value{CurrentLine})*\barsize*\ycoeff+\barsize*\ycoeff/2}
               \draw (\x,\y) node [font=\chordFontSize]{##1};%
       }%

       \newcommand{\chordh}[2]%
       {
               \ifthenelse
                       {\theCurrentBarInLine=\NumberOfBarsPerLine}
                       {
                               \refstepcounter{CurrentLine}
                               \setcounter{CurrentBarInLine}{0}
                       }
                       {}
               \refstepcounter{CurrentBarInLine}%
%               \typeout{CurrentBarInLine=\theCurrentBarInLine}
               \draw ( %
                       {\barsize*(\theCurrentBarInLine-1)}, %
                       {(\theCurrentLine+1)*\barsize*\ycoeff} %
               ) %
               -- %
               ( %
                       {\theCurrentBarInLine*\barsize}, %
                       {\theCurrentLine*\barsize*\ycoeff} %
               );
               \draw (                                              % print first chord
                       {-3*\barsize/4+\theCurrentBarInLine*\barsize},
                       {\theCurrentLine*\barsize*\ycoeff+1*\barsize/4*\ycoeff}
               ) node [font=\chordFontSize]{##1};
               \draw (                                               % print second chord
                       {-\barsize/4+\theCurrentBarInLine*\barsize},
                       {\theCurrentLine*\barsize*\ycoeff+3*\barsize/4*\ycoeff}
               ) node [font=\chordFontSize]{##2};%
       }

       \newcommand{\repeatBar}%
       { %
               \ifthenelse
                       {\theCurrentBarInLine=\NumberOfBarsPerLine}
                       {
                               \refstepcounter{CurrentLine}
                               \setcounter{CurrentBarInLine}{0}
                       }
                       {}
               \refstepcounter{CurrentBarInLine}%

               \pgfmathsetmacro{\Axa}{(\theCurrentBarInLine-1)*\barsize+\delta*\barsize}
               \pgfmathsetmacro{\Axb}{\theCurrentBarInLine*\barsize-\delta*\barsize}
               \pgfmathsetmacro{\Aya}{(1-\delta)*\barsize*\ycoeff+\theCurrentLine*\barsize*\ycoeff}
               \pgfmathsetmacro{\Ayb}{\delta*\barsize*\ycoeff+\theCurrentLine*\barsize*\ycoeff}

               \coordinate (A) at (\Axa,\Ayb);
               \coordinate (B) at (\Axb,\Aya);

               \fill (A) circle[radius=2pt];
               \fill (B) circle[radius=2pt];
               \draw [thick] (\Axa,\Aya) -- (\Axb,\Ayb); %
       }%

       \newcommand{\repeatBarPair}%
       { %
               \pgfmathsetmacro{\Axa}{\theCurrentBarInLine*\barsize+\delta*\barsize}
               \pgfmathsetmacro{\Axb}{(\theCurrentBarInLine+2)*\barsize-\delta*\barsize}
               \pgfmathsetmacro{\Aya}{(1-\delta)*\barsize*\ycoeff+\theCurrentLine*\barsize*\ycoeff}
               \pgfmathsetmacro{\Ayb}{\delta*\barsize*\ycoeff+\theCurrentLine*\barsize*\ycoeff}

               \coordinate (A) at (\Axa,\Ayb);
               \coordinate (B) at (\Axb,\Aya);

               \fill (A) circle[radius=2pt];
               \fill (B) circle[radius=2pt];
               \draw [thick] (\Axa,\Aya) -- (\Axb,\Ayb); %
               %
               \refstepcounter{CurrentBarInLine}
               \refstepcounter{CurrentBarInLine}
               \ifnum\value{CurrentBarInLine}=#2
               {
                       \refstepcounter{CurrentLine}
                       \setcounter{CurrentBarInLine}{0}
               }
               \fi
       }%

       \newcommand{\addHalfBar}[1]%
       {
               \setboolean{hasHalfBar}{true}
%
% The part might have some repetitions (arg 1), so we need to increment
% NumMesure by the number of repetions
               \addtocounter{NumMesure}{#1}
%
               \refstepcounter{CurrentBarInLine}%

% diagonal line
%       \draw (\xa,\ya) -- (\xb,\yb);  A BUG HERE: investigate
               \draw
               (\theCurrentBarInLine*\barsize,{\theCurrentLine*\barsize*\ycoeff})
                       --
               ({(\theCurrentBarInLine-1)*\barsize},{(\theCurrentLine+1)*\barsize*\ycoeff});

% horizontal line
               \draw
               (\theCurrentBarInLine*\barsize,{\theCurrentLine*\barsize*\ycoeff})
                       --
               ({(\theCurrentBarInLine-1)*\barsize},{(\theCurrentLine)*\barsize*\ycoeff});

               \pgfmathsetmacro{\x}{-3*\barsize/4+\theCurrentBarInLine*\barsize}
               \pgfmathsetmacro{\y}{\value{CurrentLine})*\barsize*\ycoeff+\barsize/4}
               \draw (\x,\y) node [font=\chordFontSize]{##1};%

       }

% HERE beginning of environment code
%       \typeout{chordbar: START #3}

       \fontfamily{phv}\selectfont
       \setcounter{CurrentLine}{0}
       \setcounter{CurrentBarInLine}{0}
       \setcounter{CurrentBar}{0}
%       \setboolean{hasHalfBar}{true}
       \setboolean{hasHalfBar}{false}

       \refstepcounter{NumPart}%
       \refstepcounter{NumMesure}%
       \noindent\ignorespaces %
       \vspace{\vspacebefore}
%\resizebox{8cm}{!} {
%       \scalebox{2}{
       \begin{tikzpicture}[line width=1pt,x=1cm,y=-1cm] %,scale=2]

       \ifthenelse
               {\boolean{printBarNumber}}
               {\draw (-.3,.5*\barsize) node{\bf \theNumMesure};}
               {}

% compute the number of bars of the first line
       \xdef\NbBarsInitialLine{\NumberOfBarsPerLine}
       \ifthenelse
               {#2<\NumberOfBarsPerLine}
               {\xdef\NbBarsInitialLine{#2}}
               {}

% initial horizontal line
       \draw (0,0) -- (\NbBarsInitialLine*\barsize,0);

% draw part title
       \ifthenelse
               {\boolean{printBarNumber}}
               {\draw (0,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize]
                       {- Part \theNumPart: #3};}
               {\draw (0,-\barsize*.2) node [anchor=west, align=left,font=\titleFontSize]
                       {- #3};}

       \pgfmathtruncatemacro{\nblines}{(#2-1)/\NumberOfBarsPerLine+1}
%       \typeout{chordbarl: nblines=\nblines}
       \foreach \line in {1,...,\nblines}
       {

               \draw (0,{\barsize*\ycoeff*(\line-1)}) -- (0,\line*\barsize*\ycoeff); % first vertical line
               \xdef\nbbars{\NumberOfBarsPerLine}
               \ifnum\line=\nblines
               {
                       \pgfmathtruncatemacro{\nbbars}{#2-\NumberOfBarsPerLine*(\nblines-1)}
                       \xdef\nbbars{\nbbars}
               }
               \fi
%               \typeout{chordbarl: nbbars=\nbbars}
               \foreach \k in {1,...,{\nbbars}}
               {
                       \draw (\k*\barsize,{(\line-1)*\barsize*\ycoeff}) -- (\k*\barsize,{\line*\barsize*\ycoeff});
                       \draw (0,{\line*\barsize*\ycoeff}) -- (\k*\barsize,{\line*\barsize*\ycoeff});

                       \refstepcounter{CurrentBar}%
               }
       }
       \setcounter{NumMesure}{#1*#2+\value{NumMesure}-1}

% print the number of repetitions
       \ifnum#1=1 {} % do nothing
       \else
%--------------------
% THIS HERE IS WIP !
               \ifthenelse
                        {\boolean{hasHalfBar}}
                        {\def\xoffset{2.0}}
                        {\def\xoffset{1.5}}
%--------------------
               \ifthenelse
                       {\boolean{printBarNumber}}
                       {\draw (\NbBarsInitialLine*\barsize+\xoffset,0.5*\barsize) node {\Large \bf $\times$~#1};}
                       {}
       \fi
}%
{
%\typeout{chordbar: END}
       \end{tikzpicture}
%       } %
%       \par\noindent%
%       \ignorespacesafterend
       \vspace{\vspaceafter}
}

% REMOVE INDENTATION
\setlength\parindent{0pt}

% so the user can use # without escaping
% see https://tex.stackexchange.com/questions/467562
\AtBeginDocument{\catcode`#=12 }

% additional code: redefine sharp and flat in text mode
% from https://tex.stackexchange.com/a/422249/11083
\let\OLDsharp\sharp
\renewcommand{\sharp}{\ensuremath{\OLDsharp}}
\let\OLDflat\flat
\renewcommand{\flat}{\ensuremath{\OLDflat}}

\endinput