summaryrefslogtreecommitdiff
path: root/macros/luatex/optex/table.opm
blob: c210c75b34cfb5d03d6ecc7d8cffcca701fdd2bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
%% This is part of OpTeX project, see http://petr.olsak.net/optex

\_codedecl \table {Basic macros for OpTeX <2020-03-13>} % preloaded in format

   \_doc -----------------------------
   The result of `\table` is inserted into `\_tablebox`. You can change
   default value if you want `\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 `\_tablinspace` is implemented by enlarging given `\tabstrut`
   by desired dimension (height and depth too) and by setting
   `\_lineskip=-2\_tablinspace`. So, 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` <declaration> to `\halign` <declaration>.
   The result is stored into `\_tbdata` tokens list. For example, the `\_scandata` creates
   following result when <declaration>=`|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 `\_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{\_toksapp\_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 defined here.
   You can define more such leeters by `\def\_tabdeclare<letter>{...}` for a non-parametric 
   letter and by `\def\_paramtabdeclare<letter>{...}` for a letter with a parameter.
   The double hash `##` must be in the definition, it is replaced by a real table item data.
   \_cod -----------------------------

\_def\_tabdeclarec{\_the\_tabiteml\_hfil##\_unsskip\_hfil\_the\_tabitemr}
\_def\_tabdeclarel{\_the\_tabiteml##\_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 and `\tskip <dimen>` 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[<declaration>]{<text>}` macro generates similar `\omit\span\omit\span` 
   sequence as plain \TeX/ macro `\multispan`. Moreover, it uses `\_scantabdata` to
   convert <declaration> 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\_crcr}\_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.4pt. 
   \_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 \"`\vbox` in `\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 % -------------------------------------