Chapter 10
halign-based tables

   10.1 Taming of halign
   10.2 Building Blocks for Accessing Halign Tables
      Build Expanded Pattern
      Html Insertions
      /omit and /span
      TD Script
      Utilities
   10.3 A Realization for halign
      Check for /edef Environment
      Remove Dimension
      Check for Embedded Def
      /halign Not Within Parameters
      Embedded /halign
      Utilities fo Embedded /halign
      /halign into <PRE>
      /halign into /MkHalign
      noalign

<..halign-based tables..>
 <.all halign-based tables.>
 <.html blocks for halign tables.>
 <.html halign.>
 \def\:temp{\let\:shrp=##} \:temp
 -_-_-

The \:shrp should be defined at the end so as not to bother other definitions that will regard it as improper # parameter.

10.1 Taming of halign

The \halign comamnds not defined within TeX4ht environment can be problematic, and the same may be true to some within such environnt. Specifically, comamnds of the form \halign...{...} are translated well in TeX4ht, but cause a problem if defined before TeX4ht was activated. Commands of the form \halign...\bgroup... cause no problem in either mode, but they also introduce no html code. Commands of the form \halign...{...\egroup cause problems in either way.

TeX4ht takes care of the \halign commands in TeX and LaTeX, but not of those that are loaded earlier from other libraries.

The following tree shows the direct and indirect use of \halign in TeX and LaTeX.

The \iffalse{\fi...\iffalse}\fi is to hide the \cr from \halign when it scans for that command.

<..all halign-based tables..>
 \let\TeXhalign=\halign
 \def\RecallTeXcr{\iffalse{\fi
    \expand:after{\let\cr=}\csname 0cr\endcsname
    \expand:after{\let\crcr=}\csname 0crcr\endcsname
    \iffalse}\fi}
 \expandafter\let\csname 0cr\endcsname=\cr
 \expandafter\let\csname 0crcr\endcsname=\crcr
 \def\TeXhalign:cr{%
    \ifx \EndPicture\:UnDef \else \iffalse{\fi
       \expandafter\let\expandafter\cr\csname \MkHalign:d cr\endcsname
       \expandafter\let\expandafter\crcr\csname \MkHalign:d crcr\endcsname
    \iffalse}\fi \fi  \TeXhalign}
 -_-_-

Save/recover \crcr and \cr causes problems, e.g., in nested arrays. It seems also we don’t really need such a feature.

<..tex4ht halign and cr/crcr..>
 \let\halign=\sv:halign
 -_-_-

10.2 Building Blocks for Accessing Halign Tables

The next comamnd can be in use when the parameters # (i.e., the first parameter #1) are in cat code 13.

We hade \:relax instead of \relax below. Where did it come from?

The \MkHalign takes the form \MkHalign#{...pattern...}...body...\EndHalign and seeds the end tags \a:halign and \b:halign around the construct, and \c:halign and d:halign in the pattern. The outcome is a seeded \halign{...}. The \Configure{MkHalign}... places a:MkHalign, b:MkHalign, c:MkHalign, d:MkHalign, e:MkHalign, and \f:MkHalign within \a:halign, \b:halign, \c:halign, and d:halign. The # in the pattern can be any character of category code 13. The & charaters shouldn’t be within braces. The \RecallTeXcr should appear before \MkHalign; if it appears within the pattern, we loose the row breaks.

<..html blocks for halign tables..>
 \def\MkHalign#1#2{%
   \iffalse{\fi   \let\sv:new:row=\new:row
   \def\relax:shrp{\let#1=\relax}%
   \def\new:halign{\TeXhalign \bgroup}%
   \add:halign#2&<.par del.>\cr
   \let#1=\:shrp  <.before TeXhalign.>%
   \iffalse}\fi      <.protection for $$.>%
   \a:PauseMkHalign \new:halign\ext:cr}
 \def\EndMkHalign{\egroup
    \d:PauseMkHalign <.end protection for $$.>%
    \iffalse{\fi <.after TeXhalign.>\relax:shrp \iffalse}\fi }
 \def\PauseMkHalign#1{\cr\egroup
    \hbox{\r:halign \global\let\new:row=\R:halign}\b:PauseMkHalign
    #1\c:PauseMkHalign\new:halign\ext:cr}
 -_-_-

<..shared config..>+
 \NewConfigure{PauseMkHalign}{4}
 -_-_-

The PauseMkHalign provides a vehicle to decompose a \halign\bgroup...0......1...\egroup and recompose it in arbitrary order and choise of components, as is the case in longtable: \setbox0=\hbox{\halign\bgroup...0...\egroup} \setbox1=\hbox{\halign\bgroup...1...\egroup}\box0\box1. In some occasions, and may be all, the parameter of \PauseMkHalign must be just boxes.

The \iffalse ...\fi above are for hiding \cr in nested cases (e.g., of \tabular in LaTeX).

Spans over N columns require many compilations to realize them.

The following is an application of \MkHalign. it allows for tables of the form \MiniHalign...\EndMiniHalign instead of \halign{...}.

<..html blocks for halign tables..>+
                             \catcode‘\#=13 \catcode‘\@=6
 \def\MiniHalign{\begingroup  \catcode‘\#=13 \let#=\relax
    \:MHalign}
 \def\:MHalign@1\cr{\endgroup  \SaveMkHalignConfig
    \Configure{MkHalign}{\a:MiniHalign}{\b:MiniHalign}\c:MiniHalign
    \d:MiniHalign{\e:MiniHalign\RecallMkHalignConfig}\f:MiniHalign
    \MkHalign#{@1}}
                              \catcode‘\#=6 \catcode‘\@=11
 \def\EndMiniHalign{\EndMkHalign  \RecallMkHalignConfig }
 -_-_-

<..shared config..>+
 \NewConfigure{MiniHalign}{6}
 -_-_-

[test data]

<..protection for $$..>
 \begingroup
 \ifmmode  \def\end:m{$$\egroup}\vtop\bgroup$$\else
 \let \end:m=\empty\fi
 -_-_-

<..end protection for $$..>
 \end:m\endgroup
 -_-_-

Build Expanded Pattern

Break the pattern at &s and enclose with calls for html code.

<..html blocks for halign tables..>+
 \def\add:halign#1&#2\cr{%
    \def\:temp{#2}\def\:tempb{<.par del.>}%
    \ifx \:temp\:tempb
       \append:def\new:halign{\b:halign#1\c:halign}%
    \else
       \def\:temp{#1}\ifx\:temp\empty \append:def\new:halign{&}%
       \else  \append:def\new:halign{\b:halign#1\c:halign&}\fi
       \add:halign#2\cr
    \fi}
 -_-_-

Html Insertions

<..before TeXhalign..>
 \global\let\new:row=\R:halign
 \Advance:\MkHalign:d by 1
 \expandafter\let\csname \MkHalign:d cr\endcsname=\cr
 \expandafter\let\csname \MkHalign:d crcr\endcsname=\crcr
 \edef\cr{\noexpand\rR:halign
    \expandafter\noexpand \csname \MkHalign:d cr\endcsname}%
 \edef\crcr{\noexpand\rR:halign
    \expandafter\noexpand \csname \MkHalign:d crcr\endcsname}%
 \let\omit=\om:t \def\TT:halign{\T:halign \global\let\TT:halign=\empty}%
 -_-_-

Inserting \T:halign here causes infinite loop in \@array of latex. Hence, we delay it to the stat of the first element.

<..after TeXhalign..>
 \expand:after{\let\cr=}\csname \MkHalign:d cr\endcsname
 \expand:after{\let\crcr=}\csname \MkHalign:d crcr\endcsname
 \let\omit=\:omit
 {\ht:everypar{}\r:halign}\t:halign
 \Advance:\MkHalign:d by -1
 -_-_-

<..html blocks for halign tables..>+
 \def\rR:halign{\gdef\new:row{\r:halign \R:halign}}
 \HAssign\MkHalign:d = 0
 -_-_-

<..html blocks for halign tables..>+
 \def\b:halign{\BB:halign \bgroup}
 \def\c:halign{\egroup\d:halign}
 \def\BB:halign{\expand:after{\global\let\new:row=\empty }\new:row
    \D:halign}
 -_-_-

The \Configure may use the values of \:MULTISPAN, \halignTD, \HRow’ and \HCol. The \halignTD gets its value from \Configure{TD}{...}.

<..html config util..>+
 \def\halignTD{\ifx \:mALIGN\empty \hT:D \else \:mALIGN \fi}
 \def\halignTB#1{
    \expandafter\ifx \csname :#1:\endcsname\relax
       \:warning{Missing \string\Configure{halignTB<>}{#1}}%
    \else
       \global\expandafter\let\expandafter\:MkHalign:
       \csname :#1:\endcsname \a:halignTB \expandafter\expandafter
       \expandafter\halign:TB \csname :#1:\endcsname<.par del.>\b:halignTB
    \fi }
 \NewConfigure{halignTB}{2}
 \NewConfigure{halignTB<>}[2]{%
    \expandafter\def\csname :#1:\endcsname{#2}}
 <.init :MkHalign:.>
 -_-_-

<..html config util..>+
 \NewConfigure{MkHalign}[6]{%
    \def\T:halign{\PushMacro\:MkHalign:<.init :MkHalign:.>#1}%
    \def\t:halign{#2\PopMacro\:MkHalign:
                  \global\let\:MkHalign:=\:MkHalign:}%
    \def\R:halign{\TT:halign \gHAdvance\HRow by 1 \gHAssign\HCol=1
       #3}%
    \def\r:halign{\end:omit#4}%
    \def\D:halign{\:nopartrue
       <.save dH.>%
       <.cond TD for multispan.>%
       \ifnum\MS:count=\ifx \:MULTISPAN\:UnDef \MS:count
                       \else                  \:MULTISPAN\fi
          \expandafter\gdef\csname dH\MkHalign:d\endcsname
             {<.cond /TD for multispan.>}\fi}%
    \def\d:halign{\csname dH\ifnum \MkHalign:d<1 1\else \MkHalign:d\fi
                  \endcsname <.recall dH.>}}
 \Configure{MkHalign}{}{}{}{}{}{}
 \HAssign\dH:cnt=0
 -_-_-

<..save dH..>
 \gHAdvance\dH:cnt by 1
 \edef\:tempa{\global\let\expandafter\noexpand\csname xc\dH:cnt\endcsname
        \expandafter\noexpand\csname dH\MkHalign:d\endcsname}%
 \:tempa
 \expandafter\xdef\csname \dH:cnt :tempa\endcsname{%
    \global\let \expandafter\noexpand\csname dH\MkHalign:d\endcsname
        \expandafter\noexpand\csname xc\dH:cnt\endcsname}%
 -_-_-

<..recall dH..>
 \csname \dH:cnt :tempa\endcsname
 \gHAdvance\dH:cnt by -1
 -_-_-

Nonleading \csname dH\MkHalign:d\endcsname produce improper closing delimiters in \multispan of index > 1. In such cases, only the outcome of the first \D:halign contribute for the openning delimiter—occuring in the iteration in which \MS:count=\:MULTISPAN.

The \ifnum \MkHalign:d<1 1\else \MkHalign:d\fi is needed because we can get down to 0 if the last entry is a \multispan.

<..math config util..>
 
 -_-_-

<..init :MkHalign:..>
 \Configure{halignTB<>}{MkHalign}{<>}%
 -_-_-

The saving \csname dH\MkHalign:d\endcsname and loading is to protect from changes that may occur inside the entity in the meaning of \d:halign. Don’t we need the same for \r:halign?

The following is for tracing users definitions to be used in extensions that need to do reverse eng of the users input.

<..shared configNO..>
 \NewConfigure{TraceTables}[8]{\def\trc:T{#1}\def\trc:eT{#2}%
    \def\trc:t{#3}\def\trc:et{#4}\def\trc:R{#5}\def\trc:eR{#6}%
    \def\trc:r{#7}\def\trc:er{#8}\d:TrcHlgn}
 \def\d:TrcHlgn#1#2#3#4{\def\trc:D{#1}\def\trc:eD{#2}%
    \def\trc:d{#3}\def\trc:ed{#4}}
 -_-_-

The \:removeindenttrue is important, for instance, in case of a \noalign{...}.

When we meet &&, which signals a loop.

We place # under catcode 13. \noalign is ignored.

<..html blocks for halign tables..>+
 \def\SaveMkHalignConfig{\let\sT:halign=\T:halign
    \let\st:halign=\t:halign
    \let\sR:halign=\R:halign
    \let\sr:halign=\r:halign
    \let\sD:halign=\D:halign
    \let\sd:halign=\d:halign}
 \def\RecallMkHalignConfig{\let\T:halign=\sT:halign
    \let\t:halign=\st:halign
    \let\R:halign=\sR:halign
    \let\r:halign=\sr:halign
    \let\D:halign=\sD:halign
    \let\d:halign=\sd:halign}
 -_-_-

/omit and /span

<..html blocks for halign tables..>+
 \let\:omit=\omit
 \def\om:t{\:omit \BB:halign
    \gdef\end:omit{\gdef\end:omit{}\d:halign}}
 \let\end:omit=\empty
 -_-_-

A \multispa is a sequence of \span’s. Each \span puts \HRow.\HCol; in \new:span;. Next compilation retrieves this info to compute \:MULTISPAN.

<..cond TD for multispan..>
 \gHAdvance\MS:count by -1
 \ifnum \MS:count > 0  \else
    \end:omit  \relax:shrp     \derive:TD
    \HAssign\:MULTISPAN=1  \let\:mALIGN=\empty
    \expandafter\add:span\old:span \gHAssign\MS:count=\:MULTISPAN
    \relax #5%
 \fi
 \xdef\Step:Col{\ifx \HMultispan\:UnDef 1 \else \HMultispan\fi}%
 -_-_-

<..cond /TD for multispan..>
 \ifnum \MS:count<2 #6\relax
  \gHAdvance\HCol  \Step:Col\relax \fi
 -_-_-

For some reason \if:latex\@multicnt\else\mscount\fi didn’t work for \MS:count>0 on

\halign{#\qquad& \$# each\cr 
\omit\span\omit\hfil 
   Shipping Charges\hfil\cr 
1--10&1.30\cr11--100&1.00\cr 
111--&0.70\cr} 

Tried to put \iffalse{\fi \let\cr|=\ext:cr \let\crcr|=\ext:crcr \iffalse}\fi at start of cell. It didn’t work, because I couldn’t restore the \cr and \crcr before the \cr is read at end of line. This doesn’t look like an important because the redefined version just has a \gdef in it and produces no code of itself. However, it is important because problems sometimes arise if a nonnative instance is present, for instance, in \openup10pt \halign{ $2^{#}$\quad& $\overbrace{2\cdots 2}^{# \rm times}$\quad& #\cr 2&2&4\cr 3&3&8\cr } .

See Knuth 386 for the hiding \iffalse{\fi\let\cr|=\ext:cr\iffalse}\fi of \cr.

<..html blocks for halign tables..>+
 \let\ext:cr=\cr  \let\ext:crcr=\crcr
 -_-_-

<..html blocks for halign tables..>+
 \let\:span=\span
 \def\add:span#1;{\def\:tempa{#1}\edef\:temp{\HRow .\HCol}%
    \ifx \:temp\:tempa \Advance:\:MULTISPAN by 1 \fi
    \ifx \:tempa\empty \let\HMultispan=\:MULTISPAN
    \else
       <.align for multispan in latex.>%
       \expandafter\add:span
    \fi }
 -_-_-

<..align for multispan in latex..>
 \let\:temp=\relax
 \def\:temp##1.{\def\:temp####1<.par del.>{\def\:temp{####1}}%
    \afterassignment\:temp\tmp:cnt}%
 \expandafter\expandafter\expandafter\:temp\expandafter\:tempa<.par del.>%
 \edef\:tempb{\HRow.\HCol\:temp}\ifx\:tempa\:tempb
    \expandafter\ifx \csname \expandafter\string\:temp :T:D\endcsname\relax
    \else \edef\:mALIGN{\expandafter\noexpand
           \csname \expandafter\string\:temp :T:D\endcsname}%
 \fi\fi
 -_-_-

<..NO..>
 \edef\:temp{\HRow .\HCol<}%
 \ifx \:temp\:tempa \def\:mALIGN{\l:TD}\fi
 \edef\:temp{\HRow .\HCol-}%
 \ifx \:temp\:tempa \def\:mALIGN{\c:TD}\fi
 \edef\:temp{\HRow .\HCol>}%
 \ifx \:temp\:tempa \def\:mALIGN{\r:TD}\fi
 -_-_-

<..before TeXhalign..>+
 \let\sv:end:omit=\end:omit  \let\end:omit=\empty
 \let\ms:count=\MS:count \HAssign\MS:count=0
 \let\lgn:r=\HRow \let\lgn:c=\HCol  \HAssign\HRow=0
 \def\span{\xdef\new:span{\new:span\HRow.\HCol;}\:span}%
 \let\sv:new:span=\new:span  \let\new:span=\empty
 \gHAdvance\Halgn:cnt by 1 \edef\halign:id{\Halgn:cnt}%
 \edef\old:span{\LikeRef{<.halign tag.>}}%
 \ifx \old:span\space \def\old:span{;}\fi
 -_-_-

The \ifx \old:span\space \def\old:span{;}\fi is needed for first runs when no info is yet available.

<..after TeXhalign..>+
 \Tag{<.halign tag.>}{\new:span;}%
 \global\let\new:span=\sv:new:span
 \iffalse{\fi \let\span=\:span \iffalse}\fi
 \global\let\HRow=\lgn:r   \global\let\HCol=\lgn:c
 \global\let\MS:count=\ms:count
 \global\let\new:row=\sv:new:row
 \global\let\end:omit=\sv:end:omit
 -_-_-

<..html blocks for halign tables..>+
 \HAssign\Halgn:cnt=0
 -_-_-

The \mu:span Provides a little movement to avoid oscilation of multi spans around incorrect values. It is attached to \TitleCount ingeneral, but not within \begin{longtable}...\end{longtable}. In that environment, \caption may appear, and so change the value of \TitleCount in the middle of a table, within a \multispan.

<..halign tag..>
 <.auto tag.>M\halign:id x\mu:span-_-_-

TD Script

Through \Configure{MkHalign}{....} with entries of the form row col insertion (space at end: \Contribute{halignTD}{1 1 - } is fine but not \Contribute{halignTD}{1 1 -}. The first character may be a code <, -, >, ^, =, -, or _. A row of value 0 applies for a full column, a column of 0 stands for a full row, and row and col of 0 stand for a full table.

<..html blocks for halign tables..>+
 \def\derive:TD{%
    \bgroup \no:actv
        \xdef\:temp{\noexpand\expandafter\noexpand\:temp
                \noexpand\halign:TD\:MkHalign: -0 0 1 <.par del.>}%
    \egroup
    \let\hT:D=\:temp
    \def\:temp##1 ##2 ##3 {\ifnum -1=##1##2##3 \else
       <.process TD op.> \expandafter\:temp \fi}%
    \def\:tempa##1\empty{}%
    \edef\hT:D{\hT:D}}
 -_-_-

<..process TD op..>
 \ifnum \HRow=##1 \ifnum \HCol=##2 \:TDcode ##3\fi\fi
 \ifnum \HRow=##1 \ifnum    0=##2 \:TDcode ##3\fi\fi
 \ifnum     0=##1 \ifnum \HCol=##2 \:TDcode ##3\fi\fi
 \ifnum     0=##1 \ifnum    0=##2 \:TDcode ##3\fi\fi
 -_-_-

<..html blocks for halign tables..>+
 \def\:TDcode#1{<.process TD code.>\EndTD:CLASS}
                              \catcode‘\_=13  \catcode‘\^=13
 \pend:defI\:TDcode{\TD:CLASS}%
 \let\:temp=\relax \let\:tempa=\relax
 \edef\no:actv{\let\noexpand\noexpand\noexpand^=\:temp
    \let\noexpand\noexpand\noexpand_=\:tempa}
                               \catcode‘\_=8  \catcode‘\^=7
 \def\:temp{^}  \def\:tempa{_}
 \edef\no:actv{\no:actv}
 -_-_-

<..html blocks for halign tablesNOOO..>
 \def\:TDcode#1{<.process TD code.>\EndTD:CLASS}
                              \catcode‘\_=13  \catcode‘\^=13
 \pend:defI\:TDcode{\TD:CLASS
    \ifx _##1 \o:TD \expandafter\:tempa \fi
    \ifx ^##1 \t:TD \expandafter\:tempa\fi}%
 \let\:temp=\relax \let\:tempa=\relax
 \edef\no:actv{\let\noexpand\noexpand\noexpand^=\:temp
    \let\noexpand\noexpand\noexpand_=\:tempa}
                               \catcode‘\_=8  \catcode‘\^=7
 \def\:temp{^}  \def\:tempa{_}
 \edef\no:actv{\no:actv}
 -_-_-

<..process TD codeOLDTD..>
 \ifx <#1  \l:TD \expandafter\:tempa \fi
 \ifx -#1  \c:TD \expandafter\:tempa \fi
 \ifx >#1  \r:TD \expandafter\:tempa \fi
 \ifx ^#1  \t:TD \expandafter\:tempa \fi
 \ifx =#1  \b:TD \expandafter\:tempa \fi
 \ifx |#1 \m:TD \expandafter\:tempa \fi
 \ifx _#1  \o:TD \expandafter\:tempa \fi
 \ifx p#1  \p:TD \expandafter\:tempa \fi
 \expandafter#1\empty
 -_-_-

<..process TD code..>
 \expandafter
    \ifx \csname \string#1:T:D\endcsname\relax \else
      \csname \string#1:T:D\endcsname \expandafter\:tempa \fi
 \expandafter#1\empty
 -_-_-

<..html config util..>+
 \NewConfigure{halignTD}[2]{\c:def\TD:CLASS{#1}%
    \c:def\EndTD:CLASS{#2}\scan:halignTD}
 \def\scan:halignTD#1{\def\:temp{#1}\ifx \:temp\empty\else
     \expandafter \sc:halignTD\fi{#1}}
 \def\sc:halignTD#1#2{\expandafter\def\csname
    \string#1:T:D\endcsname{#2}\scan:halignTD}
 -_-_-

We could also have used \Configure{halignTD} {CLASS="NOWRAP}{"} { LEFT}{ CENTER}{ RIGHT} { TOP}{ BASELINE}{ MIDDLE}{ BOTTOM} fot DTD4.0s.

<..html config util..>+
 \NewConfigure{halignTR}[1]{\def\halignTR{#1}}
 \Configure{halignTR}{}
 -_-_-

<..html config util..>+
 \def\halignTBL{\expandafter\ifx \csname v:TBL\endcsname\relax
    \else \expandafter\ifx \csname \v:TBL :T:BL\endcsname\relax\else
        \csname \v:TBL :T:BL\endcsname
    \fi\fi}
 \NewConfigure{halignTBL}[1]{\scan:halignTBL{#1}}
 \def\scan:halignTBL#1{\def\:temp{#1}\ifx \:temp\empty\else
     \expandafter \sc:halignTBL\fi{#1}}
 \def\sc:halignTBL#1#2{\expandafter\def\csname
    \string#1:T:BL\endcsname{#2}\scan:halignTBL}
 -_-_-

Utilities

The global is because the table starts within the first entry.

<..html blocks for halign tables..>+
 \def\halign:TB#1<>#2<.par del.>{#1}
 \def\halign:TD#1<>#2<.par del.>{#2}
 -_-_-

10.3 A Realization for halign

<..html halign..>
 \:CheckOption{no-halign} \if:Option \else
    <.halign tables from TeX.>
 \fi
 -_-_-

This is the corner stone for deciding the case.

Witin Picture Environment?
Ytex:align
Nwithin edef (:halign)?
Ytex halign
Nremove ‘to dim’ (:hlgn: + hl:gn)
change catcode of # (hlg:n)
within a parameter or a def? (hal:gn)
Ytex:align + PRE
Nopen delimiter? (:Hlign)
\bgrouptex:align + PRE
{go for hypertext table

Check whether we are in \Picture environment. This can happen implicitly through environment \[...\] or through nesting in a construct that explicitly activates the picture mode.

<..halign tables from TeX..>
 \def\h:halign{\ifx \EndPicture\:Undef
                 \let\to:dim=\empty  \expandafter\:halign
             \else                    \expandafter\TeXhalign:cr\fi}
 \:CheckOption{base}  \if:Option  \else
     \def\:temp{\Protect\h:halign}
     \HLet\halign=\:temp
 \fi
 -_-_-

Check for /edef Environment

ENSURE that for cases that reduce to \TeXhalign:cr the macro get into edef.

<..halign tables from TeX..>+
 \let\r:lax=\relax
 \def\r:relax{\r:lax}
 \let\rl:x=\relax
 \def\:halign{%
    \let\rl:x=\r:relax
    \ifx \rl:x\r:relax  \expandafter\nodim:hlgn: halign not in edef
    \else               \expandafter\TeXhalign:cr   halign in edef
    \fi
 }
 -_-_-

Remove Dimension

Remove the dimension in case of \halign to dim{...} or \halign spread dim{...} and store in \to:dim. The dimension can be nested within another macro

<..halign tables from TeX..>+
 \def\nodim:hlgn:{\futurelet\:temp\hl:gn}
 \def\hl:gn{\ifx   \:temp\bgroup      \let\:tempa=\hlg:n
    \else \def\:tempa##1{\append:def\to:dim{##1}\nodim:hlgn:}\fi
    \:tempa}
 -_-_-

Without recording, and using the dimension, some pictures can get corrupted. For instance, an overlap of index with the picture may [occur]

Check for Embedded Def

Within macros and parameters, and definitions, the catcode of characters in general, and # in particular, can’t change. Hence, in such cases @2 is empty.

<..halign tables from TeX..>+
                               \catcode‘\#=13  \catcode‘\~=6
 \def\hlg:n{\begingroup  \catcode‘\#=13 \let#=\relax \hal:gn}%
 <.process pattern of halign tbl.>
 <.halign defs in catcode 13.>
                               \catcode‘\#=6  \catcode‘\~=13
 -_-_-

If catcodes don’t change, we can’t get the catcode 13 for processing the parameters, and the empty flag comes up.

<..halign defs in catcode 13..>
 \long\def\hal:gn~1{\p:lgn~1#<.par del.>%
    \ifx \:temp\empty
        <.embedded halign.>%
    \else \def\:temp{\endgroup\:hlign{~1}}\fi   \:temp}
 \long\def\p:lgn~1#~2<.par del.>{\def\:temp{~2}}
 -_-_-

/halign Not Within Parameters

By now we know that we are not within a picture or embeded in other macro or a parameter, and that we have \halign\bgroup...\egroup or \halign{...}. We are going to scan \bgroup or {...}.

<..halign tables from TeX..>+
 \long\def\:hlign#1{%
     \def\:temp{#1}\def\:tempa{\bgroup}\ifx \:temp\:tempa
        \endgroup  <.halign into pre.>%
          \expand:after{\HRestore\noalign \TeXhalign:cr\bgroup}%
     \else <.halign into MkHalign.>%
     \fi}
 -_-_-

<..halign into pre..>
 \:warning{\noexpand\halign translated into linear text}%
 -_-_-

In the above if statement, \expandafter does not work for nested halign in the true part.

If we scan \bgroup we are going after all to use the original definition of \halign. Otherwise, we are going for \HTable, and for such a case we want the following environment. The variable # controls where patterns should be included in entries and it is used for spliting the patterns into the two parameters of \HTableScript.

Embedded /halign

The \halign are transformed into pictures or \TeXhalign:cr.

We now have a command of the form \halign\bgroup... or a break up on a case of the form \halign{...body.... The parameter ~1 is either \bgroup or ...body.... If we are lucky, the body doesn’t start with a # or \bgroup.

<..embedded halign..>
 \expandafter\chs:halgn\string ~1<.par del.>%
 \:tempb{%
    \csname a:embedded-halign\endcsname
       \ifmmode
         \vbox{<.recall sharp.>$$\TeXhalign:cr \to:dim{~1}$$}%
       \else \vbox{<.recall sharp.>\TeXhalign:cr \to:dim{~1}}\fi
       \:nopartrue
    \csname b:embedded-halign\endcsname
  }%
 \let\:temp=\endgroup
 \:tempb<.par del.>%
 \:tempb\:temp{\endgroup
    <.halign into pre.>%
    \HRestore\noalign  \TeXhalign:cr~1}\:tempa<.par del.>%
 -_-_-

<..halign tables from TeX..>+
 \NewConfigure{embedded-halign}{2}
 \Configure{embedded-halign}
     {\expand:after{\Picture+}\pic:hlng{ \a:@Picture{pic-halign}}}
     {\EndPicture}
 -_-_-

The \vbox{|<recall sharp|>\TeXhalign:cr \to:dim{@1}} is needed to keep the picture in one page. Without this we get from tex4ht.c complaints of mismatches \specals{+} (due to split over pages?).

An \halign{...} can be in math mode $$....$$, but not within inline math mode. If it is there, there are quite a few restctions (not clear of which kind) on what can appear in the math code outside the \halign. Hence, we put everything into math mode in a sepearte box just for an extra precaution.

\TeXhalign:cr reestablishes the meaning of \cr and \crcr for picture-mode, but not for the second one. The later case may cause problems.

Pictures might be called for also with # having catcode 13, as is the case with \halign{\empty{#}&&{#}\cr phi&varphi\cr} (but not with \halign{\empty #&& #\cr phi&varphi\cr}). In this case, the scanning in \p:lgn@1#|<par del|>% can’t detect the sharp characters that are embedded in braces. That is, a neccesary condition for getting tabular representation is at least one # out of braces, to ensure that such characters can get catcode 13.

<..recall sharp..>
 \Rc:sharp
 -_-_-

<..halign tables from TeX..>+
 \catcode‘\#=13
 \def\Rc:sharp{\let#=\sv:sharp}
 \catcode‘\#=6
 \def\:temp{\let\sv:sharp=##}\:temp
 -_-_-

Utilities fo Embedded /halign

<..halign tables from TeX..>+
 \def\chs:halgn#1{\def\:temp{#1}%
    \def\:tempa##1##2##3##4##5{\def\:tempa{##1}\def\:tempb{##2}%
       \def\:tempc{##3}\def\:tempd{##4}\def\:tempe{##5}}%
    \expandafter\:tempa\string\bgro
    \ifx \:temp\:tempa \expand:after{\expandafter\try:b\string}%
    \else              \expandafter\brc:halign \fi}
 \def\try:b{\try:ch\:tempb\try:g}
 \def\try:g{\try:ch\:tempc\try:r}
 \def\try:r{\try:ch\:tempd\try:o}
 \def\try:o#1{\def\:temp{#1}%
    \ifx \:temp\:tempe \def\:tempb{<.bgroup halign.>}%
    \else  \let\:temp=\empty
           \def\:tempb{<.braced halign.>}\fi
    <.tempa = consume the rest of @1.>\:tempa}
 \def\try:ch#1#2#3{\def\:temp{#3}%
    \ifx \:temp#1 \expand:after{\expandafter#2\string}%
    \else              \expandafter\brc:halign \fi}
 -_-_-

<..halign tables from TeX..>+
 \def\brc:halign{%
    \let\:temp=\empty   \def\:tempb{<.braced halign.>}%
    <.tempa = consume the rest of @1.>\:tempa}
 -_-_-

<..tempa = consume the rest of @1..>
 \long\def\:tempa##1<.par del.>{}%
 -_-_-

<..bgroup halign..>
 \let\:tempb=\def\:tempa
 -_-_-

<..braced halign..>
 \let\:tempb=\:tempa
 -_-_-

/halign into <PRE>

We temporariliy get out from display mode, because we want the <PRE> before \halign and nothing is allowed before \halign in display mode. The enclosure within table is to group the content for protection from embedding <CENTER> commands and the like.

/halign into /MkHalign

We now have a command of the form \halign{....} or a break up on a case of the form \halign{....\egroup.

<..halign into MkHalign..>
 \let\tabskip=\tmp:dim    \let\hrulefill=\empty
 \let\hidewidth=\empty
 \expand:after{\h:align#1\cr<.par del.>#1<.par del.>}%
 -_-_-

The pattern of \halign can end with a \cr or a \crcr. We first check whether \cr present, and if so whether or not it is preceded by a \crcr.

<..halign tables from TeX..>+
 \catcode‘\#=13 \catcode‘\@=6
 \long\def\h:align@1\cr@2<.par del.>{\def\:temp{@2}\ifx \:temp\empty
    \expandafter\h:alignII \else \crcr:align@1\crcr<.par del.>\fi}
 \def\crcr:align@1\crcr@2<.par del.>{\def\:temp{@2}\ifx \:temp\empty
    \expandafter\expandafter\expandafter\h:alignI \else
    \expandafter\expandafter\expandafter\h:alignII \fi}
 \long\def\h:alignI@1\cr@2<.par del.>{%
    \SaveMkHalignConfig <.halign configuration for halign.>%
    \MkHalign#{@1}@2\EndMkHalign \RecallMkHalignConfig}
 \def\h:alignII@1\crcr{\h:alignI@1\cr}
 \catcode‘\#=6 \catcode‘\@=11
 -_-_-

<..halign configuration for halign..>
 \Configure{MkHalign}{\hlg:a}{\hlg:b}
    \hlg:c\hlg:d{\hlg:e\RecallMkHalignConfig}\hlg:f
 -_-_-

<..html config util..>+
 \NewConfigure{halign}[6]{\c:def\hlg:a{#1}%
    \c:def\hlg:b{#2}\c:def\hlg:c{#3}\c:def\hlg:d{#4}%
    \c:def\hlg:e{#5}\c:def\hlg:f{#6}}
 \NewConfigure{pic-halign}[1]{\def\pic:hlng{#1}}
 -_-_-

<..math config util..>+
 \def\:halign:{<>}
 -_-_-

We must put in at least the <>.

noalign

In TeX4ht \everycr\noalign causes a loop because the definition of \halign includes \cr. We declare a loop when 100 cycles are encountered. Another possible problem is due to \hline which contains noalign at its start.[more]

If we want to go for optional \noalign with response to a parameter in \Preamble, we need to take care of places that needs it html interpretation (in tables?).

<..halign tables from TeX..>+
 <.noalign.>
 -_-_-

<..noalign..>
 \HAssign\noalign:N=0
 \def\:tempc#1{<.cycle protection fo noalign.>%
    \vtop{\IgnorePar\a:noalign\vtop{\IgnorePar#1}\b:noalign}\cr
    \global\tmp:toks=\everycr \global\everycr{}\cr
    \o:noalign:{\global\everycr=\tmp:toks \gHAssign\noalign:N=0 }%
  }
 \HLet\noalign=\:tempc
 <.another alternative for noalign.>
 -_-_-

We probbaly can remove the cycle protection.

The internal \top is to ensure vertical mode for material which assumes it. In the extreem, that also prevents infinite loops.

<..shared config..>+
 \NewConfigure{noalign-}[2]{\c:def\a:noalign{#1}\c:def\b:noalign{#1}}
 -_-_-

Any reason left for keeping both cases?

<..shared config..>+
 \:CheckOption{no-halign} \if:Option \else
     \NewConfigure{noalign}{2}
 \fi
 -_-_-

The \Protect is needed, for instance, in \endalignat of amstex.tex during a pre-edef stage.

The looping can happen in \displaylines, \eqalignno, and \leqalignno due to the first command below (\@align?.).

<..cycle protection fo noalign..>
 \gHAdvance\noalign:N by 1
    \ifnum \noalign:N>100
       \global\let\noalign=\o:noalign:
       \:warning{TeX4ht can’t handle
                   \string\everycr{...\string\noalign...}}%
    \fi
 -_-_-

Removed \let\dotfill|=\empty. Did I have any reason to put it there in first place?