%% This is part of OpTeX project, see http://petr.olsak.net/optex \_codedecl \table {Basic macros for OpTeX <2020-04-10>} % preloaded in format \_doc ----------------------------- The result of the \`\table``{}{}` macro is inserted into `\_tablebox`. You can change default value if you want by `\let\_tablebox=\vtop` or `\let\_tablebox=\relax`. \_cod ----------------------------- \_let\_tablebox=\_vbox \_doc ----------------------------- Categories (for example of `|` character) have to be normal when reading `\table` parameters. \_cod ----------------------------- \_def\_table{\_tablebox\_bgroup \_catcodetable\_optexcatcodes \_tableA} \_public \table ; \_doc ----------------------------- The \^`\tablinespace` is implemented by enlarging given \^`\tabstrut` by desired dimension (height and depth too) and by setting `\_lineskip=-2\_tablinespace`. Normal table rows (where no `\hrule` is between them) have normal baseline distance. \_cod ----------------------------- \_def\_tableA#1{% \_the\_thistable \_global\_thistable={}% \_ea\_ifx\_ea^\_the\_tabstrut^\_setbox\_tstrutbox=\_null \_else \_setbox\_tstrutbox=\_hbox{\_the\_tabstrut}% \_setbox\_tstrutbox=\_hbox{\_vrule width0pt height\_dimexpr\_ht\_tstrutbox+\_tablinespace depth\_dimexpr\_dp\_tstrutbox+\_tablinespace}% \_offinterlineskip \_lineskip=-2\_tablinespace \_fi \_colnum=0 \_def\_tmpa{}\_tabdata={}\_scantabdata#1\_relax \_the\_everytable \_tableB } \_def\_tableB#1{\_halign\_ea{\_the\_tabdata\_cr#1\_crcr}\_egroup} \_newbox\_tstrutbox % strut used in table rows \_newtoks\_tabdata % the \halign declaration line \_newcount\_colnum % number of columns \_doc ----------------------------- The \`\_scantabdata` converts `\table`'s `` to `\halign` ``. The result is stored into \`\_tabdata` tokens list. For example, the following result is generated when `=|cr||cl|`. \begtt tabdata: \_vrule\_the\_tabiteml\_hfil#\_unsskip\_hfil\_the\_tabitemr\_tabstrutA &\_the\_tabiteml\_hfil#\_unsskip\_the\_tabitemr \_vrule\_kern\_vvkern\_vrule\_tabstrutA &\_the\_tabiteml\_hfil#\_unsskip\_hfil\_the\_tabitemr\_tabstrutA &\_the\_tabiteml#\_unsskip\_hfil\_the\_tabitemr\_vrule\_tabstrutA ddlinedata: &\_dditem &\_dditem\_vvitem &\_dditem &\_dditem \endtt The second result in the \`\_ddlinedata` macro is a teplate of one row of the table used by \^`\crli` macro. \_cod ----------------------------- \_def\_scantabdata#1{\_let\_next=\_scantabdata \_ifx\_relax#1\_let\_next=\_relax \_else\_ifx|#1\_addtabvrule \_else\_ifx(#1\_def\_next{\_scantabdataE}% \_else\_isinlist{123456789}#1\_iftrue \_def\_next{\_scantabdataC#1}% \_else \_ea\_ifx\_csname _tabdeclare#1\_endcsname \_relax \_ea\_ifx\_csname _paramtabdeclare#1\_endcsname \_relax \_opwarning{tab-declarator "#1" unknown, ignored}% \_else \_def\_next{\_ea\_scantabdataB\_csname _paramtabdeclare#1\_endcsname}\_fi \_else \_def\_next{\_ea\_scantabdataA\_csname _tabdeclare#1\_endcsname}% \_fi\_fi\_fi\_fi\_fi \_next } \_def\_scantabdataA#1{\_addtabitem \_ea\_addtabdata\_ea{#1\_tabstrutA}\_scantabdata} \_def\_scantabdataB#1#2{\_addtabitem\_ea\_addtabdata\_ea{#1{#2}\_tabstrutA}\_scantabdata} \_def\_scantabdataC {\_def\_tmpb{}\_afterassignment\_scantabdataD \_tmpnum=} \_def\_scantabdataD#1{\_loop \_ifnum\_tmpnum>0 \_advance\_tmpnum by-1 \_addto\_tmpb{#1}\_repeat \_ea\_scantabdata\_tmpb} \_def\_scantabdataE#1){\_addtabdata{#1}\_scantabdata} \_def\_addtabitem{\_ifnum\_colnum>0 \_addtabdata{&}\_addto\_ddlinedata{&\_dditem}\_fi \_advance\_colnum by1 \_let\_tmpa=\_relax} \_def\_addtabdata#1{\_tabdata\_ea{\_the\_tabdata#1}} \_def\_addtabvrule{% \_ifx\_tmpa\_vrule \_addtabdata{\_kern\_vvkern}% \_ifnum\_colnum=0 \_addto\_vvleft{\_vvitem}\_else\_addto\_ddlinedata{\_vvitem}\_fi \_else \_ifnum\_colnum=0 \_addto\_vvleft{\_vvitemA}\_else\_addto\_ddlinedata{\_vvitemA}\_fi\_fi \_let\_tmpa=\_vrule \_addtabdata{\_vrule}% } \_def\_tabstrutA{\_copy\_tstrutbox} \_def\_vvleft{} \_def\_ddlinedata{} \_doc ----------------------------- The default \"declaration letters" `c`, `l`, `r` and `p` are declared. by `\def\_tabdeclare{...}` for a non-parametric letter and by `\def\_paramtabdeclare{...}` for a letter with a parameter. The double hash `##` must be in the definition, it is replaced by a real table item data. All items are put in group because of `\aftergroup` can be used (from `\localcolors` for example). You can declare more such \"declaration letters" if you want. \_cod ----------------------------- \_def\_tabdeclarec{{\_the\_tabiteml\_hfil##\_unsskip\_hfil\_the\_tabitemr}} \_def\_tabdeclarel{{\_the\_tabiteml\_relax##\_unsskip\_hfil\_the\_tabitemr}} \_def\_tabdeclarer{{\_the\_tabiteml\_hfil##\_unsskip\_the\_tabitemr}} \_def\_paramtabdeclarep#1{{\_the\_tabiteml \_vtop{\_hsize=#1\_relax \_baselineskip=\_normalbaselineskip \_lineskiplimit=0pt \_noindent##\_unsskip\_lower\_dp\_tstrutbox\hbox{}}\_the\_tabitemr}} \_doc ----------------------------- User puts optional spaces around the table item typically, i.\,e.\ he/she writes `& text &` instead `&text&`. The left space is ignored by internal \TeX/ algorithm but the right space must be removed by macros. This is a reason why we reccomend to use \`\_unsskip` after each `##` in your definition of \"declaration letters". This macro isn't only the primitive `\unskip` because we allow usage of plain \TeX/ `\hideskip` macro: `&\hideskip text\hideskip&`. \_cod ----------------------------- \_def\_unsskip{\_ifdim\_lastskip>0pt \_unskip\_fi} \_doc ----------------------------- The family of `\_cr*` macros \`\crl`, \`\crll`, \`\crli`, \`\crlli`, \`\crlp` and \`\tskip` `` is implemented here. The \`\_zerotabrule` is used in order to suppress the negative `\lineskip` declared by \^`\tablinespace`. \_cod ----------------------------- \_def\_crl{\_crcr\_noalign{\_hrule}} \_def\_crll{\_crcr\_noalign{\_hrule\_kern\_hhkern\_hrule}} \_def\_zerotabrule {\_noalign{\_hrule height0pt width0pt depth0pt}} \_def\_crli{\_crcr \_zerotabrule \_omit \_gdef\_dditem{\_omit\_tablinefil}\_gdef\_vvitem{\_kern\_vvkern\_vrule}\_gdef\_vvitemA{\_vrule}% \_vvleft\_tablinefil\_ddlinedata\_crcr \_zerotabrule} \_def\_crlli{\_crli\_noalign{\_kern\_hhkern}\_crli} \_def\_tablinefil{\_leaders\_hrule\_hfil} \_def\_crlp#1{\_crcr \_zerotabrule \_noalign{\_kern-\_drulewidth}% \_omit \_xdef\_crlplist{#1}\_xdef\_crlplist{,\_expandafter}\_expandafter\_crlpA\_crlplist,\_end,% \_global\_tmpnum=0 \_gdef\_dditem{\_omit\_crlpD}% \_gdef\_vvitem{\_kern\_vvkern\_kern\_drulewidth}\_gdef\_vvitemA{\_kern\_drulewidth}% \_vvleft\_crlpD\_ddlinedata \_global\_tmpnum=0 \_crcr \_zerotabrule} \_def\_crlpA#1,{\_ifx\_end#1\_else \_crlpB#1-\_end,\_expandafter\_crlpA\_fi} \_def\_crlpB#1#2-#3,{\_ifx\_end#3\_xdef\_crlplist{\_crlplist#1#2,}\_else\_crlpC#1#2-#3,\_fi} \_def\_crlpC#1-#2-#3,{\_tmpnum=#1\_relax \_loop \_xdef\_crlplist{\_crlplist\_the\_tmpnum,}\_ifnum\_tmpnum<#2\_advance\_tmpnum by1 \_repeat} \_def\_crlpD{\_global\_advance\_tmpnum by1 \_edef\_tmpa{\_noexpand\_isinlist\_noexpand\_crlplist{,\_the\_tmpnum,}}% \_tmpa\_iftrue \_kern-\_drulewidth \_tablinefil \_kern-\_drulewidth\_else\_hfil \_fi} \_def\_tskip{\_afterassignment\_tskipA \_tmpdim} \_def\_tskipA{\_gdef\_dditem{}\_gdef\_vvitem{}\_gdef\_vvitemA{}\_gdef\_tabstrutA{}% \_vbox to\_tmpdim{}\_ddlinedata \_crcr \_zerotabrule \_noalign{\_gdef\_tabstrutA{\_copy\_tstrutbox}}} \_public \crl \crll \crli \crlli \crlp \tskip ; \_doc ----------------------------- The \`\mspan``[]{}` macro generates similar `\omit\span\omit\span` sequence as plain \TeX/ macro `\multispan`. Moreover, it uses \^`\_scantabdata` to convert `` from `\table` syntax to `\halign` syntax. \_cod ----------------------------- \_def\_mspan{\_omit \_tabdata={\_tabstrutA}\_let\_tmpa=\_relax \_afterassignment\_mspanA \_mscount=} \_def\_mspanA[#1]#2{\_loop \_ifnum\_mscount>1 \_cs{_span}\_omit \_advance\_mscount-1 \_repeat \_colnum=0 \_def\_tmpa{}\_tabdata={}\_scantabdata#1\_relax \_setbox0=\_vbox{\_halign\_expandafter{\_the\_tabdata\_cr#2\_cr}\_global\_setbox8=\_lastbox}% \_setbox0=\_hbox{\_unhbox8 \_unskip \_global\_setbox8=\_lastbox}% \_unhbox8 \_ignorespaces} \_public \mspan ; \_doc ----------------------------- The parameters of primitive `\vrule` and `\hrule` keeps the rule \"last wins". If we re-define `\hrule` to `\_orihrule height1pt` then each usage of redefined `\hrule` uses `1pt` height if this parameter isn't overwriten by another following `height` parameter. This principle is used for settings another default rule thickness than 0.4\,pt by the macro \`\rulewidth`. \_cod ----------------------------- \_newdimen\_drulewidth \_drulewidth=0.4pt \_let\_orihrule=\_hrule \_let\_orivrule=\_vrule \_def\_rulewidth{\_afterassignment\_rulewidthA \_drulewidth} \_def\_rulewidthA{\_edef\_hrule{\_orihrule height\_drulewidth}% \_edef\_vrule{\_orivrule width\_drulewidth}% \_let\_rulewidth=\_drulewidth \_public \vrule \hrule \rulewidth;} \_public \rulewidth ; \_doc ----------------------------- The \`\frame``{}` uses \"\code{\\vbox} in \code{\\vtop}" trick in order to keep the baseline of the internal text at the same level as outer baseline. User can write `\frame{abcxyz}` in normal paragraph line, for example and gets the expected result: \frame{abcxyz}. The internal margins are set by `\vvkern` and `\hhkern` parameters. \_cod ----------------------------- \_long\_def\_frame#1{% \_hbox{\_vrule\_vtop{\_vbox{\_hrule\_kern\_vvkern \_hbox{\_kern\_hhkern\_relax#1\_kern\_hhkern}% }\_kern\_vvkern\_hrule}\_vrule}} \_public \frame ; \_endcode % ------------------------------------- 2020-04-10 second group for items in order to \localcolors