%GregorioTeX file.
%Copyright (C) 2007 Elie Roux <elie.roux@telecom-bretagne.eu>
%
%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 3 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, see <http://www.gnu.org/licenses/>.

% this file contains definitions for lines, initial, fonts, etc.

%%%%%%%%%%%%%%%%%%
%% engine checking
%%%%%%%%%%%%%%%%%%

% a if to see if we are called with lua(la)tex or not
\newif\ifgreluatex
% Set \ifgreluatex accordingly
\expandafter\ifx\csname directlua\endcsname\relax
  \greluatexfalse
\else
  \greluatextrue
\fi

% if we are not under LuaTeX, we check if we are under lamed or omega...
% if not, we output an error message

\ifgreluatex\else
  \expandafter\ifx\csname localrightbox\endcsname\relax
    \errmessage{Error: this document must be compiled with Aleph (lamed) or LuaTeX (lualatex)}
  \fi
\fi

% we need to check if luatextra is loaded or not
\newif\ifgreluatextra
\expandafter\ifx\csname newluaattribute\endcsname\relax
  \greluatextrafalse
\else
  \ifgreluatex
    \greluatextratrue
  \else
    \greluatextrafalse
  \fi
\fi

% we need to check if luatextra is in a recent version... even if it will
% certainly keep backward compatibility, it's better to be sure...
\newif\ifgreluatextranew
\expandafter\ifx\csname newluatexattribute\endcsname\relax
  \greluatextranewfalse
\else
  \ifgreluatex
    \greluatextranewtrue
  \else
    \greluatextranewfalse
  \fi
\fi

% in TeXLive 2009, the extra primitives of LuaTeX have a luatex prefix, and are not
% available without prefix. We mostly rely on \directlua that is still available
% without prefix, but we also rely on the Omega primitives, that have a luatex 
% prefix in TeXLive 2009.
\newif\ifgreluatexnew
\expandafter\ifx\csname luatexlocalleftbox\endcsname\relax
  \let\grelocalleftbox\localleftbox
  \let\grelocalrightbox\localrightbox
  \greluatexnewfalse
\else
  \let\grelocalleftbox\luatexlocalleftbox
  \let\grelocalrightbox\luatexlocalrightbox
  \greluatexnewtrue
\fi

% an attribute we put on the text nodes.
% if it is 1, it means that there may be a dash here if this syllable is at the end of a line
% if it is 2, it means that it's never useful to typeset a dash
% if it is 0, it just means that we are in a score...
\ifgreluatextranew
  \newluatexattribute\gregorioattr
\else
  \ifgreluatextra
    \newluaattribute\gregorioattr
  \else
    \ifgreluatex
      \ifgreluatexnew
        \luatexattributedef\gregorioattr=987
      \else
        \attributedef\gregorioattr=987
      \fi
    \fi
  \fi
\fi
  
% if we are used with LuaTeX we need to define some version-specific functions
%: Cross your fingers (and your toes)
\ifgreluatex
  \ifnum\luatexversion<36
    \def\gredirectlua{\directlua0}
  \else
    \ifgreluatextranew
      \let\gredirectlua\luadirect
%        \let\gredirectlua\directlua
    \else
      \ifgreluatextra
        \let\gredirectlua\luadirect
%        \let\gredirectlua\directlua
      \else
        \let\gredirectlua\directlua
      \fi
    \fi
  \fi
\fi
  
\ifgreluatextranew
%  \let\greloadluamodule\luatexUseModule
    \let\greloadluamodule\RequireLuaModule
\else
  \ifgreluatextra
    \let\greloadluamodule\luaUseModule
  \else
    \ifgreluatex
      \def\greloadluamodule#1{\gredirectlua{dofile(kpse.find_file('#1.lua'))}}
    \else
      \def\greloadluamodule#1{}
    \fi
  \fi
\fi

\greloadluamodule{gregoriotex}

\ifgreluatextra
  \def\greunsetattribute{\unsetluaattribute{\gregorioattr}}
\else
  \ifgreluatex
    \def\greunsetattribute{%
      \ifnum\luatexversion<37\relax %
        \gregorioattr=-1\relax %
      \else %
        \gregorioattr=-"7FFFFFFF\relax %
      \fi %
    }
  \fi
\fi



%%%%%%%%%%%%%%%%%%%%%%%
%% aux file definitions
%%%%%%%%%%%%%%%%%%%%%%%

% for now, we only use an aux file with LuaTeX

\ifgreluatex
  \newwrite\Greaux
\fi

\def\grewriteaux#1{%
  \ifgreluatex %
    \write\Greaux{#1}%
  \fi %
  \relax %
}

\def\opengreaux{%
  \ifgreluatex %
    \openout\Greaux \jobname .gaux\relax%
  \fi %
}

\def\closegreaux{%
  \ifgreluatex %
    \closeout\Greaux %
  \fi %
}


%%%%%%%%%%%%%%
%% basic start
%%%%%%%%%%%%%%

% factor is the factor with which you open you font (the number after the at). It will decide almost everything (spaces, etc.), so it is particularly important.
% at the beginning it is set to 0, but if it is still 0 when begingregorianscore is called, it is set to the default value : 17 (the value that makes it look like a standard graduale)
\newcount\grefactor
\grefactor=0

%%%%%%%%%%%%%%%%%%
%% vertical spaces
%%%%%%%%%%%%%%%%%%

\input gregoriotex-spaces.tex

% \grestafflinewidth is the width of a line of staff, this can vary, for example at the first line
\newdimen\grestafflinewidth

% \grelinewidth is the width of a line of a score (including the initial)
\newdimen\grelinewidth
\grelinewidth=\hsize 
\grestafflinewidth=\grelinewidth 

% to calculate that, we take the bottom of the third line : it is at 200 in the fonts, and it must be at grespacelinestext + grespacebeneathtext + 2*greinterstafflinespace + 2*grestafflineheight + translationheight
\def\grecalculateconstantglyphraise{%
  \global\greconstantglyphraise = -22000 sp%
  \global\multiply\greconstantglyphraise by \the\grefactor %
  \global\advance\greconstantglyphraise by \greadditionalbottomspace %
  \global\advance\greconstantglyphraise by \grespacebeneathtext %
  \global\advance\greconstantglyphraise by \grespacelinestext %
  \global\advance\greconstantglyphraise by \greinterstafflinespace %
  \global\advance\greconstantglyphraise by \greinterstafflinespace %
  \global\advance\greconstantglyphraise by \grestafflineheight %
  \global\advance\greconstantglyphraise by \grestafflineheight %
  \global\advance\greconstantglyphraise by \grecurrenttranslationheight %
  % an adjustment in the case of big lines
  \global\advance\greconstantglyphraise by \grestafflinediff %
  \relax %
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% macros for additionnal vertical spaces
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% temporary value for space for the translation, beneath the text
\newdimen\grecurrenttranslationheight

% macro to tell gregorio to set space for the translation
\def\greaddtranslationspace{%
  \global\grecurrenttranslationheight=\gretranslationheight %
  \global\gretextlower=\grespacebeneathtext %
  \global\advance\gretextlower by \gretranslationheight %
  \gregeneratelines %
  \grecalculateconstantglyphraise %
  \relax %
}

\def\greremovetranslationspace{%
  \global\grecurrenttranslationheight=0 sp%
  \global\gretextlower=\grespacebeneathtext %
  \gregeneratelines %
  \grecalculateconstantglyphraise %
  \relax %
}

%macro to call if you want to go to the next line simply
\def\grenewline{%
  \grenewlinecommon{0}{0}{0}{0}{0}%
  \relax%
}

% macro called to go to the next line but when there are additional vertical spaces to add
%% 1: can be 0, 1 or 2 or 3. 1 is when there is a note above the 4th line, 2 when there is a note on the 5th line, and 3 when there is a note above the 5th line
%% 2: idem, but with the bottom line (-1th). It can be 4, in the case of a bottom note with a vertical episemus.
%% 3: 1 if there is a translation somewhere
% #4 is if 1 if we have space above the staff
\def\grenewlinewithspace#1#2#3#4{%
  \grenewlinecommon{#1}{#2}{#3}{0}{#4}%
  \relax%
}


% basically same macros as above, but these one do a \hfill, the lines are not justified
%macro to call if you want to go to the next line simply
\def\grenewparline{%
  \grenewlinecommon{0}{0}{0}{1}{0}%
  \relax%
}

\def\grenewparlinewithspace#1#2#3#4{%
  \grenewlinecommon{#1}{#2}{#3}{1}{#4}%
}

% a macro describing a kern to make before ending the line, which we sometimes want (see \syllable)
\xdef\grekernbeforeeol{0pt\relax}

% the macro we call each time we force a changing of line, it automatically sets \greknownline, and adjusts left spaces
\def\grenewlinecommon#1#2#3#4#5{%
  % sometimes we need to add a space before ending the line:
  \kern\grekernbeforeeol\relax %
  \ifnum\greboxing=0\relax %
    \ifnum\grebiginitial=1\relax %
      \ifcase\greknownline %
      % 0: should not happend...
      \or % 1
        \greadjustsecondline %
      \or %2
        \greadjustthirdline %
      \fi %
    \fi %
    \global\advance\greknownline by 1\relax %
    \greupdateadditionalspaces{#1}{#2}%
    \ifnum#3 = 1\relax %
      \greaddtranslationspace %
    \else %
      \greremovetranslationspace %
    \fi %
    \ifnum#5 = 1\relax %
      \greaddspaceabove %
    \else %
      \greremovespaceabove %
    \fi %
    \global\grelastoflinecount=2\relax %
    \greupdateleftbox %
    \ifnum#4=1\relax %
      \hfill %
    \fi %
    \penalty-10001 %
  \fi %
  \relax %
}

% two dimensions for the additionalspaces
\newdimen\greadditionalbottomspace
\newdimen\greadditionaltopspace

% same arguments as grenewlinewithspace
\def\greupdateadditionalspaces#1#2{%
  \ifcase#1\relax %
    \global\greadditionalbottomspace=0 sp%
  \or % case 1
    \global\greadditionalbottomspace=0 sp%
    % here we don't add any space... it's just in case...
  \or % case 2
    \global\greadditionaltopspace=15000 sp%
    \global\multiply\greadditionaltopspace by \the\grefactor %
  \or % case 3
    \global\greadditionaltopspace=30000 sp%
    \global\multiply\greadditionaltopspace by \the\grefactor %
  \fi %
  \ifcase#2\relax %
    % case 0
    \global\greadditionalbottomspace=0 sp%
  \or % case 1
    \global\greadditionalbottomspace=0 sp%
  \or % case 2
    \global\greadditionalbottomspace=15000 sp%
    \global\multiply\greadditionalbottomspace by \the\grefactor %
  \or % case 3
    \global\greadditionalbottomspace=30000 sp%
    \global\multiply\greadditionalbottomspace by \the\grefactor %
  \or % case 4
    \global\greadditionalbottomspace=45000 sp%
    \global\multiply\greadditionalbottomspace by \the\grefactor %
  \fi %
  \gregeneratelines %
  \grecalculateconstantglyphraise %
  \relax %
}

%% macros for additional bottom space for the first line

% #1 is 1, 2 or 3, with the same signification as in grenewlinewithspace
\def\grefirstlinebottomspace#1#2{%
  \ifcase#1\relax %
    % case 0
    \global\greadditionalbottomspace=0 sp%
  \or % case 1
    \global\greadditionalbottomspace=0 sp%
  \or % case 2
    \global\greadditionalbottomspace=15000 sp%
    \global\multiply\greadditionalbottomspace by \the\grefactor %
  \or % case 3
    \global\greadditionalbottomspace=30000 sp%
    \global\multiply\greadditionalbottomspace by \the\grefactor %
  \fi %
  \ifnum#2=1\relax %
    \greaddtranslationspace %
  \else %
    \greremovetranslationspace %
  \fi %
  \gregeneratelines %
  \grecalculateconstantglyphraise %
  \relax %
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% macros for the typesetting of text
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% \gretextlower is the height of the separation between the bottom line (which is invisible : for the notes which are very low) and the bottom of the text
\newdimen\gretextlower
\gretextlower=\grespacebeneathtext
%\advance\gretextlower by \translationheight

%% macro that sets \gretempwidth to the width of its argument

\newbox\GreTempwidth
\newdimen\gretempwidth

\def\grewidthof#1{%
  \setbox\GreTempwidth=\hbox{#1}%
  \global\gretempwidth=\wd\GreTempwidth%
  \relax%
}

%% macro that typesets the text of the syllable, and sets \gretextaligncenter to the middle of the middle letters, it is needed because we align the note (often the middle of the note) with the middle of the middle letters
%% warning : gretextaligncenter is the width from the beginning of the letters to the middle of the middle letters

\newdimen\gretextaligncenter

\def\grefindtextaligncenter#1#2{%
  \grewidthof{\gretextformat{#1#2}}%
  \global\gretextaligncenter=\the\gretempwidth %
  \grewidthof{\gretextformat{#2}}%
  \divide\gretempwidth by 2 %
  \global\advance\gretextaligncenter by -\the\gretempwidth%
  \relax%
}

% definition of the dash that we will use after the text if necessary
\def\gregoriotextdash{-}
\newdimen\gregoriotextdashwidth
\grewidthof{\gregoriotextdash}
\gregoriotextdashwidth=\gretempwidth

\def\grewritetranslation#1{%
  \raise\grespacebeneathtext\hbox to 0pt{\vbox to 0pt{\vss\hbox to 0pt{\gretranslationformat{#1}\hss}}}%
  \relax %
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% macros for the typesetting of the initial
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%this dimention is the additional space that we have to add to the localleftbox sometimes. For now it is used only for the initials on two lines
\newdimen\greadditionalleftspace

%% box containing the initial, and dimen containing its width (and the width of the space after)
\newbox\GreInitial
\newdimen\greinitialwidth
\greinitialwidth= 0 pt


% grebiginitial means that the inital takes two lines
\newcount\grebiginitial

% greknownline is the line we think we are in
\newcount\greknownline

% macro to call before the call of \initial
\def\gresetbiginitial{%
  \global\grebiginitial=1\relax %
  \relax %
}

% macro to cancel before the call of \initial
\def\grenormalinitial{%
  \global\grebiginitial=0\relax %
  \relax %
}

% macro to call before the first syllable, but after setinitialclef
\def\greadjustsecondline{%
  \greadditionalleftspace=\greinitialwidth %
  \greupdateleftbox %
  \relax %
}

% macro to call during the second line
\def\greadjustthirdline{%
  \greadditionalleftspace= 0 pt%
  \greupdateleftbox %
  \relax %
}

\def\greupdateleftbox{%
  \greupdatelinewidth %
  \greupdatelinesclef %
}

\def\greupdatelinewidth{%
  \ifdim\greadditionalleftspace=0pt%
  \else %
    \gretempdim=\grestafflinewidth %
    \global\advance\grestafflinewidth by -\greadditionalleftspace %
    \gregeneratelines %
    \global\grestafflinewidth=\gretempdim %
  \fi %
}

\def\greinitial#1{%
  % see comments on this function to see what it does
  \gresetaboveinitialraise %
  % we print the initial always at the same place, and the we print the GreAboveinitialfirstbox  centered
  % first we print the initial
  \gretempdim=-\gretextlower %
  % if it is a big initial we print it on the second line 
  \ifnum\grebiginitial=0\relax %
    \setbox\GreInitial=\hbox{\greinitialformat{#1}}%
    \global\greinitialwidth=\the\wd\GreInitial %
    \setbox\GreInitial=\hbox{\raise -\gretempdim\hbox{\greinitialformat{#1}}}%
  \else %
    \advance\gretempdim by \greadditionalbottomspace %
    \advance\gretempdim by \grespacebeneathtext %
    \advance\gretempdim by \grespacelinestext %
    \advance\gretempdim by 4\greinterstafflinespace %
    \advance\gretempdim by 4\grestafflineheight %
    \advance\gretempdim by \grecurrenttranslationheight %
    \setbox\GreInitial=\hbox{\grebiginitialformat{#1}}%
    \global\greinitialwidth=\the\wd\GreInitial %
    \setbox\GreInitial=\hbox{\vbox to 0pt{\hbox{\raise -\gretempdim\hbox{\grebiginitialformat{#1}}}\vss}}%
  \fi %
  \hskip\grebeforeinitialshift %
  \copy\GreInitial%
  \hskip\greafterinitialshift %
  \global\advance\greinitialwidth by \greafterinitialshift%
  \global\advance\greinitialwidth by \grebeforeinitialshift %
  % then we center the first box above the initial, if there is one
  \ifdim\wd\GreAboveinitialfirstbox=0 pt\relax %
  \else %
    \gretempdim=\greinitialwidth %
    \advance\gretempdim by -\wd\GreAboveinitialfirstbox  %
    \divide\gretempdim by 2 %
    \hskip -\greinitialwidth %
    \kern\gretempdim %
    \raise\greaboveinitialfirstraise\copy\GreAboveinitialfirstbox  %
    \kern\gretempdim %
    \setbox\GreAboveinitialfirstbox=\hbox{}%
  \fi %
  % then we center the second box above the initial, if there is one
  \ifdim\wd\GreAboveinitialsecondbox=0 pt\relax %
  \else %
    \gretempdim=\greinitialwidth %
    \advance\gretempdim by -\wd\GreAboveinitialsecondbox %
    \divide\gretempdim by 2 %
    \hskip -\greinitialwidth %
    \kern\gretempdim %
    \raise\greaboveinitialsecondraise\copy\GreAboveinitialsecondbox %
    \kern\gretempdim %
    \setbox\GreAboveinitialsecondbox=\hbox{}%
  \fi %
  \relax %
}

\def\grenoinitial{%
  \setbox\GreInitial=\hbox{}%
  \global\greinitialwidth=0pt %
  \global\grelastoflinecount=2\relax %
  \relax %
}

% We set two boxes for the two lines above the initial

\newbox\GreAboveinitialfirstbox
\newdimen\greaboveinitialfirstraise
\newbox\GreAboveinitialsecondbox
\newdimen\greaboveinitialsecondraise
% the height difference between the bottom of the first annotation line and the top of the second annotation line (above the initial) is controlled by the \greaboveinitialseparation space, in gregoriotex-spaces.tex

\def\gresetfirstlineaboveinitial#1#2{%
  \ifnum\grefactor=0\relax %
    \setgrefactor{17}%
  \fi %
  % we align the top of the box with the top of the line
  % here the variables are a bit strange... we can calculate the final value of greaboveinitialfirstraise only after the beginning of the score, after the call to this macro. So we just set greaboveinitialfirstraise to the negative value the #2 will add, and then, after the beginning of the score, we'll add gresetaboveinitialraise that will... set greaboveinitialfirstraise.
  \setbox\GreAboveinitialfirstbox=\hbox{#2}%
  \global\greaboveinitialfirstraise=-\ht\GreAboveinitialfirstbox %
  \global\setbox\GreAboveinitialfirstbox=\hbox{#1}%
  \relax %
}

\def\gresetfirstannotation#1{%
  \gresetfirstlineaboveinitial{#1}{#1}%
  \relax %
}

\let\setfirstannotation\gresetfirstannotation

\def\gresetsecondannotation#1{%
  \ifnum\grefactor=0\relax %
    \setgrefactor{17}%
  \fi %
  \setbox\GreAboveinitialsecondbox=\hbox{#1}%
  \global\greaboveinitialsecondraise=-\ht\GreAboveinitialsecondbox %
  \global\advance\greaboveinitialsecondraise by -\greaboveinitialseparation %
  \relax %
}

\let\setsecondannotation\gresetsecondannotation

%here we set the true raises of the two lines above the inital
\def\gresetaboveinitialraise{%
  \global\advance\greaboveinitialfirstraise by \grestaffheight %
  \global\advance\greaboveinitialfirstraise by \grespacebeneathtext %
  \global\advance\greaboveinitialfirstraise by \grecurrenttranslationheight %
  \global\advance\greaboveinitialfirstraise by \grespacelinestext %
  \global\advance\greaboveinitialfirstraise by \greadditionalbottomspace %
  \global\advance\greaboveinitialsecondraise by \greaboveinitialfirstraise %
  \relax %
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% macros for the typesetting the things above the initial
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\def\writemode#1{%
  \gresetfirstlineaboveinitial{\sc{\bf{#1}}}{\sc{\bf{#1}}}%
  \relax %
}

\def\gregorianmode#1{%
  \ifcase#1%
  \or%
    \writemode{I}%
  \or%
    \writemode{II}%
  \or%
    \writemode{III}%
  \or%
    \writemode{IV}%
  \or%
    \writemode{V}%
  \or%
    \writemode{VI}%
  \or%
    \writemode{VII}%
  \or%
    \writemode{VIII}%
  \fi%
  \relax%
}

\def\scorereference#1{%
  \relax%
}

%% macro that draws the lines : starts by the first and then draws the lines of every line.
%% has to be called before drawing the key, after drawing the initial
\def\grebeginnotes{%
  \gredrawfirstlines %
  %%localeleftbox is a primitive of Omega, it draws the same box at the beginning of new lines (here after the first)
  \grelocalleftbox{%
    \copy\GreLines %
  }%
  \relax %
}

\def\commentary#1{%
  \vbox{\hfill\hbox{#1}}%
  \relax %
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% macro for putting text above lines for annotations and the like
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newdimen\grecurrentabovelinestextheight
\grecurrentabovelinestextheight = 0pt

% additional space for the text above lines
\def\greabovelinestextstyle#1{%
#1\relax %
}

% set space above the text lines - almost the same as for the translation
\def\greaddspaceabove{%
  \global\grecurrentabovelinestextheight=\greabovelinestextheight %
  \gregeneratelines %
  \relax %
}

% we don't need space above any more
\def\greremovespaceabove{%
  \global\grecurrentabovelinestextheight=0 sp%
  \gregeneratelines %
  \relax %
}

% the code is a bit strange here: we always execute \grespaceabovelines at the beginning of a glyph. This will:
%  - typeset the text above the lines if relevant, and making sure we execute it only once
%  - not do anything else

\xdef\grecurrenttextabovelines{}

\def\gresettextabovelines#1{%
  \gdef\grecurrenttextabovelines{%
    \gretypesettextabovelines{#1}%
    \gdef\grecurrenttextabovelines{}%
    \relax %
  }%
}

% typesets the text above the line
\def\gretypesettextabovelines#1{%
  \global\gretempdim=\greabovelinestextraise %
  \global\advance\gretempdim by 4\grestafflineheight %
  \global\advance\gretempdim by 4\greinterstafflinespace %
  \global\advance\gretempdim by \grespacebeneathtext %
  \global\advance\gretempdim by \grecurrenttranslationheight %
  \global\advance\gretempdim by \grespacelinestext %
  \global\advance\gretempdim by \greadditionalbottomspace %
  \leavevmode\raise\gretempdim\hbox to 0pt{\greabovelinestextstyle{#1}\hss}%
  \relax %
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% macros for the typesetting of the lines
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%% first a macro to prevent the typesetting of the lines (useful for some people)
\xdef\greremovelinescount{0}

\def\greremovelines{%
  \xdef\greremovelinescount{1}%
  \relax %
}

\def\gredonotremovelines{%
  \xdef\greremovelinescount{0}%
  \relax %
}

%% macro that draws the stafflines on the first line, it is different from others due to the initial that can take some place, without lines
\def\gredrawfirstlines{%
  \advance\grestafflinewidth by -\greinitialwidth%
  %\greinitialwidth=0pt%
  \hbox to0pt{%
    \vbox{%
      \grenormalstafflinesformat %
      \vskip\grecurrentabovelinestextheight %
      \vskip\greadditionaltopspace %
      \ifnum\greremovelinescount=0\relax %
        \hrule height \grestafflineheight width \grestafflinewidth %
      \else %
        \vskip\grestafflineheight %
      \fi %
      \kern\the\greinterstafflinespace %
      \ifnum\greremovelinescount=0\relax %
        \hrule height \grestafflineheight width \grestafflinewidth %
      \else %
        \vskip\grestafflineheight %
      \fi %
      \kern\the\greinterstafflinespace %
      \ifnum\greremovelinescount=0\relax %
        \hrule height \grestafflineheight width \grestafflinewidth %
      \else %
        \vskip\grestafflineheight %
      \fi %
      \kern\the\greinterstafflinespace %
      \ifnum\greremovelinescount=0\relax %
        \hrule height \grestafflineheight width \grestafflinewidth %
      \else %
        \vskip\grestafflineheight %
      \fi %
      \vskip\grespacelinestext %
      \vskip\grespacebeneathtext %
      \vskip\grecurrenttranslationheight %
      \vskip\greadditionalbottomspace %
    }%
    \hss%
  }%
  \grestafflinewidth=\grelinewidth%
  \relax%
}

%% box containing the stafflines for other lines than the first
\newbox\GreLines

% macro that must be called at each change of linewidth and grefactor
\def\gregeneratelines{%
  \setbox\GreLines=\hbox to0pt{%
    \vbox{%
      \grenormalstafflinesformat %
      \vskip\grespaceabovelines %
      \vskip\grecurrentabovelinestextheight %
      \ifnum\greremovelinescount=0\relax %
        \hrule height \grestafflineheight width \grestafflinewidth %
      \else %
        \vskip\grestafflineheight %
      \fi %
      \kern\the\greinterstafflinespace %
      \ifnum\greremovelinescount=0\relax %
        \hrule height \grestafflineheight width \grestafflinewidth %
      \else %
        \vskip\grestafflineheight %
      \fi %
      \kern\the\greinterstafflinespace %
      \ifnum\greremovelinescount=0\relax %
        \hrule height \grestafflineheight width \grestafflinewidth %
      \else %
        \vskip\grestafflineheight %
      \fi %
      \kern\the\greinterstafflinespace %
      \ifnum\greremovelinescount=0\relax %
        \hrule height \grestafflineheight width \grestafflinewidth %
      \else %
        \vskip\grestafflineheight %
      \fi %
      \vskip\grespacelinestext %
      \vskip\greadditionalbottomspace %
      \vskip\grespacebeneathtext %
      \vskip\grecurrenttranslationheight %
    }%
    \hss%
  }%
  \relax %
}

% macro called when the initial is big, and so when the second line is at the same level as the first
\def\gresmallsecondline{%
  \gretempdim=\grestafflinewidth %
  \global\advance\grestafflinewidth by -\greinitialwidth %
  \gregeneratelines %
  \global\grestafflinewidth=\gretempdim %
  \relax %
}

% macro called when we are after the second line of a big initial, to have normal lines back
\def\grenormallines{%
  \global\grestafflinewidth=\grelinewidth %
  \gregeneratelines %
  \relax %
}

\input gregoriotex-signs.tex

\input gregoriotex-syllable.tex

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% macros for the chironomic signs lines
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% here is a quite special macro called at beggining of lines, that inserts a line of chironomic signs
\def\greinsertchiroline{%
  \ifgreluatex %
    % the first line is a special case
    \ifnum\greknownline=1\relax %
      % some bugs appear if we don't box it
      \hbox{\gredirectlua{grechiro.printLine()}}%
      \par %
      % TODO: this line bugs with my version of LuaTeX
      %\penalty -10001\relax%
      \kern\grebelowsignsspace %
      %\penalty -10001\relax %
      \noindent %
    \else %
      % not very beaufiful, I don't like to make a new par inside a score, but....
      \grelocalleftbox{}%
      \grelocalrightbox{}%
      \par %
      \kern\greabovesignsspace %
      \noindent\hbox{\gredirectlua{grechiro.printLine()}}%
      \greupdateleftbox %
      \par %
      \penalty 10001\relax %
      \kern\grebelowsignsspace %
      \penalty 10001\relax %
      \noindent %
    \fi %
  \fi %
  \relax %
}

%macro to call just after begingregorioscore, if there are some chironomic signs
\def\greactivatechironomy{%
  \ifgreluatex %
    % we print the absolute position of the beginning of the score, and the width of a line, to get the absolute positions of the begginning and end of lines
    \pdfsavepos %
    \grewriteaux{begin:\number\pdflastxpos}%
    \grewriteaux{width:\number\grestafflinewidth}%
    \greloadluamodule{gregoriotex-ictus}%
    \gredirectlua{%
    grechiro.atBeginScore()}%
  \fi %
  \relax %
}

% count that is 1 or 0 if we need to print the small vertical bars in the chironomic line
\newcount\printchirovbars
\printchirovbars=1


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% other macros
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% gregorioattr (see its definition in gregorio-syllable) is 0 when we are in a score, and unset when we are not

%macro called at the beginning of a score
\def\begingregorioscore{%
  % not sure it's perfect to put that here, but it's the only way I found to make it work....
  \global\grelinewidth=\hsize %
  \ifgreluatex%
    \gregorioattr=0\relax %
  \fi %
  \global\grestafflinewidth=\grelinewidth %
  \gregeneratelines %
  \ifnum\grefactor=0\relax %
    \setgrefactor{17}%
    \gresetverticalspaces %
  \fi %
  \noindent%
  \ifgreluatex %
    \gredirectlua{%
    gregoriotex.atScoreBeggining()%
    }%
  \fi %
  %TODO do something like LaTeX's AtBeginDocument
  \ifdefined\optgabcAtScoreBeginning %
    \optgabcAtScoreBeginning %
  \fi %
  \global\greknownline=1\relax %
  \relax%
}

%macro called at the beginning of a score
\def\endgregorioscore{%
  \global\grelastoflinecount=0\relax %
  \global\greblockcusto=0\relax %
  \grelocalleftbox{}%
  \ifnum\keeprightbox=0 %
    \grelocalrightbox{}%
  \fi %
  \hfil %
  \ifgreluatex%
    \greunsetattribute %
  \fi %
  \par%
  \ifnum\keeprightbox=1 %
    \grelocalrightbox{}%
    \global\keeprightbox=0 %
  \fi%
  \ifgreluatex % with some versions of LuaTeX, the \localrightbox and \localleftbox must be set empty in an environment with the good attributes set
    \grelocalleftbox{}%
    \grelocalrightbox{}%
  \fi
  \setbox\GreAboveinitialfirstbox=\hbox{}%
  \greupdateadditionalspaces{0}{0}%
  \grenormalinitial %
  \ifgreluatex %
    \gredirectlua{%
    gregoriotex.atScoreEnd()%
    }%
  \fi %
  \relax%
}

%macro to call when there is just a little thing that will go to the last line, when it is not necessary
\def\grenolastline{%
  \ifdim\greenddifference > 0 pt %
    \ifdim\grenextbegindifference > 0 pt %
      \hskip\greinterwordspacenotes %
    \else % (next begin difference >0pt)
      \hskip\greinterwordspacenotestext %
    \fi %
  \else%(enddifference < Opt)
    \ifdim\grenextbegindifference < 0 pt %
      \hskip\greinterwordspacetext %
    \else %(next begin difference < 0 pt)
      \hskip\greinterwordspacetextnotes %
    \fi %
  \fi %
  \global\greendofscore=1 %
  \grelocalrightbox{}%
  \grelocalleftbox{}%
  \penalty 1000 %
  \relax%
}

% macro called at each end of word
\def\greendofword#1{%
  \penalty -1000%
  \ifnum#1=1\relax %
    \ifdim\greenddifference > 0 pt %
      \ifdim\grenextbegindifference > 0 pt %
        \hskip\greinterwordspacenotes %
      \else % (next begin difference >0pt)
        \hskip\greinterwordspacenotestext %
      \fi %
    \else %(enddifference < Opt)
      \ifdim\grenextbegindifference < 0 pt %
        \hskip\greinterwordspacetext %
      \else %(next begin difference < 0 pt)
        \hskip\greinterwordspacetextnotes %
      \fi %
    \fi %
  \fi %
  %\global\greenddifference=0pt %
  \relax%
}

% macro called at the end of a word or syllable when the next thing is a bar
\def\greendbeforebar#1{%
  \penalty 10001%
  \ifnum#1=1\relax %
    \ifdim\greenddifference > 0 pt %
      \ifdim\grenextbegindifference > 0 pt %
        \hskip\grenotebarspace %
      \else % (next begin difference >0pt)
        \hskip\gretextbartextspace %
      \fi %
    \else%(enddifference < Opt)
      \ifdim\grenextbegindifference < 0 pt %
        \hskip\gretextbartextspace %
      \else %(next begin difference < 0 pt)
        \hskip\greinterwordspacetextnotes %
      \fi %
    \fi %
  \fi %
  \penalty 10001%
  %\global\greenddifference=0pt %
  \relax %
}

% macro called at the end of a bar. Almost the same, but not for the penalties
\def\greendafterbar#1{%
  \penalty -2000%
  \ifnum#1=1\relax %
    \ifdim\greenddifference > 0 pt %
      \ifdim\grenextbegindifference > 0 pt %
        \hskip\grenotebarspace %
      \else % (next begin difference >0pt)
        \hskip\gretextbartextspace %
      \fi %
    \else%(enddifference < Opt)
      \ifdim\grenextbegindifference < 0 pt %
        \hskip\gretextbartextspace %
      \else %(next begin difference < 0 pt)
        \hskip\greinterwordspacetextnotes %
      \fi %
    \fi %
  \fi %
  \penalty -2000%
  %\global\greenddifference=0pt %
  \relax %
}

\newcount\grelastoflinecount

% TODO: case where we're at the beginning *and* end of a line... quite rare case though...
% macro to tell gregorioTeX no to put a space after the current syllable (otherwise it may cause annoying black boxes in the pdf if written in plainTeX)
% 0 if nothing
% 1 if the syllable is the last of the line
% 2 after it has finished the syllable, so when it is two it means that the syllable is the first of a line
\def\grelastofline{%
  \global\grelastoflinecount=1\relax%
  \relax%
}

% same as above, but for the score. For now it is the same behaviour.
\def\grelastofscore{%
  \grelocalleftbox{}%
  \greblockcustos %
  \global\grelastoflinecount=1\relax%
  \relax%
}

% a macro to disable (or reenable) the left shift for first syllables of scores
\edef\gredisableeolshifts{0}

\def\GreDisableEOLShifts{%
  \xdef\gredisableeolshifts{1}%
}

\def\GreEnableEOLShifts{%
  \xdef\gredisableeolshifts{0}%
}

% a count that is 1 if we block the custo, and 0 if we don't. We just block custos at the end of a score, to prevent a bug.
\newcount\greblockcusto

% macro to suppress the custos
\def\greblockcustos{%
  \global\greblockcusto=1\relax %
  \grelocalrightbox{}%
  \relax %
}

% macro called at each end of syllable which is not an end of word
\def\greendofsyllable{%
  \penalty -500%
  \relax%
}

% macro to end elements, #1 is the type of space, it can be : 
%% 0: default space 
%% 1: larger space
%% 2: glyph space
%% 3: zero-width space
% #2 is if the space is unbreakable (1) or not (0)

\def\greendofelement#1#2{%
  \ifnum #2=0\relax %
    \penalty -1000%
  \else %
    \penalty 10001%
  \fi %
  \ifcase#1%
    \hskip\greinterelementspace %
  \or% case 1
    \hskip\grelargerspace %
  \or% case 2
    \hskip\greglyphspace %
  \fi%
  \ifnum #2=1\relax %
    \penalty 10001%
  \fi %
\relax%
}

% macro to end a glyph without ending the element, argument is the type of space, it can be : 
%% 0: default space 
%% 1: zero width space
%% 2: space between flat or natural and a note
%% 3: space between two puncta inclinata
%% 7: space between a punctum inclinatum and a punctum inclinatum deminutus
%% 8: space between two puncta inclinata deminuti
%% 4: space between bivirga or trivirga
%% 5: space between bistropha or tristropha
%% 6: space after a punctum mora XXX: not used yet, not so sure it is a good idea...
%% 7: space between a punctum inclinatum and a punctum inclinatum debilis
%% 8: space between two puncta inclinata debilis
%% 9: space before a punctum (or something else) and a punctum inclinatum
%% 10: space between puncta inclinata (also debilis for now), larger ambitus (range=3rd).
%% 11: space between puncta inclinata (also debilis for now), larger ambitus (range=4th or more)
\def\greendofglyph#1{%
  \penalty 10001%
  \ifcase#1%
    \hskip\greinterglyphspace %
  \or% case 1
    \hskip\grezerowidthspace %
  \or% case 2
    \hskip\grealterationspace %
  \or% case 3
    \hskip\grepunctuminclinatumshift %
  \or% case 4
    \hskip\grebitrivirspace %
  \or% case 5
    \hskip\grebitristrospace %
  \or% case 6
    \hskip\grespaceaftersigns %
  \or% case 7
    \hskip\grepunctuminclinatumanddebilisshift %
  \or% case 8
    \hskip\grepunctuminclinatumdebilisshift %
  \or% case 9
    \hskip\grebeforepunctainclinatashift %
  \or% case 10
    \hskip\grepunctuminclinatumbigshift %
  \or% case 11
    \hskip\grepunctuminclinatummaxshift %
  \fi%
  \penalty 10001%
  \relax%
}

\input gregoriotex-symbols.tex

%%%%%%%%
%% fonts
%%%%%%%%

\def\gretilde{%
  \ensuremath{\sim}%
  \relax %
}

\def\greitalic#1{%
  {\it #1}%
  \relax %
}

\def\gresmallcaps#1{%
  {\sc #1}%
  \relax %
}

\def\greboldfont#1{%
  {\bf #1}%
  \relax %
}

\def\grett#1{%
  {\tt #1}%
  \relax %
}

\def\greul#1{%
  {#1}%
  \relax %
}

% the default gregorio font
\xdef\gregoriofontname{greciliae}

\def\setgregoriofont#1{%
  \xdef\gregoriofontname{#1}%
  \ifnum\grefactor=0\else %
    \gretempdimcount = \the\grefactor %
    \multiply\gretempdimcount by 100000 %
    \global\font\gregoriofont=#1 at \the\gretempdimcount sp%
  \fi %
  \relax%
}

\xdef\greusestylefont{0}

% gregoriostylefont is the font used for additional glyphs
\def\gresetstylefont{%
  \ifnum\grefactor=0\else %
    \gretempdimcount = \the\grefactor %
    \multiply\gretempdimcount by 100000 %
    \global\font\gregoriostylefont=greextra at \the\gretempdimcount sp%
  \fi %
  \relax%
}

\def\gretextformat#1{%
  #1\relax %
}

\def\gretranslationformat#1{%
  \greitalic{#1}%
  \relax %
}

\def\grenormalstafflinesformat{%
  \relax %
}

\def\greadditionalstafflinesformat{%
  \relax %
}

\def\GreSetStaffLinesFormat#1{%
  \global\def\greadditionalstafflinesformat{#1\relax }%
  \global\def\grenormalstafflinesformat{#1\relax }%
  \relax %
}

\def\greinitialformat#1{%
  \font\grefontofinitial=pncr at 40pt%
  {\grefontofinitial #1}%
  \relax %
}

\def\grebiginitialformat#1{%
  \font\grefontofgrebiginitial=pncr at 80pt%
  {\grefontofgrebiginitial #1}%
  \relax %
}

\def\setgrefactor#1{%
  \ifnum\grefactor=0\relax %
    \changedimenfactor{1}{#1}%
  \else %
    \changedimenfactor{\grefactor}{#1}%
  \fi %
  \global\grefactor=#1\relax %
  \gresetverticalspaces %
  \gregeneratelines %
  \setgregoriofont{\gregoriofontname}%
  \ifnum\greusestylefont=1\relax %
  \gresetstylefont %
  \fi %
  \relax %
}

%%%%%%%%%%%%%%%%%%
%% score including
%%%%%%%%%%%%%%%%%%

% function that includes a score in TeX format
\def\greincludetexscore#1{%
  \input #1%
  \relax %
}

% function provided for backward compatibility
\let\includetexscore\greincludetexscore
\let\includescore\includetexscore

% TODO: comment, lamed version?
\def\greincludegabcscore#1{%
  \ifgreluatex %
    \gredirectlua{gregoriotex.include_gabc_score([[#1]])}%
  \else %
    \errmessage{GregorioTeX error: you must use LuaTeX to use \string\includegabcscore}%
  \fi %
  \relax %
}

\let\includegabcscore\greincludegabcscore

%%%%%%%%%%%%%%%%%%%%%%%%%%
%% some hyphen definitions
%%%%%%%%%%%%%%%%%%%%%%%%%%

% a zero-width hyphen, useful for fine tuning line endings. To input in gabc verb for example.
\def\grezerhyph{%
  \hbox to 0pt{%
  %-%
  \char\the\hyphenchar\font %
  \hss %
  }%
}

% a normal hyphen
\def\grenormalhyph{%
  %-%
  \char\the\hyphenchar\font %
  \relax %
}

% the definition that will be always used for end of lines hyphens in gregorio, except if one of the two before is explicitely used
\let\grehyph\grenormalhyph 

% two macros to change the definition of the hyphen:
\def\GreUseNormalHyphen{%
  \global\let\grehyph\normalhyph %
}

\def\GreUseZeroHyphen{
  \global\let\grehyph\zerhyph %
}
