% \iffalse meta-comment
%
% This is file `xepersian-hm.dtx'
% 
% Copyright (C) 2020 Hossein Movahhedian
% 
% It may be distributed and/or modified under the LaTeX Project Public License,
% version 1.3c or higher (your choice). The latest version of
% this license is at: http://www.latex-project.org/lppl.txt 
%
%<*internal>
\iffalse
%</internal>
%<*README-txt>
The XEPERSIAN-HM package
------------------------

Kashida feature in 'xepersian' has problems with some fonts such as 'HM Series'
available at 'https://dma8hm1334.bitbucket.io' and 'X Series 2' available at
'http://wiki.irmug.com/index.php/X_Series_2'. The 'xepersian-hm' package fixes
these problems.

The files 'kashida-glyph-example.tex' and 'kashida-hrule-example.tex' in
the directory 'texmf-dist/doc/xelatex/xepersian-hm/' can be used as simple
examples of the usage of the package.

Please use the Bitbucket issue tracker:
'https://bitbucket.org/dma8hm1334/xepersian-hm/issues' to report a bug, request
a feature or if you have a comment.

I will do my best to fix all the bugs you report, but, unfortunately, time is a
big hurdle to overcome; so, my apologies in advance for those which I cannot
make time to fix.
%</README-txt>
%<*internal>
\fi
%</internal>
%
%    \begin{macrocode}
%<*driver>
\documentclass[full]{ltxdoc}
\usepackage{longtable}
\usepackage{hypdoc}
\addtolength{\hoffset}{-10mm}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{\jobname.dtx}
\end{document}
%</driver>
%    \end{macrocode}
% \fi
%
% \immediate\write18{xelatex xepersian-hm-doc.ltx}
%
% \title{^^A
%   The \textsf{xepersian-hm} package\\Fixing kashida in xepersian\\Source code documentation^^A
% }
% 
% \author{^^A
%  Hossein Movahhedian\thanks
%    {^^A
%      E-mail:
%        \href{mailto:dma8hm1334@gmail.com}
%          {\textsf{dma8hm1334@gmail.com}}
%    }^^A
% }
% 
% \date{Released \quad 2020-08-05 \quad v1.0d}
% 
% \maketitle
% 
% \section{\texttt{xepersian-hm} Implementation}
%
% \subsection{File: \texttt{xepersian-hm.sty}}
%
%    \begin{macrocode}
%<*xepersian-hm-sty>
\NeedsTeXFormat{LaTeX2e}
\RequirePackage{expl3}[2020-03-06]
\@ifpackagelater{expl3}{2020-03-06}
  {}
  {%
    \PackageError{xepersian-hm}{Support package l3kernel too old}
      {%
        Please install an up to date version of l3kernel\MessageBreak
        using your TeX package manager or from CTAN.\MessageBreak
        \MessageBreak
        Loading xtemplate will abort!%
      }%
    \endinput
  }
\RequirePackage{l3keys2e}
\RequirePackage{graphicx}[2019-11-30]
\RequirePackage{zref-savepos}[2020-03-03]
\RequirePackage{xepersian}
\ExplSyntaxOn
\ProvidesExplPackage {xepersian-hm} {2020-08-05} {1.0d} { Fixes~issues~in~xepersian~package }

\box_new:N \l_xephm_ksh_box

\int_const:Nn \c_xephm_ksh_int {"0640} % kashida
\int_const:Nn \c_xephm_lrm_int {"200E} % left-right-mark
\int_const:Nn \c_xephm_zwj_int {"200D} % zero-width joiner

\int_const:Nn \c_xephm_two_int {2} % 2
\int_const:Nn \c_xephm_four_int {4} % 4

\tl_const:Nn \c_xephm_skip_a_tl { 0 em plus 0.5 em }
\tl_const:Nn \c_xephm_skip_b_tl { 0.14 em plus 5.5 em }

\int_new:N \l_xephm_counter_int

\int_new:N \l_xephm_kashida_slot_int

\int_new:N \l_xephm_line_break_penalty_int

\int_new:N \l_xephm_min_penalty_int
\int_new:N \l_xephm_low_penalty_int
\int_new:N \l_xephm_med_penalty_int
\int_new:N \l_xephm_high_penalty_int
\int_new:N \l_xephm_max_penalty_int

\tl_new:N \l_xephm_line_break_tl

\tl_new:N \l_xephm_main_font_full_tl
\tl_new:N \l_xephm_main_font_name_tl

\tl_new:N \l_xephm_font_full_tl
\tl_new:N \l_xephm_font_name_tl

\tl_new:N \l_xephm_skip_default_tl

\tl_new:N \l_xephm_active_ligs_tl

\tl_new:N \l_xephm_gap_filler_tl

\dim_new:N \l_xephm_diff_pos_dim

\bool_set_false:N \l_xephm_kashida_hm_fix_bool
\bool_set_false:N \l_xephm_ligature_bool
\bool_set_false:N \l_xephm_linebreakpenalty_bool

\int_set:Nn \l_xephm_min_penalty_int { 0 }
\int_set:Nn \l_xephm_low_penalty_int { 8 }
\int_set:Nn \l_xephm_med_penalty_int { 15 }
\int_set:Nn \l_xephm_high_penalty_int { 25 }
\int_set:Nn \l_xephm_max_penalty_int { 10000 }

\tl_set:Nn \l_xephm_stretch_glyph_tl { glyph }
\tl_set:Nn \l_xephm_stretch_leaders_glyph_tl { leaders+glyph }
\tl_set:Nn \l_xephm_stretch_leaders_hrule_tl { leaders+hrule }
\tl_set:Nn \l_xephm_stretch_off_tl { Off }
\tl_set:Nn \l_xephm_stretch_on_tl { On }

\tl_set:Nn \l_xephm_fnt_kayhan_tl       { kayhan }
\tl_set:Nn \l_xephm_fnt_kayhannavaar_tl { kayhannavaar }
\tl_set:Nn \l_xephm_fnt_kayhanpook_tl   { kayhanpook }
\tl_set:Nn \l_xephm_fnt_kayhansayeh_tl  { kayhansayeh }
\tl_set:Nn \l_xephm_fnt_khoramshahr_tl  { khoramshahr }
\tl_set:Nn \l_xephm_fnt_khorramshahr_tl { khorramshahr }
\tl_set:Nn \l_xephm_fnt_niloofar_tl     { niloofar }
\tl_set:Nn \l_xephm_fnt_paatch_tl       { paatch }
\tl_set:Nn \l_xephm_fnt_riyaz_tl        { riyaz }
\tl_set:Nn \l_xephm_fnt_roya_tl         { roya }
\tl_set:Nn \l_xephm_fnt_shafigh_tl      { shafigh }
\tl_set:Nn \l_xephm_fnt_shafighKurd_tl  { shafighKurd }
\tl_set:Nn \l_xephm_fnt_shafighUzbek_tl { shafighUzbek }
\tl_set:Nn \l_xephm_fnt_shiraz_tl       { shiraz }
\tl_set:Nn \l_xephm_fnt_sols_tl         { sols }
\tl_set:Nn \l_xephm_fnt_tabriz_tl       { tabriz }
\tl_set:Nn \l_xephm_fnt_titr_tl         { titr }
\tl_set:Nn \l_xephm_fnt_titre_tl        { titre }
\tl_set:Nn \l_xephm_fnt_traffic_tl      { traffic }
\tl_set:Nn \l_xephm_fnt_vahid_tl        { vahid }
\tl_set:Nn \l_xephm_fnt_vosta_tl        { vosta }
\tl_set:Nn \l_xephm_fnt_yaghut_tl       { yaghut }
\tl_set:Nn \l_xephm_fnt_yagut_tl        { yagut }
\tl_set:Nn \l_xephm_fnt_yas_tl          { yas }
\tl_set:Nn \l_xephm_fnt_yekan_tl        { yekan }
\tl_set:Nn \l_xephm_fnt_yermook_tl      { yermook }
\tl_set:Nn \l_xephm_fnt_zar_tl          { zar }
\tl_set:Nn \l_xephm_fnt_ziba_tl         { ziba }
\tl_set:Nn \l_xephm_fnt_default_tl      { default }
\tl_set:Nn \l_xephm_fnt_noskip_tl       { noskip }

\tl_set:Nn \l_xephm_lig_aalt_tl    { aalt } % Access All Alternatives
\tl_set:Nn \l_xephm_lig_ccmp_tl    { ccmp } % Glyph Composition/Decomposition
\tl_set:Nn \l_xephm_lig_dlig_tl    { dlig } % Discretionary Ligatures
\tl_set:Nn \l_xephm_lig_fina_tl    { fina } % Final (Terminal) Forms
\tl_set:Nn \l_xephm_lig_init_tl    { init } % Initial Forms
\tl_set:Nn \l_xephm_lig_locl_tl    { locl } % Localized Forms
\tl_set:Nn \l_xephm_lig_medi_tl    { medi } % Medial Forms
\tl_set:Nn \l_xephm_lig_rlig_tl    { rlig } % Required Ligatures
\tl_set:Nn \l_xephm_lig_default_tl { default }

\clist_set:Nn \l_xephm_lig_aalt_clist    { } % Access All Alternatives
\clist_set:Nn \l_xephm_lig_ccmp_clist    { } % Glyph Composition/Decomposition
\clist_set:Nn \l_xephm_lig_dlig_clist    { FDF2 = الله , FDF3 = اکبر , FDFB = جلجلاله } % Discretionary Ligatures
\clist_set:Nn \l_xephm_lig_fina_clist    { } % Final (Terminal) Forms
\clist_set:Nn \l_xephm_lig_init_clist    { } % Initial Forms
\clist_set:Nn \l_xephm_lig_locl_clist    { } % Localized Forms
\clist_set:Nn \l_xephm_lig_medi_clist    { } % Medial Forms
\clist_set:Nn \l_xephm_lig_rlig_clist    { } % Required Ligatures
\clist_set:Nn \l_xephm_lig_default_clist { }

\clist_set:Nn \l_xephm_lig_names_clist
  {
    \l_xephm_lig_aalt_tl , { \l_xephm_lig_aalt_clist } ,
    \l_xephm_lig_ccmp_tl , { \l_xephm_lig_ccmp_clist } ,
    \l_xephm_lig_dlig_tl , { \l_xephm_lig_dlig_clist } ,
    \l_xephm_lig_fina_tl , { \l_xephm_lig_fina_clist } ,
    \l_xephm_lig_init_tl , { \l_xephm_lig_init_clist } ,
    \l_xephm_lig_locl_tl , { \l_xephm_lig_locl_clist } ,
    \l_xephm_lig_medi_tl , { \l_xephm_lig_medi_clist } ,
    \l_xephm_lig_rlig_tl , { \l_xephm_lig_rlig_clist } ,
  }

\msg_new:nnn { xepersian-hm } { error-kashida-character-is-not-available-in-the-main-font }
  {
    Sorry,~ kashida~ character~ is~ not~ available~ in~ the~ main~ font~#1!
  }

\msg_new:nnn { xepersian-hm } { error-value-not-available-for-kashida-option }
  {
    Sorry,~ value~ `#1'~ is~ not~ available~ for~ `Kashida'~ option~ yet~!
  }

\msg_new:nnn { xepersian-hm } { error-specify-value-for-kashida-option }
  {
    Sorry,~ you~ must~ specify~ a~ value~ for~ `Kashida'~ option~ yet~!
  }

\msg_new:nnn { xepersian-hm } { warning-experimental-feature }
  {
    Please~ note~ that~ the~ feature~ `#1'~ is~ still~ experimental~
    and~ is~ not~ regarded~ as~ stable.
  }

\msg_new:nnn { xepersian-hm } { hm-series-font-not-found }
  {
    Either~ the~ font~`#1'~ is~ not~ installed~ on~ your~ system~ or~ does~ not~
    belong~ to~ HM~Series~fonts.~
    Please~ note~ that~ the~ option~ `Kashida=leaders+glyph'~ is~ currently~ only~
    supported~ by~ HM~Series~fonts.~
    If~ you~ know~ of~ any~ other~ font~ that~ supports~ this~ option,~ please~
    let~ me~ know~ to~ add~ it~ to~ the~ list~ of~ corresponding~ fonts.~
  }

\keys_define:nn { xepersian-hm }
  {
    Kashida .code:n =
      {
        \tl_set:Nn \l_tmpa_tl { #1 }
        \tl_case:NnTF \l_tmpa_tl
          {
            \l_xephm_stretch_glyph_tl
              {
                \msg_warning:nnn { xepersian-hm } { warning-experimental-feature } { Kashida=glyph }
                \tl_set:Nx \l_xephm_gap_filler_tl { \l_xephm_stretch_glyph_tl }
                \AtBeginDocument
                  {
                    \tl_set:Nx \l_xephm_main_font_full_tl { \tex_fontname:D \tex_the:D \tex_font:D }
                    \tl_set:Nx \l_xephm_main_font_name_tl { \l_xephm_main_font_full_tl }
                    \regex_replace_once:nnN { ^"([^/]+)/.* } { \1 } \l_xephm_main_font_name_tl
                    \int_set:Nn \l_xephm_kashida_slot_int { \XeTeXcharglyph \c_xephm_ksh_int }
                    \int_compare:nT { \l_xephm_kashida_slot_int = \c_zero_int }
                      {
                        \msg_error:nnx { xepersian-hm } { error-kashida-character-is-not-available-in-the-main-font } { \l_xephm_main_font_name_tl }
                      }
                  }
                \bool_set_true:N \l_xephm_kashida_hm_fix_bool
              }
            \l_xephm_stretch_leaders_glyph_tl
              {
                \tl_set:Nx \l_xephm_gap_filler_tl { \l_xephm_stretch_leaders_glyph_tl }
                \bool_set_true:N \l_xephm_kashida_hm_fix_bool
              }
            \l_xephm_stretch_leaders_hrule_tl
              {
                \tl_set:Nx \l_xephm_gap_filler_tl { \l_xephm_stretch_leaders_hrule_tl }
                \bool_set_true:N \l_xephm_kashida_hm_fix_bool
              }
            \l_xephm_stretch_off_tl
              {
                \tl_set:Nx \l_xephm_gap_filler_tl { \l_xephm_stretch_off_tl }
                \bool_set_false:N \l_xephm_kashida_hm_fix_bool
              }
            \l_xephm_stretch_on_tl
              {
                \tl_set:Nx \l_xephm_gap_filler_tl { \l_xephm_stretch_leaders_glyph_tl }
                \bool_set_true:N \l_xephm_kashida_hm_fix_bool
              }
          } { } { \tl_set:Nx \l_xephm_gap_filler_tl { #1 } }
        \tl_if_empty:NT \l_xephm_gap_filler_tl { \msg_error:nn { xepersian-hm } { error-specify-value-for-kashida-option } }
      } ,

    linebreakpenalty .code:n =
      {
        \int_set:Nn \l_tmpa_int { #1 }
        \int_case:nnTF \l_tmpa_int
          {
            \l_xephm_min_penalty_int  { \int_set:Nn \l_xephm_line_break_penalty_int { \l_xephm_min_penalty_int } }
            \l_xephm_low_penalty_int  { \int_set:Nn \l_xephm_line_break_penalty_int { \l_xephm_low_penalty_int } }
            \l_xephm_med_penalty_int  { \int_set:Nn \l_xephm_line_break_penalty_int { \l_xephm_med_penalty_int } }
            \l_xephm_high_penalty_int { \int_set:Nn \l_xephm_line_break_penalty_int { \l_xephm_high_penalty_int } }
            \l_xephm_max_penalty_int  { \int_set:Nn \l_xephm_line_break_penalty_int { \l_xephm_max_penalty_int } }
          } { } { \int_set:Nn \l_xephm_line_break_penalty_int { #1 } }
        \bool_set_true:N \l_xephm_linebreakpenalty_bool
      } ,

    kashidastretch .code:n =
      {
        \tl_set:Nn \l_tmpa_tl { #1 }
        \tl_case:NnTF \l_tmpa_tl
          {
             \l_xephm_fnt_kayhan_tl       { \tl_set:Nn \l_xephm_skip_default_tl { 0.14  em plus 0.5 em } }
             \l_xephm_fnt_kayhannavaar_tl { \tl_set:Nn \l_xephm_skip_default_tl { 0.129 em plus 0.5 em } }
             \l_xephm_fnt_kayhanpook_tl   { \tl_set:Nn \l_xephm_skip_default_tl { 0.133 em plus 0.5 em } }
             \l_xephm_fnt_kayhansayeh_tl  { \tl_set:Nn \l_xephm_skip_default_tl { 0.135 em plus 0.5 em } }
             \l_xephm_fnt_khoramshahr_tl  { \tl_set:Nn \l_xephm_skip_default_tl { 0.128 em plus 0.5 em } }
             \l_xephm_fnt_khorramshahr_tl { \tl_set:Nn \l_xephm_skip_default_tl { 0.13  em plus 0.5 em } }
             \l_xephm_fnt_niloofar_tl     { \tl_set:Nn \l_xephm_skip_default_tl { 0.132 em plus 0.5 em } }
             \l_xephm_fnt_paatch_tl       { \tl_set:Nn \l_xephm_skip_default_tl { 0.127 em plus 0.5 em } }
             \l_xephm_fnt_riyaz_tl        { \tl_set:Nn \l_xephm_skip_default_tl { 0.125 em plus 0.5 em } }
             \l_xephm_fnt_roya_tl         { \tl_set:Nn \l_xephm_skip_default_tl { 0.142 em plus 0.5 em } }
             \l_xephm_fnt_shafigh_tl      { \tl_set:Nn \l_xephm_skip_default_tl { 0.143 em plus 0.5 em } }
             \l_xephm_fnt_shafighKurd_tl  { \tl_set:Nn \l_xephm_skip_default_tl { 0.126 em plus 0.5 em } }
             \l_xephm_fnt_shafighUzbek_tl { \tl_set:Nn \l_xephm_skip_default_tl { 0.123 em plus 0.5 em } }
             \l_xephm_fnt_shiraz_tl       { \tl_set:Nn \l_xephm_skip_default_tl { 0.122 em plus 0.5 em } }
             \l_xephm_fnt_sols_tl         { \tl_set:Nn \l_xephm_skip_default_tl { 0.124 em plus 0.5 em } }
             \l_xephm_fnt_tabriz_tl       { \tl_set:Nn \l_xephm_skip_default_tl { 0.119 em plus 0.5 em } }
             \l_xephm_fnt_titr_tl         { \tl_set:Nn \l_xephm_skip_default_tl { 0.12  em plus 0.5 em } }
             \l_xephm_fnt_titre_tl        { \tl_set:Nn \l_xephm_skip_default_tl { 0.121 em plus 0.5 em } }
             \l_xephm_fnt_traffic_tl      { \tl_set:Nn \l_xephm_skip_default_tl { 0.124 em plus 0.5 em } }
             \l_xephm_fnt_vahid_tl        { \tl_set:Nn \l_xephm_skip_default_tl { 0.134 em plus 0.5 em } }
             \l_xephm_fnt_vosta_tl        { \tl_set:Nn \l_xephm_skip_default_tl { 0.136 em plus 0.5 em } }
             \l_xephm_fnt_yaghut_tl       { \tl_set:Nn \l_xephm_skip_default_tl { 0.138 em plus 0.5 em } }
             \l_xephm_fnt_yagut_tl        { \tl_set:Nn \l_xephm_skip_default_tl { 0.137 em plus 0.5 em } }
             \l_xephm_fnt_yas_tl          { \tl_set:Nn \l_xephm_skip_default_tl { 0.126 em plus 0.5 em } }
             \l_xephm_fnt_yekan_tl        { \tl_set:Nn \l_xephm_skip_default_tl { 0.141 em plus 0.5 em } }
             \l_xephm_fnt_yermook_tl      { \tl_set:Nn \l_xephm_skip_default_tl { 0.139 em plus 0.5 em } }
             \l_xephm_fnt_zar_tl          { \tl_set:Nn \l_xephm_skip_default_tl { 0.116 em plus 0.5 em } }
             \l_xephm_fnt_ziba_tl         { \tl_set:Nn \l_xephm_skip_default_tl { 0.119 em plus 0.5 em } }
             \l_xephm_fnt_default_tl      { \tl_set:Nn \l_xephm_skip_default_tl { 0.14  em plus 0.5 em } }
             \l_xephm_fnt_noskip_tl       { \tl_set:Nn \l_xephm_skip_default_tl { 0     em plus 0.5 em } }
          } { } { \tl_set:Nn \l_xephm_skip_default_tl { #1 } }
      } ,
    kashidastretch .default:n = \tl_set:Nn \l_xephm_skip_default_tl { 0 em plus 0.5 em } ,

    ligatures .code:n =
      {
        \tl_set:Nn \l_tmpa_tl { #1 }
        \tl_case:NnTF \l_tmpa_tl
          {
            \l_xephm_lig_aalt_tl    { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_aalt_tl } }
            \l_xephm_lig_ccmp_tl    { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_ccmp_tl } }
            \l_xephm_lig_dlig_tl    { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_dlig_tl } }
            \l_xephm_lig_fina_tl    { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_fina_tl } }
            \l_xephm_lig_init_tl    { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_init_tl } }
            \l_xephm_lig_locl_tl    { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_locl_tl } }
            \l_xephm_lig_medi_tl    { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_medi_tl } }
            \l_xephm_lig_rlig_tl    { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_rlig_tl } }
            \l_xephm_lig_default_tl { \tl_set:Nx \l_xephm_active_ligs_tl { \l_xephm_lig_default_tl } }
          } { } { \tl_set:Nn \l_xephm_active_ligs_tl { #1 } }
        \bool_set_true:N \l_xephm_ligature_bool
      } ,
    ligatures .default:n = \tl_set:Nn \l_xephm_active_ligs_tl { \l_xephm_lig_default_tl } ,
  }

\ProcessKeysOptions { xepersian-hm }

\bool_if:NT \l_xephm_kashida_hm_fix_bool
  {
    \tex_input:D { kashida-xepersian-hm.def }
  }

\ExplSyntaxOff
 \endinput
%</xepersian-hm-sty>
%    \end{macrocode}
%
% \subsection{File: \texttt{kashida-xepersian-hm.def}}
%    \begin{macrocode}
%<*kashida-xepersian-hm-def>
\ExplSyntaxOn
\ProvidesExplFile {kashida-xepersian-hm.def} {2020-08-05} {1.0d} { Fixes~implementation~of~Kashida~in~xepersian~package }

\newXeTeXintercharclass \c_xephm_d_charclass % dual-joiner class
\newXeTeXintercharclass \c_xephm_l_charclass % lam
\newXeTeXintercharclass \c_xephm_r_charclass % right-joiner
\newXeTeXintercharclass \c_xephm_a_charclass % alef
\newXeTeXintercharclass \c_xephm_y_charclass % yeh

\bool_if:NT \l_xephm_ligature_bool
{
  \clist_new:N \l_xephm_ligatures_clist
  \int_new:N \l_xephm_lig_names_len_int
  \int_set:Nn \l_xephm_lig_names_len_int { \clist_count:N \l_xephm_lig_names_clist }
  \int_step_inline:nnnn { 1 } { 2 } { \l_xephm_lig_names_len_int }
    {
      \int_set:Nn \l_tmpa_int { #1 }
      \int_set:Nn \l_tmpb_int { \int_eval:n { \l_tmpa_int + 1 } }
      \tl_set:Nf \l_tmpa_tl { \clist_item:Nn \l_xephm_lig_names_clist { \l_tmpa_int } }
      \clist_set:Nx \l_tmpa_clist { { \clist_item:Nn \l_xephm_lig_names_clist { \l_tmpb_int } } }
      \bool_if:nT { \tl_if_eq_p:NN  \l_xephm_active_ligs_tl  \l_tmpa_tl || \tl_if_eq_p:NN  \l_xephm_active_ligs_tl \l_xephm_lig_default_tl }
        {
          \clist_put_left:Nx \l_xephm_ligatures_clist { \l_tmpa_clist }
        }
    }
  \clist_map_inline:Nn \l_xephm_ligatures_clist
    {
      \seq_set_split:Nnn \l_tmpa_seq { = } { #1 }
      \seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl { } { }
      \seq_pop_left:NN \l_tmpa_seq \l_tmpb_tl { } { }
      \tl_const:cx { \tl_use:N \l_tmpb_tl } { \char"\l_tmpa_tl \ }
    }
}

\bool_if:NT \l_xephm_linebreakpenalty_bool
{
  %% Partly adapted from LaTeX2e source
  \cs_new:Nn \xephm_line_break: {
    \if_mode_vertical:
      \GenericError{
        \space\space\space\space\space\space\space\space\space\space\space\space\space\space\space
        }{
           LaTeX Error: There’s no line here to end
        }{
           See the LaTeX manual or LaTeX Companion for explanation.
        }{
           Your command was ignored.\MessageBreak
           Type \space I <command> <return> \space to replace it~
           with another command,\MessageBreak
           or \space <return> \space to continue without it.}
    \else:
      \l_tmpa_skip \tex_lastskip:D
      \tex_unskip:D
      \tex_penalty:D -\l_xephm_line_break_penalty_int
      \dim_compare:nT { \l_tmpa_skip > \c_zero_skip }
        { \skip_horizontal:N \l_tmpa_skip  \tex_ignorespaces:D }
    \fi:
  }

  \NewDocumentCommand { \discouragebadlinebreaks } { O{\l_xephm_line_break_penalty_int} O{\c_xephm_skip_b_tl} m }
    {
      \IfNoValueF {#1}
        { \int_set:Nn \l_xephm_line_break_penalty_int {#1} }
      \IfNoValueF {#2}
        { \tl_set:Nn \l_xephm_skip_default_tl {#2} }
      \xephm_put_line_breaks:n { #3 }
   }

  \cs_new_protected:Nn \xephm_put_line_breaks:n
    {
      \tl_set:Nn \l_xephm_line_break_tl { #1 }
      \regex_replace_all:nnN { ([ابپتثجحخچدذرزژسشعغصضفقطظکگلمنوهیـ])+ } { \ \0 \  \c{xephm_line_break:}\  } \l_xephm_line_break_tl
      \tl_use:N \l_xephm_line_break_tl
    }
}

%% Partly adapted from the code provided by David Carlisle in:
%% https://tex.stackexchange.com/questions/356709/how-to-know-the-width-and-fill-the-glue-space-between-two-characters-when-using/356721#356721
\cs_new:Npn \xephm_kashida_glyph #1
{
  \bool_if:NT \l_xephm_kashida_hm_fix_bool
  {
    \c_xephm_lrm_int\tex_penalty:D 10000
    \mode_leave_vertical:
    \tex_global:D \tex_advance:D \l_xephm_counter_int \c_one_int

    \tl_set:Nx \l_xephm_pos_tl { p\tex_romannumeral:D \l_xephm_counter_int }
    \tl_set:Nx \l_xephm_zref_tl { z\tex_romannumeral:D \l_xephm_counter_int }

    \zsaveposx{x_i_\l_xephm_zref_tl}
    \tl_set:Nx \l_tmpa_tl
      {
        \iow_now:cx { @auxout }
        {
          \token_to_str:N \gdef \exp_after:wN \token_to_str:N \cs:w xi\l_xephm_pos_tl \cs_end: { \zposx{ x_i_\l_xephm_zref_tl } }
        }
      }
    \l_tmpa_tl
    \skip_horizontal:n { #1 }
    \zsaveposx{x_f_\l_xephm_zref_tl}
    \tl_set:Nx \l_tmpa_tl
      {
        \iow_now:cx { @auxout }
        {
          \token_to_str:N \gdef \exp_after:wN \token_to_str:N \cs:w xf\l_xephm_pos_tl \cs_end: { \zposx{ x_f_\l_xephm_zref_tl } }
        }
      }
    \l_tmpa_tl
    \exp_after:wN
    \if_meaning:w
      \cs:w xi\l_xephm_pos_tl \cs_end: \tex_relax:D
    \else:
      \dim_set:Nn \l_xephm_diff_pos_dim
        {
          \dim_eval:n { \cs:w xi\l_xephm_pos_tl \cs_end: sp - \cs:w xf\l_xephm_pos_tl \cs_end: sp }
        }
      \dim_compare:nTF { \l_xephm_diff_pos_dim == 0sp }
        { }
        { \llap { \resizebox { \l_xephm_diff_pos_dim \tex_relax:D } { \height } { \c_xephm_ksh_int } } }
    \fi:
  }
}

\cs_new:Npn \xephm_kashida_leaders #1
{
  \bool_if:NT \l_xephm_kashida_hm_fix_bool
    {
      \tl_if_eq:NNTF \l_xephm_gap_filler_tl  \l_xephm_stretch_leaders_glyph_tl
        {
          \tl_set:Nx \l_xephm_font_full_tl { \tex_fontname:D \tex_the:D \tex_font:D }
          \tl_set:Nx \l_xephm_font_name_tl { \l_xephm_font_full_tl }
          \tl_set:Nx \l_xephm_font_init_tl { \l_xephm_font_name_tl }
          \regex_replace_once:nnN { ^"\[?(HM)[\_\ ](X|F).* } { \1\2 } \l_xephm_font_init_tl\relax
          \tl_set:Nn \l_tmpa_tl { HMF }
          \tl_set:Nn \l_tmpb_tl { HMX }
          \bool_if:nTF { \str_if_eq_p:NN { \l_xephm_font_init_tl } { \l_tmpa_tl } || \str_if_eq_p:NN { \l_xephm_font_init_tl } { \l_tmpb_tl } }
            {
              \hbox_set:Nn \l_xephm_ksh_box { \XeTeXglyph\XeTeXglyphindex"kashida" }
              \c_xephm_zwj_int \tex_penalty:D 10000
              \tex_leaders:D \copy\l_xephm_ksh_box \skip_horizontal:n { #1 }
              \c_xephm_zwj_int
            }
            {
              \msg_error:nnx { xepersian-hm } { hm-series-font-not-found } { \l_xephm_font_name_tl }
            }
        }
        {
          %% Partly adapted from the code provided by Jonathan Kew in:
          %% https://tug.org/pipermail/xetex/2009-February/012307.html.
          %% Somebody notified me that the code in 'kashida-xepersian.def' from xepersian
          %% package is an exact copy of Jonathan Kew's code. Being unaware of this, in
          %% the earlier versions of this package I made a mistake and acknowledged
          %% Vafa Khalighi instead of Jonathan Kew. A sincere thank you to Jonathan Kew
          %% for his excellent code.
          \c_xephm_lrm_int\c_xephm_zwj_int\tex_penalty:D 10000
          \tex_leaders:D \tex_hrule:D height \XeTeXglyphbounds \c_xephm_two_int
          \int_use:N \XeTeXcharglyph \c_xephm_ksh_int depth \XeTeXglyphbounds \c_xephm_four_int
          \int_use:N \XeTeXcharglyph \c_xephm_ksh_int \skip_horizontal:n { #1 }
          \c_xephm_zwj_int
        }
    }
}

\XeTeXinterchartokenstate = 1

\clist_set:Nn \l_xephm_a_clist { 0622,0623,0625,0627 } % ‏ا، إ، أ، آ‏
\clist_map_inline:Nn \l_xephm_a_clist
  {
    \XeTeXcharclass "#1 \c_xephm_a_charclass
  }

\clist_set:Nn \l_xephm_d_clist { 0626,0628,062A,062B,062C,062D,062E,0633,0634,0635,0636,0637,0638,0639,063A,0640,0641,0642,0643,0645,0646,0647,067E,0686,06A9,06AF } % ‏ئ,ب,ت,ث,ج,ح,خ,س,ش,ص,ض,ط,ظ,ع,غ,ـ,ف,ق,ك,م,ن,ه,پ,چ,ک,گ‏
\clist_map_inline:Nn \l_xephm_d_clist
  {
    \XeTeXcharclass "#1 \c_xephm_d_charclass
  }

\clist_set:Nn \l_xephm_l_clist { 0644 } % ‏ل‏
\clist_map_inline:Nn \l_xephm_l_clist
  {
    \XeTeXcharclass "#1 \c_xephm_l_charclass
  }

\clist_set:Nn \l_xephm_r_clist { 0624,0629,062F,0630,0631,0632,0648,0698 } % ‏ؤ,ة,د,ذ,ر,ز,و,ژ‏
\clist_map_inline:Nn \l_xephm_r_clist
  {
    \XeTeXcharclass "#1 \c_xephm_r_charclass
  }

\clist_set:Nn \l_xephm_y_clist { 0649,064A,06CC } % ‏ی,ي,ى‏
\clist_map_inline:Nn \l_xephm_y_clist
  {
    \XeTeXcharclass "#1 \c_xephm_y_charclass
  }

\tl_if_eq:NNTF  \l_xephm_gap_filler_tl  \l_xephm_stretch_glyph_tl {
  \XeTeXinterchartoks \c_xephm_y_charclass \c_xephm_y_charclass = {
    \bool_if:NTF \l_xephm_kashida_hm_fix_bool
    { \c_xephm_zwj_int \xephm_kashida_glyph \l_xephm_skip_default_tl \c_xephm_zwj_int }
    { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  }
  \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_y_charclass = {
    \bool_if:NTF \l_xephm_kashida_hm_fix_bool
    { \c_xephm_zwj_int \xephm_kashida_glyph \l_xephm_skip_default_tl \c_xephm_zwj_int }
    { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  }
  \XeTeXinterchartoks \c_xephm_y_charclass \c_xephm_d_charclass = { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_d_charclass = { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  \XeTeXinterchartoks \c_xephm_l_charclass \c_xephm_d_charclass = { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_l_charclass = { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  \XeTeXinterchartoks \c_xephm_l_charclass \c_xephm_l_charclass = { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_r_charclass = { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_a_charclass = { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  \XeTeXinterchartoks \c_xephm_l_charclass \c_xephm_r_charclass = { \c_xephm_zwj_int \xephm_kashida_glyph \c_xephm_skip_a_tl \c_xephm_zwj_int }
  \XeTeXinterchartoks \c_xephm_l_charclass \c_xephm_a_charclass = { }
}
{
  \bool_if:nTF {
    \tl_if_eq_p:NN  \l_xephm_gap_filler_tl  \l_xephm_stretch_leaders_glyph_tl ||
    \tl_if_eq_p:NN  \l_xephm_gap_filler_tl  \l_xephm_stretch_leaders_hrule_tl
  }
  {
    \XeTeXinterchartoks \c_xephm_y_charclass \c_xephm_y_charclass = {
      \bool_if:NTF \l_xephm_kashida_hm_fix_bool
      { \xephm_kashida_leaders \l_xephm_skip_default_tl }
      { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    }
    \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_y_charclass = {
      \bool_if:NTF \l_xephm_kashida_hm_fix_bool
      { \xephm_kashida_leaders \l_xephm_skip_default_tl }
      { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    }
    \XeTeXinterchartoks \c_xephm_y_charclass \c_xephm_d_charclass = { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_d_charclass = { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    \XeTeXinterchartoks \c_xephm_l_charclass \c_xephm_d_charclass = { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_l_charclass = { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    \XeTeXinterchartoks \c_xephm_l_charclass \c_xephm_l_charclass = { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_r_charclass = { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    \XeTeXinterchartoks \c_xephm_d_charclass \c_xephm_a_charclass = { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    \XeTeXinterchartoks \c_xephm_l_charclass \c_xephm_r_charclass = { \xephm_kashida_leaders \c_xephm_skip_a_tl }
    \XeTeXinterchartoks \c_xephm_l_charclass \c_xephm_a_charclass = { }
  }
  {
    \msg_error:nnx { xepersian-hm } { error-value-not-available-for-kashida-option } { \l_xephm_gap_filler_tl }
  }
}

\NewDocumentCommand \KashidaHMFixOn {} { \bool_set_true:N \l_xephm_kashida_hm_fix_bool }
\NewDocumentCommand \KashidaHMFixOff {} { \bool_set_false:N \l_xephm_kashida_hm_fix_bool }

\tex_let:D \KashidaOn \KashidaHMFixOn
\tex_let:D \KashidaOff \KashidaHMFixOff

\bool_if:NTF \l_xephm_kashida_hm_fix_bool
  {
    \tl_if_empty:NT \l_xephm_skip_default_tl { \tl_set:Nn \l_xephm_skip_default_tl  { 0.14 em plus 0.5 em } }
  }
  {
    \tl_set:NV \l_xephm_skip_default_tl  \c_xephm_skip_a_tl
  }

\ExplSyntaxOff

\makeatletter
\newif\if@Kashida@on
%% Becuase Vafa Khalighi has copied the above code (injecting the character uni+200E) in xepersian-23.0
%% (https://tug.org/svn/texlive/trunk/Master/texmf-dist/tex/xelatex/xepersian/kashida-xepersian.def?revision=55165&view=co),
%% the following line of code is not needed in xepersian anymore.
%% % \newif\if@Kashida@XB@fix
\makeatother

 \endinput
%</kashida-xepersian-hm-def>
%    \end{macrocode} 
%
% \section*{Acknowledgements}
% 
% Todo
%
% \section*{Change History}
%
% Todo
%
% \section*{References}
%
% Todo
%
% \section*{Index}
%
% Todo
%
% \Finale
