% lollipop-lists.tex copyright 1992/3 Victor Eijkhout
%               copyright 2014--2016 Vafa Khalighi
%
%
%    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/>.
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%% L I S T S 


\@GenericConstruct{List}

\newif\if@initem \@initemyes \newif\if@alitem
\newbox\@labelbox 

\def\item{\Emessage{Item command outside list}}

% Breakpoints around a list
%
% first redefine generic defaults:
% try not to break before, maybe not after,
%
\add@List@default{\def\@beforepenalty{\penalty1000 }}
\add@List@default{\def\@afterpenalty{\penalty200 }}

% between items is okay
% 
\add@List@default{\def\@betweenpenalty{\penalty-50 }}
\@ListOption{breakbetween}{
    \switch {\if\EqualString{#1}}
    {no}  {\def\@betweenpenalty{\penalty\@M}}
    {yes} {\def\@betweenpenalty{\CSname{\h@or@v fil}\penalty-\@M}}
    {0}   {\def\@betweenpenalty{}}
    {default} {\edef\cs@e{\def\nxp\@betweenpenalty{\penalty\@w@w{#1}\relax}}
               \cs@e}
    \endswitch
    }

\newtoks\indent@depth
\add@List@default{\indent@depth={}}

\noeol
\def\@DefineList{
    \@DefineStopCommand{\nxp\xx@label \the\item@e@coms\@gen@close}
    \csarg\edef{\@name}{\@gen@open
         \ifitem@list \nxp\step@counter{itemlevel}\fi
         \ifenum@list \nxp\step@counter{enumlevel}
            \nxp\represent@counter{item}
                {\nxp\enum@repr{\counter@@name{enumlevel}}}\fi
         \ifleft@embedded@construct \previousindent\z@
             \else \nxp\PushIndentLevel 
                   \ifauto@indent \else \levelindent\the\indent@depth \fi
                   \parindent\levelindent
             \fi
         \nxp\@alitemno
         \nxp\start@counter{item}%
         \the\item@b@coms
         \def\nxp\item@label{
             \nxp\ifdim\wd\@labelbox>\tempdima
                 \ifitem@tab \advance\tempdima20pt\relax
                             {\nxp\item@label}
                 \else \iflabel@flow@right 
                             \ifleft@embedded@construct
                             \else\hskip-\previousindent\fi
                             \box\@labelbox
                       \else \nxp\llap{\box\@labelbox}\fi\fi
             \nxp\else \llap{\hbox to \tempdima
                {\ifleft@item\else\hfil\fi
                 \box\@labelbox \ifleft@item\hfil\fi}}
             \nxp\fi}%
         \def\nxp\num@item
            {\setbox\@labelbox=\hbox{\the\item@coms}
             \tempdima\previousindent
             \nxp\item@label %\nxp\Indent:no
             \the\item@a@coms \nxp\xx@label}
         \def\nxp\item
            {\ifleft@embedded@construct
             \else \nxp\if@alitem\@par%\CSname{@itembreek}%
                   \nxp\hold@parskip \nxp\fi \fi
             \nxp\if\nxp\TestCounter:item >0 \@betweenpenalty \nxp\fi
             \CSname{@\h@or@v white}{\white@between}
             \nxp\@initemno \nxp\@alitemyes \nxp\noindent
             \nxp\step@counter{item}\relax 
             \iflabel@defined\else\nxp\define@reference{item}\fi
             \CSname{\@name @item}}
         }
    \csarg\edef{\@name @item}{
         \iflist@has@description \nxp\desc@item
         \else \nxp\num@item\fi}
    \@Labelize{\@name @item}
    }
\normaleol

% Inside a list Foo \item is defined as
%
% \item = all sorts of skips and switches
%         step item counter, define reference
%         \Foo@item
%
% \Foo@item[opt.lab.] = \desc@item or \num@item
%
% \desc@item =
% { \aftergroup\num@item \@description}
%
% \num@item = \item@label \item@a@coms \xx@label
%

% Item
% start with start/left/right
% indicating alignment, start = left
%
\newif\ifleft@item \newif\ifitem@tab
\add@List@default{\left@itemyes \item@tabno}
\newtoks\item@coms % content of the item label
\newtoks\item@b@coms % start of the list?
\newtoks\item@a@coms % immediately after the item
\newtoks\item@e@coms % after the whole list
\add@List@default{\item@coms{}\item@b@coms{}\item@a@coms{}
    \item@e@coms{}\def\@current@options@list{item@b@coms}}
\@ListOption{item}{
    \switch {\if\EqualString{#1}}
    {stop} {\@add@toks{\egroup}\e@group
         \def\@current@options@list{item@a@coms}}
    {tabstop} {\item@tabyes
             \@add@toks{\egroup}\e@group
             \def\@current@options@list{item@a@coms}}
    {left} {\global\left@itemyes
             \b@group\def\@current@options@list{item@coms}%
             \@add@toks{\bgroup}}
    {start}{\global\left@itemyes
             \b@group\def\@current@options@list{item@coms}%
             \@add@toks{\bgroup}}
    {right}{\global\left@itemno
             \b@group\def\@current@options@list{item@coms}%
             \@add@toks{\bgroup}}
    {default} {\Emessage{Unknown option #1 for List, item}}
    \endswitch}

% Label overflow
%
\newif\iflabel@flow@right
\add@List@default{\label@flow@rightyes}
\@ListOption{labeloverflow}{
    \if\EqualString{#1}{left}\label@flow@rightno
    \else\label@flow@rightyes\fi}

% Description
% the line after \item gets picked up,
% and becomes available as `description'
%
\newif\iflist@has@description
\add@List@default{\list@has@descriptionno}
\@ListOption{description}{
    \global\list@has@descriptionyes \@add@toks{\description@text}}
{\noeol
 \othercr
\gdef\@description{\bgroup\othercr \@@description}
\gdef\@@description#1^^M
    {\gdef\description@text{#1}%
    \egroup % balance the \bgroup in \@description
            % which kept the \othercr local
    \egroup % balance the \bgroup in \desc@item
            % which enabled the \aftergroup\num@item
    }
}
\def\desc@item{\bgroup    
    \aftergroup\num@item
    \@description}

% White between items
%
\add@List@default{\def\white@between{0pt}}
\@ListOption{whitebetween}{\def\white@between{#1}}
%    \edef\white@between{\@w@w{#1}}}

% Indentation
% is automatic (default) and level dependent
% or explicit
%
\newif\ifauto@indent
\add@List@default{\auto@indentyes}
\@ListOption{indentation}{
    \if\EqualString{#1}{automatic}\auto@indentyes
    \else\auto@indentno
         \edef\cs@e{\nxp\indent@depth={\@w@w{#1}}}\cs@e
    \fi}

% Tail of the list:
% everything after the keyword 'text' is tail
%
\@ListOption{text}{\at@breakpointyes
    \def\@current@options@list{item@e@coms}}

%%%%%%%%%%%%%%%% List Nesting Counters
%

% Item sign
% gives the default, level dependent marker
%
\new@@counter{itemlevel} \set@counter{itemlevel}0
\newif\ifitem@list
\add@List@default{\item@listno}
\@ListOption{itemsign}{
    \global\item@listyes
    \edef\cs@e{\nxp\@add@toks
                {\nxp\ifcustom@label\nxp\the\current@label
                 \nxp\else\nxp\item@sign\counter@@name{itemlevel}%
                 \nxp\fi}}
    \cs@e}
\def\@item@sign#1{itemsign\romannumeral#1}
\def\item@sign#1{\if\UndefinedCS{\@item@sign{#1}}\@@item@sign{#1}%
    \else \csname \@item@sign{#1}\endcsname \fi}
\def\@@item@sign#1{\ifcase#1\relax\or
    $\bullet$\or $\circ$ \or --\else $\cdot$\fi}
\def\SetItemSign:#1=#2{\csarg\edef{\@item@sign{#1}}%
   {\cswitch \ifx#2 in:
    b $\bullet$;
    c $\circ$;
    d $\diamond$;
    m ---;
    n --;
    . $\cdot$;
    default $\cdot$;
    \endswitch}}

% Item Counter 
% 
% Allocate a bare bones counter
\new@@counter{item}\represent@counter{item}1
\newtoks\item@RL \item@RL{}

% Keep track of enumerate list level
%
\new@@counter{enumlevel} \set@counter{enumlevel}0
\newif\ifenum@list
\add@List@default{\enum@listno}
\@ListOption{itemCounter}{
    \global\enum@listyes
    \@add@toks{\pad@clear\ifcustom@label\the\current@label
               \else\itemCounter\fi}
    }
\def\@enum@repr#1{enumrepr\romannumeral#1}
\def\enum@repr#1{\if\UndefinedCS{\@enum@repr{#1}}\@@enum@repr{#1}%
    \else \csname \@enum@repr{#1}\endcsname \fi}
\def\@@enum@repr#1{\ifcase#1\relax\or
    1\or A\or I\or a\or i\else 1\fi}
\def\SetItemCounterRepresentation:#1=#2{\csarg\edef{\@enum@repr{#1}}{#2}}

%
\def\@itembreek{\if@initem\par\fi}

% Clear items for Widest.
% this is rather susceptible for improvement.
%
\def\ClearFor:#1 
   {\def\widest@pad{#1}}
\def\widest@pad{\m@ne}
\def\pad@clear{\ifnum\widest@pad=\m@ne\else
    \tempcounta\widest@pad
    \advance\tempcounta-\LogTen{\cs@counter@name{item}}\relax
    \hphantom{\ifcase\tempcounta \or 9\or 99 \or 999 \or 9999 \else 99999\fi
              }%
    \fi}

%%%%%%%%%%%%%%%% Stripped Lists
%
% for use in external files
%

\@GenericConstruct{ExternalItem}%stripped list

\add@ExternalItem@default{\extra@args\tw@}

\noeol
\def\@DefineExternalItem{
    \@DefineStopCommand{\@gen@close}
    \ifx\pre@fix\@empty \Wmessage{No file for external item: \@name}\fi
    \edef\cs@e{\nxp\append@to@list
         {\pre@fix @local@defs}
         {\nxp\if\nxp\UndefinedCS{\@command}
                 \nxp\Wmessage{Item `\@name' not defined for `\pre@fix'}
          \nxp\else
          \let\CSname{\@name}\CSname{\@command}
          \nxp\fi}}
    \cs@e
    \csarg\edef{\@command}##1##2{
         \def\CSname{\@name Label}{##1}
         \@gen@open\def\nxp\Page{##2}
         \nxp\PushIndentLevel \let\nxp\nl\relax
         \the\item@b@coms
         \def\nxp\item{\ifleft@embedded@construct\else\noindent\fi
             \setbox\@labelbox=\hbox{\the\item@coms}
             \nxp\ifdim\wd\@labelbox>\previousindent
                 \iflabel@flow@right \hskip-\previousindent\box\@labelbox
                 \else \nxp\llap{\box\@labelbox}\fi
             \nxp\else \llap{\hbox to \previousindent
                {\ifleft@item\else\hfil\fi
                 \box\@labelbox \ifleft@item\hfil\fi}}
             \nxp\fi}%
         \ifexternal@item@has@item\nxp\item\the\item@a@coms\fi
         \ifright@embedded@construct\else\@par\fi
         \iflong@external\else\nxp\>\fi
         }
    }
\normaleol

\add@ExternalItem@default{\@whitebefore\z@toks}
\add@ExternalItem@default{\@whiteafter\z@toks}
\add@ExternalItem@default{\let\Page\@space 
    \csarg\let{\@name Label}\@space}

% Specify for what external file this is meant
%
\@ExternalItemOption{file}{
  \if\UndefinedCS{\file@ext@name{#1}}
    \Emessage{File <#1> has not been defined yet}\fi
  \def\pre@fix{#1}}

\newif\iflong@external
\add@ExternalItem@default{\long@externalno}
\@ExternalItemOption{long}{
    \csname long@external#1\endcsname}

% Commands before and after
% option 'title' is dummy
%
%\@ExternalItemOption{title}{}
% dangerous: better rely on automatic titelization

% Item
% start with start/left/right
% indicating alignment, start = left
%
\add@ExternalItem@default{\left@itemyes}
\add@ExternalItem@default{\item@coms{}\item@b@coms{}\item@e@coms{}
    \item@a@coms{}\def\@current@options@list{item@b@coms}}
\newif\ifexternal@item@has@item
\adds@ExternalItem@default{\external@item@has@itemno}
\def\ExternalItem@item{\external@item@has@itemyes
  \List@item}

% Label overflow
%
\add@ExternalItem@default{\label@flow@rightyes}
\let\ExternalItem@labeloverflow\List@labeloverflow

\endinput

% 92/11/26 itemsign / itemCounter changed to handle custom@label
% 93/01/03 item call in ExternalItem made conditional