%:strip
% Part of the ptx2pdf macro package for formatting USFM text
% copyright (c) 2020 by SIL International
% written by David Gardner 
%
% Permission is hereby granted, free of charge, to any person obtaining  
% a copy of this software and associated documentation files (the  
% "Software"), to deal in the Software without restriction, including  
% without limitation the rights to use, copy, modify, merge, publish,  
% distribute, sublicense, and/or sell copies of the Software, and to  
% permit persons to whom the Software is furnished to do so, subject to  
% the following conditions:
%
% The above copyright notice and this permission notice shall be  
% included in all copies or substantial portions of the Software.
%
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,  
% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF  
% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND  
% NONINFRINGEMENT. IN NO EVENT SHALL SIL INTERNATIONAL BE LIABLE FOR  
% ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  
% CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  
% WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
%
% Except as contained in this notice, the name of SIL International  
% shall not be used in advertising or otherwise to promote the sale,  
% use or other dealings in this Software without prior written  
% authorization from SIL International.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% generic chapter.verse / milestone / etc trigger support for the ptx2pdf package
% A trigger is a piece of code that is run at a particular chapter.verse or other event.
% a triggercheck  is code to check if a certain type of trigger e.g. piclist entry is to be run.
% Triggering is based on the actual verse number/range specified in \v, not \vp (printed verse)  
% The setting is set in c@rref (and for diglots, dc@rref). Triggers should be careful
% to not alter the values of c@rref or dc@rref, as these are used by other trigger code.
% The following conventions are applied:
% GEN14.5-preverse  is triggered before the verse number is output. It is possible that this is in vertical mode after a
% paragraph break.
% GEN14.5 is triggered after the verse number has been output. 
% GEN14.5=2 is triggered by the start of the second paragraph in verse 5. (assuming no other trigger point intervenes)
% ?? GENk.thisword-preverse is triggered before the key term \k this word k*  is output
% k.thisword is triggered after the key term \k this word\k* is output 

\newtoks\trigg@rchecks
\trigg@rchecks{}
\def\addtotrigg@rchecks#1{\x@\global\x@\trigg@rchecks\x@{\the\trigg@rchecks #1}}

\newif\ifMarkTriggerPoints
\x@\font\csname font<TP>\endcsname "Source Code Pro:extend=0.8,color=007f7f" at 7pt %Trigger Paragraph
\x@\font\csname font<TV>\endcsname "Source Code Pro:extend=0.8,color=7f007f" at 7pt %Trigger verse
\x@\font\csname font<AP>\endcsname "Source Code Pro:extend=0.8,color=7f7f00" at 7pt % AdjustPar

\def\@@@TP{TP}
\def\@@@TV{TV}
\def\@mark@trigerTP{1}
\def\@mark@trigerTV{0.5}
\def\@mark@trigerAP{0.1}
\def\trigg@rmark@selectT{\ifdiglot\dc@rref\else\c@rref\fi}%
\def\trigg@rmark@selectA{\adjc@rref,\the\curr@djpar}
\def\trigg@rmark@select#1#2\E{\csname trigg@rmark@select#1\endcsname}%
\def\trigg@rmark#1{%
  \ifhmode
    {%
      \count255=0
      \ifdim\lastkern<0pt \ifdim\lastkern>-10sp
        \count255=\lastkern\unkern 
        \count254=\lastkern\unkern
        \ifnum\count254=-\count255
        \else
          \ifnum\count254=0 \else       
            \kern\count254
          \fi
          \kern\count255
          \count255=0
        \fi
      \fi\fi
      \setbox0\hbox{\csname font<#1>\endcsname \trigg@rmark@select#1\E\hskip0.5em}%
      \dimen0=\x@\dimexpr\csname @mark@triger#1\endcsname\ht0 - 0.7\ht0 * \count255\relax
      %\trace{tm}{Trigger mark at \c@rref, \the\count255, lowering by \the\dimen0}%
      \llap{\smash{\lower\dimen0\box0}}%
      \advance\count255 by -1
      \kern -\count255 sp% 
      \kern \count255 sp% 
    }%
  \else
    %If anything is put in vmode, then empty paragraphs are no longer skipped. Better to do nothing until we work out how to add a 0pt box which won't cause a parskip. Must be possible, surely?
    \edef\t@st{#1}\ifx\t@st\@@@TV\else
      \setbox0\hbox{\csname font<#1>\endcsname \trigg@rmark@select#1\E\hskip1em}\vbox to 0pt{\smash{\x@\lower\csname @mark@triger#1\endcsname\ht0\box0}\penalty10000 }%
    \fi
  \fi
}

\let\@@lastc@rref\empty
\def\runtrigg@rscv{%after the verse number
  \ifversion{4}{%
    \global\p@rnum=\ifhmode 1\else 0\fi
  }{\global\p@rnum=1}%
  \let\@@lastc@rref\c@rref
  {\let\\=\clearn@tecount \the\n@tecl@sses}%
  \settrig@refcv
  \ifMarkTriggerPoints\trigg@rmark{TV}\fi
  \trace{T}{running (cv) triggers \c@rref (p@rnum reset to \the\p@rnum)}%
  \the\trigg@rchecks
}
\def\runtrigg@rsprecv{% before the verse number
  \global\p@rnum=0
  \let\@@lastc@rref\c@rref
  \settrig@refprecv
  \trace{T}{running (precv) triggers \c@rref}%
  \the\trigg@rchecks
}

\def\SetTriggerParagraphSeparator#1{%
  \xdef\TriggerP@rSep{#1}%
  \gdef\ch@kparref##1#1##2\E{\def\chkp@rrf{##2}\ifx\chkp@rrf\empty\temptrue\fi}}
\SetTriggerParagraphSeparator{=}


\def\runtrigg@rspar{%Paragraph trigger
  \ifdiglot\let\c@rftmp\dc@rref\else\let\c@rftmp\c@rref\fi
  \trace{T}{runtrigg@rspar[\m@rker ] \c@rftmp=\@@lastc@rref?}%
  \ifversion{7}{\ifx\c@rftmp\@@lastc@rref\else\global\p@rnum=0 \fi}{}%If we don't reset it here, then we might carry it over when we should reset
  \global\advance\p@rnum by 1 {\let\\=\clearn@tecount \the\n@tecl@sses}%
  \ifx\v@rse\empty\else
    \settrig@refcv
  \fi
  \let\oc@rref=\c@rref\let\odc@rref=\dc@rref % Preserve old references so that we can restore it later.
  \xdef\c@rref{\c@rref\TriggerP@rSep\the\p@rnum}%
  \ifdiglot
    \xdef\dc@rref{\odc@rref\TriggerP@rSep\the\p@rnum}%
  \fi
  \ifMarkTriggerPoints\trigg@rmark{TP}\fi
  \trace{T}{running triggers(par) \c@rref\space  \c@rrdstat \the\p@rnum, \the\curr@djpar}%
  \the\trigg@rchecks
  \global\let\c@rref=\oc@rref\global\let\dc@rref=\odc@rref
}

\def\opentriglist "#1" {%
  \openin\t@stread="\the\PtxFilePath#1"
  \ifeof\t@stread \def\n@xt{\trace{T}{Trigger list "#1" not found -- ignored}}%
  \else \closein\t@stread \def\n@xt{\prepusfm\relax\mapinput "\the\PtxFilePath#1"\relax\unprepusfm}\fi
  \n@xt
}
\def\multitriglists "#1" {%
  \temptrue\loopcount=1% use loopcount as file counter
  \m@ltitriglists{#1}%
}
\def\m@ltitriglists#1{%
  \edef\t@mptrigfilename{#1-\the\loopcount.triggers}%
  \advance\loopcount by 1
  \openin\t@stread="\t@mptrigfilename"
  \ifeof\t@stread \def\n@xt{\trace{T}{Trigger list "\t@mptrigfilename" not found -- not checking for more}}%
  \else \closein\t@stread \def\n@xt{\prepusfm\relax\mapinput "\t@mptrigfilename"\relax\unprepusfm\m@ltitriglists{#1}}\fi
  \n@xt
}
  

\def\runtrigg@rsother#1{%
    \trace{T}{runtrigg@rsother #1}%
    \runtrigg@rs{\mkp@cref{\id@@@}{#1}}%
    \ifdiglot
      \runtrigg@rs{\mkp@cref{\id@@@\c@rrdstat}{#1}}%
      \xdef\dc@rref{\id@@@\c@rrdstat#1}% 
    \fi
    \xdef\c@rref{\id@@@#1}% Paragraph number (for triggers) resets on keywords
    \ifversion{4}{%
	  \global\p@rnum=\ifhmode 0\@dvance@djfalse\ch@ckadjustments\else 0\fi
    }{\global\p@rnum=1}%
}

\def\runtrigg@rs#1{%Generic something trigger (milestone, or...)
  \trace{T}{runtrigg@rs #1}%
  \edef\c@rref{#1}%
  \let\oodc@rref\dc@rref
  \ifdiglot\edef\dc@rref{#1\g@tdstat}\fi%
  \trace{T}{running triggers \c@rref}%
    \ifMarkTriggerPoints\trigg@rmark{TV}\fi
  \the\trigg@rchecks
  \global\let\dc@rref\oodc@rref
}
\def\settrign@me#1{\edef\trign@me{trigger-#1}}

\def\addtrigger#1#2{%
  \settrign@me{#1}%
  \addtr@gger{#2}}% Not expected to be long 

\def\AddTrigger{\prepusfm\@AddTrigger}
\def\@AddTrigger#1 {% #1 is space-delimited, input may contain blank lines.
  \settrign@me{#1}%
  \catcode"FDEC=0\catcode`\\=12
  \@@AddTrigger}

\def\r@storbkslsh{\catcode`\\=0}
{
 \catcode"FDEC=0\catcode`\\=12
 ﷬long﷬gdef﷬@@AddTrigger#1 \EndTrigger{%
  ﷬r@storbkslsh
  ﷬unprepusfm
  ﷬addtr@gger{#1}}%
 ﷬r@storbkslsh
}

\long\def\addtr@gger#1{%Add trigger code trigger on reference trign@me (to do #1). 
   %Much of the complication is so the triggers concatenate roughly like a toklist
   \x@\let\x@\tr@gtmp\csname\trign@me\endcsname
   \ifx\tr@gtmp\relax
     \def\tr@gtmp{#1}%
   \else
     \x@\def\x@\tr@gtmp\x@{\tr@gtmp#1}%
   \fi
   \x@\global\x@\let\csname\trign@me\endcsname\tr@gtmp
}

\def\r@ntr@g#1\E{\p@sheof\scantokens{#1\noexpand}\p@peof}
%\def\r@ntr@g#1\E{
  %\toks0={#1}%
  %\immediate\openout0=tmptrigfile\relax
  %\immediate\write0{\the\toks0}
  %\immediate\closeout0
  %\input tmptrigfile\relax
%}

\newif\ifkeeptrigger
\def\c@llr@ntr@g{%Trigger contents is in \tmp, trigger name is in \trign@me
  \catcode"FDEF=2
  \ifx\thismil@stone\empty
    \keeptriggerfalse
  \else
    \ch@ckislocation{\thismil@stone}%
  \fi
  \bgroup
    \x@\x@\x@\r@ntr@g\x@\detokenize\x@{\tmp}\E
  \egroup
  \ifkeeptrigger\else% Triggers should normally only fire once. Kill it, unless the trigger has set keeptriggertrue
    \x@\global\x@\let\csname\trign@me\endcsname=\relax 
  \fi
}

\def\stdtrigger{%Run any triggers if they exist.
  \settrign@me{\c@rref}\ifcsname \trign@me\endcsname
    \x@\let\x@\tmp\csname\trign@me\endcsname
    \ifx\relax\tmp\else
      \trace{T}{Trigger(\trign@me ) present}%
      \c@llr@ntr@g
    \fi%
  \fi
  \ifdiglot
    \settrign@me{\dc@rref}\ifcsname \trign@me\endcsname
      \x@\let\x@\tmp\csname\trign@me\endcsname
      \ifx\relax\tmp\else
        \trace{T}{Trigger(\trign@me ) present}%
        \c@llr@ntr@g
      \fi%
    \fi
  \fi
}

\addtotrigg@rchecks{\stdtrigger}


\def\settrig@refcv{%
  \xdef\c@rref{\id@@@\ch@pter.\v@rse}%
  \trace{T}{settrig@refcv: \c@rref}%
  \ifdiglot
    \xdef\dc@rref{\id@@@\c@rrdstat\ch@pter.\v@rse}%
  \fi
}



\def\settrig@refprecv{%
  \edef\c@rref{\id@@@\ch@pter.\v@rse-preverse}%
  \ifdiglot
    \edef\dc@rref{\id@@@\c@rrdstat\ch@pter.\v@rse-preverse}%
  \fi
}
\addtopreversehooks{\runtrigg@rsprecv} % e.g. piclists
\addtoversehooks{\runtrigg@rscv} % e.g. adjustlist
\addtoeveryparhooks{\runtrigg@rspar} 
\def\c@rref{start}
\xdef\dc@rref{start\c@rrdstat}
