summaryrefslogtreecommitdiff
path: root/macros/luatex/optex/base/table.opm
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/optex/base/table.opm')
-rw-r--r--macros/luatex/optex/base/table.opm325
1 files changed, 287 insertions, 38 deletions
diff --git a/macros/luatex/optex/base/table.opm b/macros/luatex/optex/base/table.opm
index 5fa252eeba..4aaaa9a442 100644
--- a/macros/luatex/optex/base/table.opm
+++ b/macros/luatex/optex/base/table.opm
@@ -1,6 +1,6 @@
%% This is part of OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \table {Basic macros for OpTeX <2020-04-10>} % preloaded in format
+\_codedecl \table {Basic macros for OpTeX <2020-05-20>} % preloaded in format
\_doc -----------------------------
The result of the \`\table``{<declaration>}{<data>}` macro is inserted into
@@ -11,21 +11,36 @@
\_let\_tablebox=\_vbox
\_doc -----------------------------
- Categories (for example of `|` character) have to be normal when reading
- `\table` parameters.
+ We save the `to<size>` or `pxto<size>` to `#1` and \`\_tableW` sets the
+ `to<size>` to the \`\_tablew` macro.
+ If `pxto<size>` is used then `\_tablew` is empty and `\_tmpdim` includes
+ given <size>. The `\_ifpxto` returns true in this case.
+
+ The `\table` continues by reading `{<declaration>}` in the \^`\_tableA` macro.
+ Catcodes (for example the `|` character) have to be normal when reading
+ `\table` parameters. This is the reason why we use `\catcodetable` here.
\_cod -----------------------------
-\_def\_table{\_tablebox\_bgroup \_catcodetable\_optexcatcodes \_tableA}
+\_newifi \_ifpxto
+\_def\_table#1#{\_tablebox\_bgroup \_tableW#1\_empty\_end
+ \_bgroup \_catcodetable\_optexcatcodes \_tableA}
+\_def\_tableW#1#2\_end{\_pxtofalse
+ \_ifx#1\_empty \_def\_tablew{}\_else
+ \_ifx#1p \_def\_tablew{}\_tableWx#2\_end \_else \_def\_tablew{#1#2}\_fi\_fi}
+\_def\_tableWx xto#1\_end{\_tmpdim=#1\_relax \_pxtotrue}
\_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.
+ between them) have normal baseline distance.\nl
+ The \`\_tableA``{<declaration>}` macro scans the `<declaration>` by
+ `\_scantabdata#1\_relax` and continues by reading `{<data>}` by
+ the \^`\_tableB` macro.
\_cod -----------------------------
-\_def\_tableA#1{%
+\_def\_tableA#1{\_egroup
\_the\_thistable \_global\_thistable={}%
\_ea\_ifx\_ea^\_the\_tabstrut^\_setbox\_tstrutbox=\_null
\_else \_setbox\_tstrutbox=\_hbox{\_the\_tabstrut}%
@@ -35,17 +50,67 @@
\_offinterlineskip
\_lineskip=-2\_tablinespace
\_fi
- \_colnum=0 \_def\_tmpa{}\_tabdata={}\_scantabdata#1\_relax
+ \_colnum=0 \_let\_addtabitem=\_addtabitemx
+ \_def\_tmpa{}\_tabdata={\_colnum1\_relax}\_scantabdata#1\_relax
\_the\_everytable \_tableB
}
-\_def\_tableB#1{\_halign\_ea{\_the\_tabdata\_cr#1\_crcr}\_egroup}
+
+ \_doc -----------------------------
+ The \`\_tableB``{<data>}` saves `<data>` to `\_tmpb`
+ and does four \^`\replstring`s to prefix each macro \^`\crli` (etc.)
+ by `\_crcr`. The reason is: we want to use macros which scan its parameter
+ to the delimeiter written in right part of table item declaration.
+ See \^`\fS` for example. The `\crcr` cannot be hidden in other macro in such case.
+
+ The `\tabskip` value is saved for places between columns
+ into the \`\_tabskipmid` macro. Then it runs
+ \begtt \catcode`\<=13
+ \tabskip=\tabskipl \halign{<converted declaration>\tabskip=\tabskipr \cr <data>\crcr}
+ \endtt
+ This sets the desired boundary values of `\tabskip`. The
+ \"between-columns" values are set as `\tabskip=`\^`\_tabskipmid` in the
+ `<converted declaration>` immediately after each column declarator.
+
+ If `pxto` keyword was used, then we set the virtual unit \^`\tsize` to
+ `\hsize` first. Then the first attempt of the table is created in box 0.
+ Then the \^`\tsize` is re-calculated using `\wd0` and the real table is
+ printed by `\halign` in the second pass.
+
+ If no `pxto` keyword was used, then we print the table using `\halign`
+ directly. The \^`\_tablew` macro is nonempty if the `to` keyword was used.
+
+ Because the color selector with `\aftergroup` can be used inside the
+ table item, we must to create second real group for each table item.
+ This is reason why we start `<converted declaration>` by `\bgroup` and we
+ end it by `\egroup` in the \`\_tableC` macro. Each `&` character
+ is stored as `\egroup&\bgroup` in `<converted declaration>`. The
+ `\halign\_tablew\_tableC` really does:
+ \begtt \catcode`\<=13
+ \halign\_tablew{\bgroup<converted declaration>\egroup\tabskip=\tabskipr \cr<data>\crcr}
+ \endtt
+ \relax
+ \_cod -----------------------------
+
+\_def\_tableB#1{\_def\_tmpb{#1}%
+ \_replstring\_tmpb{\crli}{\_crcr\crli}\_replstring\_tmpb{\crll}{\_crcr\crll}%
+ \_replstring\_tmpb{\crlli}{\_crcr\crlli}\_replstring\_tmpb{\crlp}{\_crcr\crlp}%
+ \_edef\_tabskipmid{\_the\_tabskip}\_tabskip=\_tabskipl
+ \_ifpxto
+ \_tsize=\_hsize \_setbox0 = \_vbox{\_halign \_tableC}%
+ \_tsize=\_dimexpr\_hsize-(\_wd0-\_tmpdim)\_relax
+ \_setbox0=\_null \_halign \_tableC
+ \_else
+ \_halign\_tablew \_tableC
+ \_fi \_egroup
+}
+\_def\_tableC{\_ea{\_ea\_bgroup\_the\_tabdata\_egroup\_tabskip=\_tabskipr\_cr\_tmpb\_crcr}}
+
\_newbox\_tstrutbox % strut used in table rows
\_newtoks\_tabdata % the \halign declaration line
-\_newcount\_colnum % number of columns
\_doc -----------------------------
- The \`\_scantabdata` converts `\table`'s `<declaration>` to
- `\halign` `<declaration>`.
+ The \`\_scantabdata` macro converts `\table`'s `<declaration>` to
+ `\halign` `<converted declaration>`.
The result is stored into \`\_tabdata` tokens list.
For example, the
following result is generated when `<declaration>=|cr||cl|`.
@@ -57,7 +122,7 @@
&\_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
+ The second result in the \`\_ddlinedata` macro is a template of one row of the table
used by \^`\crli` macro.
\_cod -----------------------------
@@ -65,25 +130,57 @@
\_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
+ \_else\_ifx:#1\_def\_next{\_scantabdataF}%
+ \_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
+ \_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
+ \_else \_def\_next{\_ea\_scantabdataA\_csname _tabdeclare#1\_endcsname}%
+ \_fi\_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\_scantabdataA#1{\_addtabitem
+ \_ea\_addtabdata\_ea{#1\_tabstrutA \_tabskip\_tabskipmid}\_scantabdata}
+\_def\_scantabdataB#1#2{\_addtabitem
+ \_ea\_addtabdata\_ea{#1{#2}\_tabstrutA \_tabskip\_tabskipmid}\_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\_scantabdataF {\_addtabitem\_def\_addtabitem{\_let\_addtabitem=\_addtabitemx}\_scantabdata}
-\_def\_addtabitem{\_ifnum\_colnum>0 \_addtabdata{&}\_addto\_ddlinedata{&\_dditem}\_fi
- \_advance\_colnum by1 \_let\_tmpa=\_relax}
+ \_doc -----------------------------
+ The \`\_addtabitemx` adds the boundary code (used between columns)
+ to the <converted declaration>. This code is
+ `\egroup &\bgroup \colnum=<value>\relax`. You can get the current number of
+ column from the \`\colnum` register, but you cannot write
+ `\the\colnum` as the first object in a <data> item because `\halign`
+ first expands the front of the item and the left part of the declaration
+ is processed after this. Use `\relax\the\colnum` instead. Or you can
+ write:
+ \begtt
+ \def\showcolnum{\ea\def\ea\totcolnum\ea{\the\colnum}\the\colnum/\totcolnum}
+ \table{ccc}{\showcolnum & \showcolnum & \showcolnum}
+ \endtt
+ This example prints 1/3 \ 2/3 \ 3/3, because the value of the `\colnum` is
+ equal to the total number of columns before left part of the column declaration
+ is processed.
+ \_cod -----------------------------
+
+\_newcount\_colnum % number of current column in the table
+\_public \colnum ;
+
+\_def\_addtabitemx{\_ifnum\_colnum>0
+ \_addtabdata{\_egroup &\_bgroup}\_addto\_ddlinedata{&\_dditem}\_fi
+ \_advance\_colnum by1 \_let\_tmpa=\_relax
+ \_ifnum\_colnum>1 \_ea\_addtabdata\_ea{\_ea\_colnum\_the\_colnum\_relax}\_fi}
\_def\_addtabdata#1{\_tabdata\_ea{\_the\_tabdata#1}}
+
+ \_doc -----------------------------
+ This code converts `||` or `|` from `\table` <declaration> to the <converted declaration>.
+ \_cod -----------------------------
+
\_def\_addtabvrule{%
\_ifx\_tmpa\_vrule \_addtabdata{\_kern\_vvkern}%
\_ifnum\_colnum=0 \_addto\_vvleft{\_vvitem}\_else\_addto\_ddlinedata{\_vvitem}\_fi
@@ -95,32 +192,49 @@
\_def\_ddlinedata{}
\_doc -----------------------------
- The default \"declaration letters" `c`, `l`, `r` and `p` are declared.
- by `\def\_tabdeclare<letter>{...}` for a non-parametric
- letter and by `\def\_paramtabdeclare<letter>{...}` for a letter with a parameter.
+ The default \"declaration letters" `c`, `l`, `r` and `p` are declared
+ by setting \`\tabdeclarec`, \`\tabdeclarel`, \`\tabdeclarer` and
+ \`\paramtabdeclarep` macros. In general, define
+ `\def\_tabdeclare<letter>{...}` for a non-parametric
+ letter and `\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.
- 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
+\_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}}
+ \_lineskiplimit=0pt \_noindent##\_unsskip
+ \_ifvmode\_vskip\_dp\_tstrutbox \_else\_lower\_dp\_tstrutbox\_hbox{}\_fi}\_the\_tabitemr}
\_doc -----------------------------
- User puts optional spaces around the table item typically, i.\,e.\ he/she writes
+ 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
+ the right space must be removed by macros. This is a reason why we recommend 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}
+\_def\_unsskip{\_ifmmode\_else\_ifdim\_lastskip>0pt \_unskip\_fi\_fi}
+
+ \_doc -----------------------------
+ The \`\fL`, \`\fR`, \`\fC` and \`\fX` macros only does a special parameters settings
+ for paragraph building algorithm. The \`\fS` prints the paragraph into
+ box 0 first, measures the number of lines by the `\prevgraf` primitive
+ and use (or don't use) `\hfil` (for centering) before the first line.
+ \_cod -----------------------------
+
+\_let\_fL=\_raggedright
+\_def\_fR{\_leftskip=0pt plus 1fill \_relax}
+\_def\_fC{\_leftskip=0pt plus1fill \_rightskip=0pt plus 1fill \_relax}
+\_def\_fX{\_leftskip=0pt plus1fil \_rightskip=0pt plus-1fil \_parfillskip=0pt plus2fil \_relax}
+\_long\_def\_fS #1\_unsskip{\_noindent \_setbox0 =\_vbox{\_noindent #1\_endgraf \_ea}%
+ \_ifnum\_prevgraf=1 \_hfil \_fi #1\_unsskip
+}
+\_public \fL \fR \fC \fX \fS ;
\_doc -----------------------------
The family of `\_cr*` macros
@@ -168,17 +282,33 @@
\_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}%
+ \_count1=\_colnum \_colnum=0 \_def\_tmpa{}\_tabdata={}\_scantabdata#1\_relax
+ \_colnum=\_count1 \_setbox0=\_vbox{\_halign\_ea{\_ea\_bgroup\_the\_tabdata\_egroup\_cr#2\_cr}%
+ \_global\_setbox8=\_lastbox}%
\_setbox0=\_hbox{\_unhbox8 \_unskip \_global\_setbox8=\_lastbox}%
\_unhbox8 \_ignorespaces}
\_public \mspan ;
\_doc -----------------------------
+ The \`\vspan``{<number>}{<text>}` implementaiton is here.
+ We need to lower the box by
+ \begtt \catcode`\<=13
+ (<number>-1)*(\ht+\dp of \tabstrut) / 2.
+ \endtt
+ The `#1` parameter must be one-digit number. If you want to set more digits
+ then use braces.
+ \_cod -----------------------------
+
+\_def\_vspan#1#2{\_vtop to 0pt{\_hbox{\_lower \_dimexpr
+ #1\_dimexpr(\_ht\_tstrutbox+\_dp\_tstrutbox)/2\_relax
+ -\_dimexpr(\_ht\_tstrutbox+\_dp\_tstrutbox)/2\_relax \_hbox{#2}}\_vss}}
+\_public \vspan ;
+
+ \_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
+ overwritten by another following `height` parameter. This principle is used for
settings another default rule thickness than 0.4\,pt by the macro
\`\rulewidth`.
\_cod -----------------------------
@@ -208,4 +338,123 @@
\_endcode % -------------------------------------
+\secc[table.bound] The boundary declarator \code{:}
+
+The `<declaration>` part of `\table{<declaration>}{<data>}` includes
+column declarators (letters) and other material: the `|` or `(<cmd>)`.
+The boundaries of columns are just before each column declarator
+(with exception of the first one) if the boundary declarator `:` is not used.
+For example, the declaration `{|c||c(xx)(yy)c}`
+should be written more exactly using the boundary declarator `:`
+by `{|c||:c(xx)(yy):c}`. But you can set these boundaries to
+another places using the boundary declarator~`:` explicitly,
+for example `{|c:||c(xx):(yy)c}`. The boundary declarator `:`
+can be used only once between each two column declarators.
+
+Each table item have its own group. The `(<cmd>)` are parts of the given
+table item (depending on the boundary declarator position).
+If you want to apply a special setting for given column, you can do this by
+`(<setting>)` followed by column declarator. But if such column is not
+first, you must use `:(<setting>)`. Example. We have three centered columns,
+the second one have to be in bold font and the third one have to be in red:
+`\table{c:(\bf)c:(\Red)c}{<data>}`
+
+\secc Usage of the \code{\\tabskip} primitive
+
+The value of `\tabskip` primitive is used between all columns of the table.
+It is glue-type, so it can be stretchable or shrinkable, see next
+section~\ref[table.w].
+
+By default, `\tabskip` is 0\,pt. It means that only \^`\tabiteml`,
+\^`\tabitemr` and `(<cmds>)` can generate visual spaces between columns. But they
+are not real spaces between columns because they are in fact the part of
+the total column width.
+
+The `\tabskip` value declared before the \^`\table` macro (or in
+\^`\everytable` or in \^`\thistable`) is used between all columns in the table.
+This value is equal for all spaces between columns. But you can set each such space
+individualy if you use `(\tabskip=<value>)` in the <declaration> immediately
+before boundary character. The boundary character represents the column pair for
+which the `\tabskip` have individual value. For example
+`c(\tabskip=5pt):r` gives `\tabskip` value betwen `c` and `r` columns.
+You need not to use boundary character explicitly, so `c(\tabskip=5pt)r` gives
+the same result.
+
+The space before first column is given by the \^`\tabskipl`
+and the space after last column is equal to \^`\tabskipr`.
+Default values are 0\,pt.
+
+Use nonzero `\tabskip` only in special applications. If `\tabskip` is
+nonzero then horizontal lines generated by \^`\crli`, \^`\crlli` and \^`\crlp`
+have another behavior than you probably expected: they are interrupted in
+each `\tabskip` space.
+
+\secc[table.w] Tables to given width
+
+There are two possibilities how to create tables to given width:
+
+\begitems
+* `\table to<size>{<declaration>}{<data>}` uses stretchability or
+ shrinkability of all spaces between columns generated by `\tabskip` value and
+ eventually by \^`\tabskipl`, \^`\tabskipr` values. See example below.
+* `\table pxto<size>{<declaration>}{<data>}` expands the columns declared
+ by `p{<size>}`, if the `<size>` is given by a virtual \^`\tsize` unit.
+ See example below.
+\enditems
+
+Example of `\table to<size>`:
+
+\begtt \catcode`\<=13
+\thistable{\tabskip=0pt plus1fil minus1fil}
+\table to\hsize {lr}{<data>}
+\endtt
+%
+This table has its width `\hsize`. First column starts at the left boundary of
+this table and it is justified left (to the boundary). Second column ends at
+the right boundary of the table and it is justified right (to the boundary).
+The space between them are stretchable and shrinkable in order to reach
+given width `\hsize`.
+
+\medskip
+Example of `\table pxto<size>` (means \"{\bf p}aragraphs e{\bf x}panded {\bf to}"):
+
+\begtt
+\table pxto\hsize {|c|p{\tsize}|}{\crl
+ aaa & Ddkas jd dsjds ds cgha sfgs dd fddzf dfhz xxz
+ dras ffg hksd kds d sdjds h sd jd dsjds ds cgha
+ sfgs dd fddzf dfhz xxz. \crl
+ bb ddd ggg & Dsjds ds cgha sfgs dd fddzf dfhz xxz
+ ddkas jd dsjds ds cgha sfgs dd fddzf. \crl }
+\endtt
+
+\noindent\table pxto\hsize {|c|p{\tsize}|}{\crl
+ aaa & Ddkas jd dsjds ds cgha sfgs dd fddzf dfhz xxz
+ dras ffg hksd kds d sdjds h sd jd dsjds ds cgha
+ sfgs dd fddzf dfhz xxz. \crl
+ bb ddd ggg & Dsjds ds cgha sfgs dd fddzf dfhz xxz
+ ddkas jd dsjds ds cgha sfgs dd fddzf. \crl }
+\medskip
+
+The first `c` colum is variable width (it gets the width of most wide item)
+and the resting space to given `\hsize` is filled by the `p` column.
+
+You can declare more than one `p{<coefficient>\tsize}` columns in the table
+when `pxto` keyword is used. The total sum of <coefficinets> must be exactly one.
+For example,
+
+\begtt \catcode`\<=13
+\table pxto13cm {r p{.3\tsize} p{.5\tsize} p{.2\tsize} l}{<data>}
+\endtt
+%
+This gives the ratio of widths of individual paragraphs in the table.
+
+\_endinput
+
+2020-05-20 \colnum implemented.
+ \vspan implemented.
+2020-05-19 \fL, \fR ets defined.
+ \table to, \table pxto implemented.
+2020-05-10 \bgroup &\egroup added to tabdata (in order to \aftergroup from colors)
+ boundary declarator : introduced
+ \_unsskip: \ifmmode added.
2020-04-10 second group for items in order to \localcolors