% --------------------------------------------------------------------------
% 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-2013 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.
% --------------------------------------------------------------------------
% The exsheets package consists of the files
%  - exsheets.sty, exsheets_headings.def, exsheets_headings.cfg,
%    exsheets_tasks.def, exsheets_tasks.cfg, exsheets_configurations.cfg,
%  - exsheets_en.tex, exsheets_en.pdf,
%  - README
% --------------------------------------------------------------------------
% 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_meta_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_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_new:N     \l__exsheets_heading_number_post_code_tl

\tl_new:N     \l__exsheets_heading_meta_pre_code_tl
\tl_new:N     \l__exsheets_heading_meta_post_code_tl

\tl_new:N     \l__exsheets_heading_points_format_tl
\tl_new:N     \l__exsheets_heading_points_pre_code_tl
\tl_new:N     \l__exsheets_heading_points_post_code_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
\DeclareObjectType { exsheets-heading } { 4 }

% the `default' template interface:
\DeclareTemplateInterface { exsheets-heading } { default } { 4 }
  {
    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 =       ,
    meta-pre-code    : tokenlist =       ,
    meta-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 } { 4 }
  {
    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 ,
    meta-pre-code    = \l__exsheets_heading_meta_pre_code_tl    ,
    meta-post-code   = \l__exsheets_heading_meta_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: }
    \bool_if:nT
      { \l__exsheets_questions_totoc_bool && \l__exsheets_inside_question_bool }
      {
        \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 }
      {
        \phantomsection
        \addcontentsline { toc } { \l__exsheets_solutions_toclevel_tl }
          {
            \bool_if:NTF \l__exsheets_heading_toc_reversed_bool
              { #2 \ #1 }
              { #1 \ #2 }
          }
      }
    \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_meta_coffin
      {
        \prop_get:NoNT \g__exsheets_questions_meta_prop
          { \g__exsheets_questions_current_id_tl }
          \l__exsheets_questions_meta_tl
          {
            \tl_use:N \l__exsheets_heading_meta_pre_code_tl
            \tl_use:N \l__exsheets_questions_meta_tl
            \tl_use:N \l__exsheets_heading_meta_post_code_tl
          }
      }
    \hcoffin_set:Nn \l__exsheets_heading_points_coffin
      {
        \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
              {
                \fp_compare:nF { #3 = 0 }
                  {
                    \bool_if:nTF
                      {
                        \l__exsheets_points_separate_bonus_bool ||
                        \fp_compare_p:n { #4 = 0 }
                      }
                      { \exsheets_print_points:n { #3 } }
                      { \exsheets_parse_points:n { #3 } }
                  }
                \bool_if:nT { !\fp_compare_p:n { #3 = 0 } && !\fp_compare_p:n { #4 = 0 } }
                  { ~ }
                \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
          }
      }
    \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 }
    \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
          { \@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