% --------------------------------------------------------------------------
% the EXSHEETS package
% 
%   Yet another package for the creation of exercise sheets
% 
% --------------------------------------------------------------------------
% Clemens Niederberger
% Web:    https://bitbucket.org/cgnieder/exsheets/
% E-Mail: contact@mychemistry.eu
% --------------------------------------------------------------------------
% Copyright 2011-2015 Clemens Niederberger
% 
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% 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 Clemens Niederberger.
% --------------------------------------------------------------------------
% If you have any ideas, questions, suggestions or bugs to report, please
% feel free to contact me.
% --------------------------------------------------------------------------
% HEADINGS FOR QUESTIONS AND SOLUTIONS
% the 6 base coffins:
\ProvidesFile{exsheets_headings.def}
  [\exsheets@date\space v\exsheets@version\space ExSheets headings object]

\coffin_new:N \l__exsheets_heading_main_coffin
\coffin_new:N \l__exsheets_heading_pre_coffin
\coffin_new:N \l__exsheets_heading_post_coffin
\coffin_new:N \l__exsheets_heading_title_coffin
\coffin_new:N \l__exsheets_heading_number_coffin
\coffin_new:N \l__exsheets_heading_points_coffin
\coffin_new:N \l__exsheets_heading_subtitle_coffin

% the object variables:
\bool_new:N   \l__exsheets_heading_runin_bool
\bool_new:N   \l__exsheets_heading_inline_bool
\bool_new:N   \l__exsheets_heading_indent_first_bool
\bool_new:N   \l__exsheets_heading_toc_reversed_bool

\dim_new:N    \l__exsheets_heading_above_dim
\dim_new:N    \l__exsheets_heading_below_dim
\fp_new:N     \l__exsheets_heading_scale_fp

\tl_new:N     \l__exsheets_heading_main_tl
\tl_new:N     \l__exsheets_heading_pre_code_tl
\tl_new:N     \l__exsheets_heading_post_code_tl

\tl_new:N     \l__exsheets_heading_title_format_tl
\tl_new:N     \l__exsheets_heading_title_pre_code_tl
\tl_set:Nn    \l__exsheets_heading_title_pre_code_tl { \use:n }
\tl_new:N     \l__exsheets_heading_title_post_code_tl

\tl_new:N     \l__exsheets_heading_number_format_tl
\tl_new:N     \l__exsheets_heading_number_pre_code_tl
\tl_set:Nn    \l__exsheets_heading_number_pre_code_tl { \use:n }
\tl_new:N     \l__exsheets_heading_number_post_code_tl

\tl_new:N     \l__exsheets_heading_subtitle_format_tl
\tl_new:N     \l__exsheets_heading_subtitle_pre_code_tl
\tl_set:Nn    \l__exsheets_heading_subtitle_pre_code_tl { \use:n }
\tl_new:N     \l__exsheets_heading_subtitle_post_code_tl

\tl_new:N     \l__exsheets_heading_points_format_tl
\tl_new:N     \l__exsheets_heading_points_pre_code_tl
\tl_set:Nn    \l__exsheets_heading_points_pre_code_tl { \use:n }
\tl_new:N     \l__exsheets_heading_points_post_code_tl
\tl_new:N     \l__exsheets_heading_points_post_hook_tl

\tl_new:N     \l__exsheets_heading_joined_coffins_tl
\tl_new:N     \l__exsheets_heading_attached_coffins_tl
\seq_new:N    \l__exsheets_heading_joined_coffins_seq
\seq_new:N    \l__exsheets_heading_attached_coffins_seq

% internal object functions:
% the following is shamelessly adapted from the `needspace' package by
% Peter Wilson and Herries Press
\cs_new:Npn \exsheets_needspace:n #1
  {
    \group_begin:
      \dim_set:Nn \l__exsheets_tmpa_dim { #1 }
      \skip_vertical:n { \c_zero_dim + \l__exsheets_tmpa_dim }
      \tex_penalty:D -100
      \skip_vertical:n { \c_zero_dim - \l__exsheets_tmpa_dim }
      \skip_vertical:N \l__exsheets_tmpa_dim
      \tex_penalty:D 9999
      \skip_vertical:n { - \l__exsheets_tmpa_dim }
      \skip_vertical:N \c_zero_dim
    \group_end:
  }

\AtBeginDocument
  {
    \cs_if_exist:NF \needspace
      { \cs_set_eq:NN \needspace \exsheets_needspace:n }
  }

\cs_generate_variant:Nn \seq_set_split:Nnn { NnV }

\cs_new:Npn \__exsheets_join:N #1
  {
    \seq_map_inline:Nn #1
      {
        \tl_if_blank:nF { ##1 }
          { \exp_after:wN \__exsheets_join_coffin_sequence:w ##1 }
      }
  }
\cs_new:Npn \__exsheets_join_coffin_sequence:w #1[#2,#3] #4[#5,#6] (#7,#8)
  { \__exsheets_join_coffins:nnnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8} }

\cs_new:Npn \__exsheets_join_coffins:nnnnnnnn #1#2#3#4#5#6#7#8
  {
    \coffin_join:cnncnnnn
      { l__exsheets_heading_#1_coffin } { #2 } { #3 }
      { l__exsheets_heading_#4_coffin } { #5 } { #6 }
      { #7 } { #8 }
  }
\cs_new:Npn \__exsheets_attach:N #1
  {
    \seq_map_inline:Nn #1
      {
        \tl_if_blank:nF { ##1 }
          { \exp_after:wN \__exsheets_attach_coffin_sequence:w ##1 }
      }
  }
\cs_new:Npn \__exsheets_attach_coffin_sequence:w #1[#2,#3]#4[#5,#6](#7,#8)
  { \__exsheets_attach_coffins:nnnnnnnn {#1}{#2}{#3}{#4}{#5}{#6}{#7}{#8} }

\cs_new:Npn \__exsheets_attach_coffins:nnnnnnnn #1#2#3#4#5#6#7#8
  {
    \coffin_attach:cnncnnnn
      { l__exsheets_heading_#1_coffin } { #2 } { #3 }
      { l__exsheets_heading_#4_coffin } { #5 } { #6 }
      { #7 } { #8 }
  }

% the `exsheets-heading' object:
%   #1 = title,
%   #2 = number,
%   #3 = points
%   #4 = bonus
%   #5 = id
\DeclareObjectType { exsheets-heading } { 5 }

% the `default' template interface:
\DeclareTemplateInterface { exsheets-heading } { default } { 5 }
  {
    inline             : boolean   = false ,
    runin              : boolean   = false ,
    indent-first       : boolean   = false ,
    toc-reversed       : boolean   = false ,
    vscale             : real      = 1     ,
    above              : length    = 2pt   ,
    below              : length    = 2pt   ,
    main               : tokenlist =       ,
    pre-code           : tokenlist =       ,
    post-code          : tokenlist =       ,
    title-format       : tokenlist =       ,
    title-pre-code     : tokenlist =       ,
    title-post-code    : tokenlist =       ,
    number-format      : tokenlist =       ,
    number-pre-code    : tokenlist =       ,
    number-post-code   : tokenlist =       ,
    subtitle-format    : tokenlist =       ,
    subtitle-pre-code  : tokenlist =       ,
    subtitle-post-code : tokenlist =       ,
    points-format      : tokenlist =       ,
    points-pre-code    : tokenlist =       ,
    points-post-code   : tokenlist =       ,
    join               : tokenlist =       ,
    attach             : tokenlist =
  }

% the `default' template code:
\DeclareTemplateCode { exsheets-heading } { default } { 5 }
  {
    inline             = \l__exsheets_heading_inline_bool         ,
    runin              = \l__exsheets_heading_runin_bool          ,
    indent-first       = \l__exsheets_heading_indent_first_bool   ,
    toc-reversed       = \l__exsheets_heading_toc_reversed_bool   ,
    vscale             = \l__exsheets_heading_scale_fp            ,
    above              = \l__exsheets_heading_above_dim           ,
    below              = \l__exsheets_heading_below_dim           ,
    main               = \l__exsheets_heading_main_tl             ,
    pre-code           = \l__exsheets_heading_pre_code_tl         ,
    post-code          = \l__exsheets_heading_post_code_tl        ,
    title-format       = \l__exsheets_heading_title_format_tl     ,
    title-pre-code     = \l__exsheets_heading_title_pre_code_tl   ,
    title-post-code    = \l__exsheets_heading_title_post_code_tl  ,
    number-format      = \l__exsheets_heading_number_format_tl    ,
    number-pre-code    = \l__exsheets_heading_number_pre_code_tl  ,
    number-post-code   = \l__exsheets_heading_number_post_code_tl ,
    subtitle-format    = \l__exsheets_heading_title_format_tl     ,
    subtitle-pre-code  = \l__exsheets_heading_subtitle_pre_code_tl    ,
    subtitle-post-code = \l__exsheets_heading_subtitle_post_code_tl   ,
    points-format      = \l__exsheets_heading_points_format_tl    ,
    points-pre-code    = \l__exsheets_heading_points_pre_code_tl  ,
    points-post-code   = \l__exsheets_heading_points_post_code_tl ,
    join               = \l__exsheets_heading_joined_coffins_tl   ,
    attach             = \l__exsheets_heading_attached_coffins_tl
  }
  {
    \AssignTemplateKeys
    \bool_if:NT \l__exsheets_heading_inline_bool
      { \cs_set_eq:NN \exsheets_par: \scan_stop: }
    \seq_set_split:NnV \l__exsheets_heading_joined_coffins_seq { ; }
      \l__exsheets_heading_joined_coffins_tl
    \seq_set_split:NnV \l__exsheets_heading_attached_coffins_seq { ; }
      \l__exsheets_heading_attached_coffins_tl
    \bool_if:nTF
      { \l__exsheets_heading_runin_bool || \l__exsheets_heading_inline_bool }
      {
        \hcoffin_set:Nn \l__exsheets_heading_main_coffin
          {
            \tl_if_blank:VTF \l__exsheets_heading_main_tl
              { \tl_use:N \l__exsheets_heading_title_format_tl \strut }
              { \tl_use:N \l__exsheets_heading_main_tl }
          }
      }
      {
        \hcoffin_set:Nn \l__exsheets_heading_main_coffin
          {
            \parbox { \linewidth }
              {
                \tl_if_blank:VTF \l__exsheets_heading_main_tl
                  { \tl_use:N \l__exsheets_heading_title_format_tl \strut }
                  { \tl_use:N \l__exsheets_heading_main_tl }
              }
          }
      }
    \hcoffin_set:Nn \l__exsheets_heading_pre_coffin
      { \tl_use:N \l__exsheets_heading_pre_code_tl }
    \hcoffin_set:Nn \l__exsheets_heading_post_coffin
      { \tl_use:N \l__exsheets_heading_post_code_tl }
    \coffin_join:NnnNnnnn
      \l__exsheets_heading_main_coffin { l } { t }
      \l__exsheets_heading_pre_coffin  { l } { b } { 0pt } { 0pt }
    \coffin_join:NnnNnnnn
      \l__exsheets_heading_main_coffin { l } { b }
      \l__exsheets_heading_post_coffin { l } { t } { 0pt } { 0pt }
    \hcoffin_set:Nn \l__exsheets_heading_title_coffin
      {
        \tl_use:N \l__exsheets_heading_title_format_tl
        \strut
        \tl_use:N \l__exsheets_heading_title_pre_code_tl
          { \tl_use:N \l_exsheets_heading_title_user_format_tl {#1} }
        \tl_use:N \l__exsheets_heading_title_post_code_tl
      }
    \hcoffin_set:Nn \l__exsheets_heading_number_coffin
      {
        \tl_if_blank:VTF \l__exsheets_heading_number_format_tl
          { \tl_use:N \l__exsheets_heading_title_format_tl }
          { \tl_use:N \l__exsheets_heading_number_format_tl }
        \strut
        \tl_use:N \l__exsheets_heading_number_pre_code_tl
          { \tl_use:N \l_exsheets_heading_title_user_format_tl {#2} }
        \tl_use:N \l__exsheets_heading_number_post_code_tl
      }
    \hcoffin_set:Nn \l__exsheets_heading_subtitle_coffin
      {
        \exsheets_if_question_subtitle:T
          {
            \tl_if_blank:VTF \l__exsheets_heading_subtitle_format_tl
              { \tl_use:N \l__exsheets_heading_title_format_tl }
              { \tl_use:N \l__exsheets_heading_subtitle_format_tl }
            \strut
            \tl_use:N \l__exsheets_heading_subtitle_pre_code_tl
            {
              \group_begin:
                \tl_use:N \l_exsheets_heading_subtitle_user_format_tl
                { \exsheets_get_question_property:nn { subtitle } { #5 } }
              \group_end:
            }
            \tl_use:N \l__exsheets_heading_subtitle_post_code_tl
          }
      }
    \hcoffin_set:Nn \l__exsheets_heading_points_coffin
      {
        \bool_if:NTF \l__exsheets_parse_points_bool
          {
            \bool_if:nF
              { \fp_compare_p:n { #3 = 0 } && \fp_compare_p:n { #4 = 0 } }
              {
                \tl_use:N \l__exsheets_heading_points_format_tl
                \group_begin:
                  \tl_use:N \l__exsheets_heading_title_format_tl \strut
                \group_end:
                \tl_use:N \l__exsheets_heading_points_pre_code_tl
                  {
                    \tl_use:N \tl_use:N \l__exsheets_points_format_tl
                      {
                        \fp_compare:nF { #3 = 0 }
                          {
                            \bool_if:nTF
                              {
                                \l__exsheets_points_separate_bonus_bool ||
                                \fp_compare_p:n { #4 = 0 }
                              }
                              {
                                \exsheets_parse_points:n { #3 }
                                \exsheets_points_name:n { #3 }
                              }
                              { \exsheets_parse_points:n { #3 } }
                          }
                        \fp_compare:nF { #4 = 0 }
                          {
                            \tl_use:N \l__exsheets_points_pre_bonus_marker_tl
                            \bool_if:nTF
                              {
                                \l__exsheets_points_separate_bonus_bool ||
                                \fp_compare_p:n { #3 = 0 }
                              }
                              {
                                \exsheets_print_bonus:n { #4 }
                                \tl_use:N \l__exsheets_points_post_bonus_marker_tl
                              }
                              {
                                \exsheets_parse_bonus:n { #4 }
                                \tl_use:N \l__exsheets_points_post_bonus_marker_tl
                                \exsheets_points_name:n { #3 + #4 }
                              }
                          }
                      }
                  }
                \tl_use:N \l__exsheets_heading_points_post_code_tl
              }
          }
          {% points/parse = false
            \tl_use:N \l__exsheets_heading_points_format_tl
            \group_begin:
              \tl_use:N \l__exsheets_heading_title_format_tl \strut
            \group_end:
            % \exp_args:Nx \tl_show:n { #3 }
            \tl_if_eq:xnF { #3 } { 0 }
              {
                \tl_use:N \l__exsheets_heading_points_pre_code_tl
                  { \exsheets_print_points:n { #3 } }
                \tl_use:N \l__exsheets_heading_points_post_code_tl
              }
          }
      }
    % this allows users to provide their own point system while also using
    % exsheets' positioning mechanism:
    \tl_use:N \l__exsheets_heading_points_post_hook_tl
    \bool_if:nT
      { !\l__exsheets_heading_runin_bool && !\l__exsheets_heading_inline_bool }
      {
        \coffin_resize:Nnn \l__exsheets_heading_main_coffin { \linewidth }
          {
            \fp_to_decimal:N \l__exsheets_heading_scale_fp
            \coffin_ht:N \l__exsheets_heading_main_coffin +
            \l__exsheets_heading_below_dim
          }
      }
    \__exsheets_join:N \l__exsheets_heading_joined_coffins_seq
    \__exsheets_attach:N \l__exsheets_heading_attached_coffins_seq
    \bool_if:NTF \l__exsheets_heading_inline_bool
      { \exsheets_questions_debug: }
      {
        \skip_vertical:N \l__exsheets_heading_above_dim
        \exsheets_needspace:n
          {
            \coffin_ht:N \l__exsheets_heading_main_coffin +
            \coffin_dp:N \l__exsheets_heading_main_coffin +
            \l__exsheets_heading_below_dim +
            \baselineskip
          }
        \exsheets_questions_debug:
        \noindent
      }
    \skip_set:Nn \parfillskip { 0pt plus 1fil }
    \bool_if:nT
      { \l__exsheets_questions_totoc_bool && \l__exsheets_inside_question_bool }
      {
        \use:c {phantomsection}
        \addcontentsline { toc } { \l__exsheets_questions_toclevel_tl }
          {
            \bool_if:NTF \l__exsheets_heading_toc_reversed_bool
              { #2 \ #1 }
              { #1 \ #2 }
          }
      }
    \bool_if:nT
      { \l__exsheets_solutions_totoc_bool && !\l__exsheets_inside_question_bool }
      {
        \use:c {phantomsection}
        \addcontentsline { toc } { \l__exsheets_solutions_toclevel_tl }
          {
            \bool_if:NTF \l__exsheets_heading_toc_reversed_bool
              { #2 \ #1 }
              { #1 \ #2 }
          }
      }
    \coffin_typeset:Nnnnn \l__exsheets_heading_main_coffin
      { H } { l } { 0pt }{ 0pt }
    \bool_if:nT
      { !\l__exsheets_heading_runin_bool && !\l__exsheets_heading_inline_bool }
      {
        \skip_vertical:N \l__exsheets_heading_below_dim
        \dim_compare:nF { \parskip = 0pt }
          { \skip_vertical:n { -\parskip } }
        \bool_if:NTF \l__exsheets_heading_indent_first_bool
          { \@afterindenttrue\@afterheading }
          { \@afterindentfalse\@afterheading }
      }
  }

% the two basic instances:
% BLOCK:
\DeclareInstance { exsheets-heading } { block } { default }
  {
    join             = { title[r,B] number[l,B] (1ex,0pt) } ,
    attach           =
      {
        main[l,vc] title[l,vc] (0pt,0pt) ;
        main[r,vc] points[l,vc] (\marginparsep,0pt)
      }
  }

% RUNIN:
\DeclareInstance { exsheets-heading } { runin } { default }
  {
    runin            = true ,
    number-post-code = \c_space_tl ,
    attach           =
      { main[l,vc] points[l,vc] (\linewidth + \marginparsep,0pt) } ,
    join             =
      {
        main[r,vc] title[r,vc] (0pt,0pt) ;
        main[r,vc] number[l,vc] (1ex,0pt)
      }
  }

\tex_endinput:D
