summaryrefslogtreecommitdiff
path: root/macros/optex/base
diff options
context:
space:
mode:
Diffstat (limited to 'macros/optex/base')
-rw-r--r--macros/optex/base/basic-macros.opm24
-rw-r--r--macros/optex/base/colors.opm215
-rw-r--r--macros/optex/base/doc.opm6
-rw-r--r--macros/optex/base/fonts-select.opm30
-rw-r--r--macros/optex/base/graphics.opm75
-rw-r--r--macros/optex/base/hi-syntax.opm122
-rw-r--r--macros/optex/base/hisyntax-python.opm4
-rw-r--r--macros/optex/base/if-macros.opm7
-rw-r--r--macros/optex/base/makeindex.opm8
-rw-r--r--macros/optex/base/maketoc.opm6
-rw-r--r--macros/optex/base/math-macros.opm7
-rw-r--r--macros/optex/base/math-unicode.opm48
-rw-r--r--macros/optex/base/optex.ini6
-rw-r--r--macros/optex/base/optex.lua268
-rw-r--r--macros/optex/base/others.opm4
-rw-r--r--macros/optex/base/output.opm51
-rw-r--r--macros/optex/base/parameters.opm26
-rw-r--r--macros/optex/base/prefixed.opm12
-rw-r--r--macros/optex/base/ref-file.opm135
-rw-r--r--macros/optex/base/references.opm6
-rw-r--r--macros/optex/base/slides.opm19
-rw-r--r--macros/optex/base/table.opm125
22 files changed, 768 insertions, 436 deletions
diff --git a/macros/optex/base/basic-macros.opm b/macros/optex/base/basic-macros.opm
index 57393fc323..912be5e036 100644
--- a/macros/optex/base/basic-macros.opm
+++ b/macros/optex/base/basic-macros.opm
@@ -1,9 +1,9 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \sdef {Basic macros for OpTeX <2021-05-16>} % preloaded in format
+\_codedecl \sdef {Basic macros for OpTeX <2021-07-20>} % preloaded in format
\_doc ------------------------------
- \`\bgroup`, \`\egroup`, \`\empty`, \`\space`, \`\null` and \`\wlog`
+ \`\bgroup`, \`\egroup`, \`\empty`, \`\space`, and \`\null`
are classical macros from plain \TeX/.
\_cod ------------------------------
@@ -11,8 +11,7 @@
\_def \_empty {}
\_def \_space { }
\_def \_null {\_hbox{}}
-\_def \_wlog {\_immediate\_write-1 } % write on log file (only)
-\_public \bgroup \egroup \empty \space \null \wlog ;
+\_public \bgroup \egroup \empty \space \null ;
\_doc ------------------------------
\`\ignoreit` ignores next token or `{<text>}`,
@@ -107,25 +106,32 @@
\_cod ------------------------------
\_def\_loggingall{\_tracingcommands=3 \_tracingstats=2 \_tracingpages=1
- \_tracingoutput=1 \_tracinglostchars=1 \_tracingmacros=2
+ \_tracingoutput=1 \_tracinglostchars=1 \_tracingmacros=3
\_tracingparagraphs=1 \_tracingrestores=1 \_tracingscantokens=1
\_tracingifs=1 \_tracinggroups=1 \_tracingassigns=1 }
\_def\_tracingall{\_tracingonline=1 \_loggingall}
\_public \loggingall \tracingall ;
\_doc ------------------------------
- Write a warning if the user did not load a Unicode Font {\em or}
- if there were unresolved references. \`\_byehook` is used in the \^`\bye` macro.
+ \`\_byehook` is used in the \^`\bye` macro.
+ Write a warning if the user did not load a Unicode Font.
+ Write a \"rerun" warning if the `.ref` file was newly created or it was
+ changed (compared to the previous TeX run).
\_cod ------------------------------
\_def\_byehook{%
\_ifx\_initunifonts\_relax \_relax\_else \_opwarning{Unicode font was not loaded}\_fi
- \_ifnum\_unresolvedrefs>0 \_opwarning{Try to rerun to get references right}\_fi
+ \_immediate\_closeout\_reffile
+ \_edef\_tmp{\_mdfive{\_jobname.ref}}%
+ \_ifx\_tmp\_prevrefhash\_else \_opwarning{Try to rerun,
+ \_jobname.ref file was \_ifx\_prevrefhash\_empty created\_else changed\_fi}\_fi
}
\_endcode % -------------------------------------
-2021-05-16: \slet reimplemnted (to allow \slet{foo}{undefined}).
+2021-07-20: \_unresovedrefs removed from \_byehook
+2021-07-18: \_byehook: checking `ref` file consistency added.
+2021-05-16: \slet reimplemented (to allow \slet{foo}{undefined}).
2021-02-03: \useit defined.
2021-01-22: \trycs: \ea added in order to be able to use cs with parameters
2021-01-08: \opwarning format changed (secondly, hope that conclusively)
diff --git a/macros/optex/base/colors.opm b/macros/optex/base/colors.opm
index 23ec22dd9f..6ef8fc9dcf 100644
--- a/macros/optex/base/colors.opm
+++ b/macros/optex/base/colors.opm
@@ -1,16 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \colordef {Colors <2021-05-28>} % preloaded in format
-
- \_doc -----------------------------
- We declare internal boolean value \`\_iflocalcolor` ad do
- \`\localcolor` as default.
- \_cod -----------------------------
-
-\_newifi \_iflocalcolor \_localcolortrue
-\_protected\_def \_localcolor {\_localcolortrue}
-\_protected\_def \_nolocalcolor {\_localcolorfalse}
-\_public \localcolor \nolocalcolor ;
+\_codedecl \colordef {Colors <2021-07-16>} % preloaded in format
\_doc -----------------------------
The basic colors in CMYK
@@ -21,103 +11,101 @@
\_def\Blue {\_setcmykcolor{1 1 0 0}}
\_def\Red {\_setcmykcolor{0 1 1 0}}
-\_def\Brown {\_setcmykcolor{0 0.67 0.67 0.5}}
+\_def\Brown {\_setcmykcolor{0 .67 .67 .5}}
\_def\Green {\_setcmykcolor{1 0 1 0}}
\_def\Yellow {\_setcmykcolor{0 0 1 0}}
\_def\Cyan {\_setcmykcolor{1 0 0 0}}
\_def\Magenta {\_setcmykcolor{0 1 0 0}}
-\_def\Grey {\_setcmykcolor{0 0 0 0.5}}
-\_def\LightGrey {\_setcmykcolor{0 0 0 0.2}}
+\_def\Grey {\_setcmykcolor{0 0 0 .5}}
+\_def\LightGrey {\_setcmykcolor{0 0 0 .2}}
\_def\White {\_setgreycolor{1}}
\_def\Black {\_setgreycolor{0}}
\_doc -----------------------------
By default, the \`\setcmykcolor` \`\setrgbcolor` and \`\setgreycolor`
macros with `{<componetns>}` parameter
- expand to `\_setcolor{<pdf-primitive>}` using \`\_formatcmyk`
- or \`\_formatrgb` or \`\_formatgrey` expandable macros.
- For example `\setrgbcolor{1 0 0}` expands to `\_setcolor{1 0 0 rg 1 0 0 RG}`.\nl
- We set both types of colors (for lines (`K` or `RG` or `G`) and for fills
- (`r` or `rg` or `g`) together in the <pdf-primitive> command.
- This is the reason why the \`\_fillstroke` uses both its parameters.
- If only fills are needed you can do `\def\_fillstroke#1#2{#1}`.
- If only strokes are needed you can do `\def\_fillstroke#1#2{#2}`.
+ expand to \^`\_setcolor``{<color-data>}{<fill-op>}{<stroke-op>}` where
+ <color-data> is <R> <G> <B> or <C> <M> <Y> <K> or <G> and
+ <fill-op> is color operator for filling, <stroke-op> is color operator
+ for stroking.
\_cod -----------------------------
-\_def\_setcmykcolor#1{\_setcolor{\_formatcmyk{#1}}}
-\_def\_setrgbcolor#1{\_setcolor{\_formatrgb{#1}}}
-\_def\_setgreycolor#1{\_setcolor{\_formatgrey{#1}}}
-\_def\_formatcmyk#1{\_fillstroke{#1 k}{#1 K}}
-\_def\_formatrgb#1{\_fillstroke{#1 rg}{#1 RG}}
-\_def\_formatgrey#1{\_fillstroke{#1 g}{#1 G}}
-\_def\_fillstroke#1#2{#1 #2}
+\_def\_setcmykcolor#1{\_setcolor{#1}kK}
+\_def\_setrgbcolor#1{\_setcolor{#1}{rg}{RG}}
+\_def\_setgreycolor#1{\_setcolor{#1}gG}
\_public \setcmykcolor \setrgbcolor \setgreycolor ;
\_doc -----------------------------
- The \`\onlyrgb` declaration redefines \^`\_formatcmyk` in order it expands
- to its conversion to RGB <pdf-primitive>. This conversion is done by
- the \^`\_cmyktorgb` macro. Moreover, `\onlyrgb` re-defines three basic RGB
+ The \`\onlyrgb` declaration redefines \^`\setcmykcolor` to do conversion
+ to RGB just before \^`\_setcolor` is used.
+ The \`\onlycmyk` declaration redefines \^`\setrgbcolor` to do conversion
+ to CMYK just before \^`\_setcolor` is used.
+ Moreover, \^`\onlyrgb` re-defines three basic RGB
colors for RGB color space and re-declares \^`\colordef` as \^`\rgbcolordef`.
- The \hbox{\`\onlycmyk`} macro does similar work, it re-defines \^`\_formatrgb`
- macro. The Grey color space is unchanged and works in both main
- settings (RGB or CMYK) without collisions.
\_cod -----------------------------
\_def\_onlyrgb{\_def\Red{\_setrgbcolor{1 0 0}}%
\_def\Green{\_setrgbcolor{0 1 0}}\_def\Blue{\_setrgbcolor{0 0 1}}%
\_let\_colordef=\_rgbcolordef
- \_def\_formatrgb##1{\_fillstroke{##1 rg}{##1 RG}}%
- \_def\_formatcmyk##1{\_fillstroke{\_cmyktorgb ##1 ; rg}{\_cmyktorgb ##1 ; RG}}}
-\_def\_onlycmyk{\_def\_formatcmyk##1{\_fillstroke{##1 k}{##1 K}}%
- \_def\_formatrgb##1{\_fillstroke{\_rgbtocmyk ##1 ; k}{\_rgbtocmyk ##1 ; K}}}
+ \_def\_setrgbcolor##1{\_setcolor{##1}{rg}{RG}}%
+ \_def\_setcmykcolor##1{\_ea\_setcolor\_ea{\_expanded{\_cmyktorgb ##1 ;}}{rg}{RG}}%
+ \_public \colordef \setrgbcolor \setcmykcolor ;}
+\_def\_onlycmyk{%
+ \_let\_colordef=\_cmykcolordef
+ \_def\_setrgbcolor##1{\_ea\_setcolor\_ea{\_expanded{\_rgbtocmyk ##1 ;}}kK}%
+ \_def\_setcmykcolor##1{\_setcolor{##1}kK}%
+ \_public \colordef \setrgbcolor \setcmykcolor ;}
\_public \onlyrgb \onlycmyk ;
\_doc -----------------------------
- The \`\_setcolor` macro redefines empty `\_ensureblack` macro (used in
- output routine for headers and footers) to `\_ensureblackA` which sets
- Black at the start of its parameter and returns to the current color at the
- end of its parameter.
-
- The current color is saved into `\_currentcolor` macro and colorstack is pushed.
- Finally, the `\_colorstackpop` is initialized by `\aftergroup` if
- `\localcolor` is declared.
-
- You can save the current color to your macro by `\let\yourmacro=\_currentcolor`
- and you can return to this color by the command `\_setcolor\yourmacro`.
+ The \`\_colorattr` for coloring is allocated and
+ \`\_setcolor``{<color-data>}{<fill-op>}{<stroke-op>}` is defined here.
+ This macro does `\_colorattr=`\`\_colorcnt` if the <color data> was not used
+ before and prepare mapping from this integer value to the <color data>
+ and increments \^`\_colorcnt`.
+ If the <color data> were used already, then \^`\_setcolor`
+ does `\_colorattr=<stored-value>`.
+ This work is done by the \`\_translatecolor` macro. The following mapping
+ macros are created:
+ \begtt \catcode`<=13
+ \_color::<data> <fill-op> ... expands to used <attribute-value>
+ \_color:<attribute-value> ... expands to <data> <fill-op>
+ \_color-s:<attribute-value> ... expands to <data> <stroke-op>
+ \endtt
+ The \`\_resetcolor` un-sets the color attribute, it means that default
+ color (black) shall be used.
\_cod -----------------------------
-\_protected\_def \_setcolor #1{\_global\_let\_ensureblack=\_ensureblackA
- \_iflocalcolor \_edef\_currentcolor{#1}\_colorstackpush\_currentcolor
- \_aftergroup\_colorstackpop
- \_else \_xdef\_currentcolor{#1}\_colorstackset\_currentcolor \_fi
+\_newattribute \_colorattr
+\_newcount \_colorcnt \_colorcnt=1 % allocations start at 1
+\_protected\_def\_setcolor{\_colorprefix\_colorattr=\_translatecolor}
+\_def\_resetcolor{\_colorattr=-"7FFFFFFF }
+\_def\_translatecolor#1#2#3{\_ifcsname _color::#1 #2\_endcsname\_lastnamedcs\_relax
+ \_else
+ \_colorcnt
+ \_sxdef{_color::#1 #2}{\_the\_colorcnt}%
+ \_sxdef{_color:\_the\_colorcnt}{#1 #2}%
+ \_sxdef{_color-s:\_the\_colorcnt}{#1 #3}%
+ \_incr \_colorcnt
+ \_fi
}
-\_def\_pdfblackcolor{0 g 0 G}
-\_edef\_currentcolor{\_pdfblackcolor}
-\_def\_ensureblackA#1{\_global\_let\_openfnotestack=\_openfnotestackA
- \_colorstackpush\_pdfblackcolor #1\_colorstackpop}
-
- \_doc -----------------------------
- The colorstack is initialized here and the basic macros
- \`\_colorstackpush`, \`\_colorstackpop` and \`\_colorstackset`
- are defined here.
- \_cod -----------------------------
-
-\_mathchardef\_colorstackcnt=0 % Implicit stack usage
-\_def\_colorstackpush#1{\_pdfcolorstack\_colorstackcnt push{#1}}
-\_def\_colorstackpop{\_pdfcolorstack\_colorstackcnt pop}
-\_def\_colorstackset#1{\_pdfcolorstack\_colorstackcnt set{#1}}
+% Black is the default color.
+\_sdef{_color::0 g}{0}
+\_sdef{_color:0}{0 g}
+\_sdef{_color-s:0}{0 G}
\_doc -----------------------------
- We need to open a special color stack for footnotes because footnotes
- can follow on the next pages and their colors are independent of colors
- used in the main page-body. The \`\_openfnotestack` is defined as
- \`\_openfnotestackA` when the \^`\_setcolor` is used first.
- The \`\_fnotestack` is initialized in in `\everyjob` because the
- initialization is not saved to the format.
+ We support concept of non-local color, i.e. all changes of the color
+ attribute are global by setting \`\_colorprefix` to `\global`.
+ \`\localcolor` is the default, i.e.\ \^`\_colorprefix` is `\relax`.\nl
+ You can write `\global\Red` if you want to have global setting of the
+ color.
\_cod -----------------------------
-%\_mathchardef\_fnotestack=\_pdfcolorstackinit page {0 g 0 G} % must be in \everyjob
-\_def \_openfnotestackA {\_pdfcolorstack\_fnotestack current}
+\_protected\_def \_localcolor {\_let\_colorprefix=\_relax}
+\_protected\_def \_nolocalcolor {\_let\_colorprefix=\_global}
+\_public \localcolor \nolocalcolor ;
+\_localcolor
\_doc -----------------------------
We use Lua codes for RGB to CMYK or CMYK to RGB conversions and for
@@ -297,7 +285,7 @@
\begtt
\def\vr{\vrule height10pt depth2pt width20pt}
\def\_showcolor{\hbox{\tt\_bslash\_tmpb: \csname\_tmpb\endcsname \vr}\space\space}
- \begmulti 4 \typosize[11/14]
+ \begmulti 4 \typosize[10/14]
\morecolors
\endmulti
\endtt
@@ -319,35 +307,49 @@
\_endcode % -------------------------------------
-The colors have different behavior than fonts. Marks (whatsits) with color
-information are stored into PDF output and \TeX/ doesn't interpret them.
-The PDF viewer (or PDF interpreter in a printer) reads these marks
-and switches colors according to them. This
-is independent of \TeX/ group mechanism. You can declare
-`\nolocalcolor` at the beginning of the document, if you want this behavior.
-In this case, if you set a color then you must return to the black color
-using `\Black` manually.
-
-By default, \OpTeX/ sets `\localcolor`. It means that the typesetting
-returns to a previous color at the end of the current group, so you cannot
-write `\Black` explicitly. This is implemented using the `\aftergroup` feature.
-There is a limitation of this feature: when a color selector is used in a
-group of a box, which is saved by `\setbox`, then the activity or
-reconstruction of the previous color is processed at `\setbox` time, no in the
-box itself. You must correct it by double group:
-\begtt
-\setbox0=\hbox{\Red text} % bad: \Black is done after \setbox
-\setbox0=\hbox{{\Red text}} % good: \Black is done after group inside the box
-\endtt
-
-The implementation of colors is based on colorstack, so the current color
-can follow across more pages. It is not so obvious because PDF viewer (or PDF
-interpreter) manipulates with colors locally at each PDF page and it
-initializes each PDF page with black on white color.
+\secc Basic concept
+
+Setting of color in PDF is handled by graphics operators which change the
+graphics context. Colors for fills/strokes are distinguished, but apart from
+that, only one color is active at time and is used for all material drawn by
+following graphics operators, until next color is set. Each PDF content (e.g.
+page or form XObject) has its own graphics context, that is initialized from
+zero. Hence we have different concept of selecting fonts in \TeX/ (it
+depends on \TeX/ groups but does not depends on pages) and color handling in
+PDF.
+
+\TeX/ itself has no concept of colors. Colors have always been handled by
+inserting whatsits (either using `\special` for DVI or using
+`\pdfliteral`/`\pdfcolorstack` for PDF). It is very efficient and \TeX/ doesn't
+even have to know anything about colors, but it is also problematic in many
+ways.
+
+That is the reason why we decided to change color handling from
+`\pdfcolorstack` to \LuaTeX/ attributes in version 1.04 of \OpTeX. Using
+attributes, the color setting behaves exactly like font selection from \TeX/
+point of view: it respects \TeX/ groups, colors can span more pages,
+independent colors can be set for `\insert`s, etc. Moreover, once a material is
+created (using `\setbox` for example) then it has its fonts and its colors
+frozen and you can rely on it when you are using e.g. `\unhbox`. There are no
+internal whatsits for colors which can interfere with other typesetting
+material. In the end something like setting text to red (`{\Red text}`) should
+have the same nice behavior like setting text to bold (`{\bf text}`).
+
+\LuaTeX/ attributes can be set like count register -- one attribute holds one
+number at a time. But the value of attribute is propagated to each created
+typesetting element until the attribute is unset or set to another value. Very
+much like the font property. We use one attribute \^`\_colorattr` for storing
+the currently selected color (in number form).
Macros \^`\setcmykcolor``{<C> <M> <Y> <K>}` or \^`\setrgbcolor``{<R> <G> <B>}`
-or\nl \^`\setgreycolor``{<Grey>}` should be used in color selectors or user can
-specify these macros explicitly.
+or\nl \^`\setgreycolor``{<Grey>}` are used in color selectors. These
+macros expand to internal \^`\_setcolor` macro which sets the \^`\_colorattr`
+attribute to an integer value and prepares mapping between this value and the real
+color data. This mapping is used just before each `\shipout` in output routine.
+The \^`\_preshipout` pseudo-primitive is used here, it converts attribute
+values to internal PDF commands for selecting colors.
+
+\secc Color mixing
The color mixing processed by the \^`\colordef` is done in the subtractive color
model CMYK. If the result has a component greater than 1 then all
@@ -405,8 +407,11 @@ and it is used in \^`\colordef` or if it is printed when \^`\onlycmyk` is declar
The CMYK to RGB conversion is invoked when a color is declared using \^`\setcmykcolor`
and it is used in \^`\rgbcolordef` or if it is printed when \^`\onlyrgb` is declared.
+\secc Implementation
+
\_endinput
+2021-07-16 colors reimplemented, now they are based on attributes
2021-05-28 \rgbcmykmap introduced
2020-04-22 \replstring\tmpb{+ }{+}, {- }{-} added in \colordef, bug fixed
2020-03-18 introduced
diff --git a/macros/optex/base/doc.opm b/macros/optex/base/doc.opm
index 643a283e7c..34a00dc1e9 100644
--- a/macros/optex/base/doc.opm
+++ b/macros/optex/base/doc.opm
@@ -127,7 +127,7 @@
The lines in the listing mode have a yellow background.
\_cod -----------------------------
-\_def\Yellow{\_setcmykcolor{0.0 0.0 0.3 0.03}}
+\_def\Yellow{\_setcmykcolor{0 0 .3 .03}}
\_def\_printcodeline#1{\_advance \_maxlines by-1
\_ifnum \_maxlines<0 \_ea \_endverbprinting \_fi
@@ -137,7 +137,7 @@
\_indent \_printverblinenum #1\par}
\_def\_printfilename{\_hbox to0pt{%
- \_hskip\_hsize\vbox to0pt{\_vss\_llap{\Brown\docfile}\_kern7.5pt}\_hss}%
+ \_hskip\_hsize\_vbox to0pt{\_vss\_llap{\Brown\docfile}\_kern7.5pt}\_hss}%
\_let\_printfilename=\_relax
}
\_everytt={\_let\_printverblinenum=\_relax}
@@ -153,7 +153,7 @@
\_def\docfile{}
\_def\_printdoc #1 {\_par \_def\docfile{#1}%
\_everytt={\_ttshift=-15pt \_let\_printverblinenum=\_relax}%
- \_ea\_cod \input #1
+ \_ea\_cod \_input #1
\_everytt={\_let\_printverblinenum=\_relax}%
\_def\docfile{}%
}
diff --git a/macros/optex/base/fonts-select.opm b/macros/optex/base/fonts-select.opm
index 5dab510453..355a71a191 100644
--- a/macros/optex/base/fonts-select.opm
+++ b/macros/optex/base/fonts-select.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \fontfam {Fonts selection system <2021-05-23>} % preloaded in format
+\_codedecl \fontfam {Fonts selection system <2021-07-16>} % preloaded in format
\_doc -----------------------------
The variant selectors \^`\rm`, \^`\bf`, \^`\it`, \^`\bi`, \^`\tt`
@@ -16,7 +16,7 @@
`\_tryloadbf \_tenbf`. If the font context (font family, font size, features)
is not changed, then `\_tryloadbf` is `\relax` and `\_tenbf` font switcher selects
given font. If the font context is changed, then `\_tryloadbf` is re-defined (see
- \^`\_reloading` macro) to load new bold varinat of the font using \^`\_resizefont`
+ \^`\_reloading` macro) to load new bold variant of the font using \^`\_resizefont`
The loaded font is saved to `\_tenbf` switcher and `\_tryloadbf` returns
back to the `\relax` meaning. So, `\bf` macro loads
new font with current font context and then selects it by `\_tenbf`
@@ -31,8 +31,8 @@
family independence for `\tt` macro, see section~\ref[tt].
So, `\_tryloadtt` is defined constantly as \"loading `\tt` font" and it is
not re-defined to `\relax`. On the other hand, `\_tryloadtt` is
- re-defined in the \^`\initunifonts` macro or when used
- \~`\famvardef``\tt`.
+ re-defined in the \^`\initunifonts` macro or when
+ \~`\famvardef``\tt` is used.
\_cod -----------------------------
\_def\_reloading{\_loadf{rm}\_tenrm \_loadf{bf}\_tenbf \_loadf{it}\_tenit \_loadf{bi}\_tenbi}
@@ -46,8 +46,8 @@
\_doc ----------------------------
The Font Selection system allows to use \`\currvar`
- instead explicitly specified variant selector. The current variant
- is extracted from `\the\font` output which could be `\_ten<XX>` control
+ instead of an explicitly specified variant selector. The current variant
+ is extracted from `\the\font` output which could be the `\_ten<XX>` control
sequence. Then `\currvar` expands to `\_rm` or `\_it` etc.
\_cod ----------------------------
@@ -66,7 +66,7 @@
The <variant-name> is `rm` or `bf` or `it` or `bi` or `tt`.
The new <font-switch> is declared (roughly speaking) by:
\begtt \catcode`<=13
- \_font <font switch> = <fontname of>\_ten<variant-name> \_sizepec % in TFM mode
+ \_font <font switch> = <fontname of>\_ten<variant-name> \_sizespec % in TFM mode
\_font <font switch> = {\_fontnamegen} \_sizespec % in OTF mode
\endtt
The font is loaded by \`\_doresizefont``<font switch>`. This macro has
@@ -121,7 +121,7 @@
typesetting then it is set to a positive value.\nl
The `\_newfontloaded` should be defined for micro-typographic configuration of
fonts, for example. See
- \ulink[http://petr.olsak.net/optex/optex-tricks.html\#fontexpand]{OpTeX/ trick 0058}.
+ \ulink[http://petr.olsak.net/optex/optex-tricks.html\#fontexpand]{\OpTeX/ trick 0058}.
\_cod -----------------------------
\_def\_fontloaded #1{\_ifnum\_skewchar#1=-1 \_skewchar#1=-2 \_newfontloaded#1\_fi}
@@ -130,7 +130,7 @@
\_doc -----------------------------
\`\initunifonts` macro extends \LuaTeX's font capabalities,
in order to be able to load Unicode fonts. Unfortunately, this part of
- \OpTeX/ depends on `luaotfload` package, which adapts Con\TeX/t's generic
+ \OpTeX/ depends on the `luaotfload` package, which adapts Con\TeX/t's generic
font loader for plain \TeX/ and \LaTeX. `luaotfload` uses Lua functions
from \LaTeX's `luatexbase` namespace, we provide our own replacements.
Moreover, `\initunifont` switches with
@@ -146,6 +146,7 @@
\_directlua{%
require('luaotfload-main')
luaotfload.main()
+ optex_hook_into_luaotfload()
}%
\_gdef\_rfskipatX ##1" ##2\_relax{"##1"}%
\_global\_let \_doresizefont=\_doresizeunifont
@@ -169,7 +170,7 @@
be in the right font family context. The `\_currfamily` is set to the
`<Famselector>` by the `\<Famselector>` too, because `\<Famselector>`
must set the right font family context. The font family context is given by the current
- `\_currfamily` value and by the actual meaning of the \^`\_fontnamegen` macro.
+ `\_currfamily` value and by the current meaning of the \^`\_fontnamegen` macro.
The \`\_mathfaminfo` is saved for usage in the catalog.
\_cod -----------------------------
@@ -585,7 +586,7 @@ We distinguish between
In addition, \OpTeX/ defines \~`\tt` as variant selector
independent of chosen font family. It selects typewriter-like font.
* {\em font modifiers} are declared in a family (`\cond`, `\caps`) or are
- \"build in" (\^`\setfontsize``{<size spec>}`, \~`\setff{<features>}`).
+ \"built-in" (\^`\setfontsize``{<size spec>}`, \~`\setff{<features>}`).
They do appropriate change in the {\em font context} but do not select
the font.
* {\em family selectors} (for example `\Termes`, `\LMfonts`),
@@ -701,10 +702,10 @@ family selectors and defined font macros doing something with fonts.
variant selectors can be declared by \~`\famvardef` command. They select a
font dependent on the current font context, see section~\ref[famvardef].
The `\tt` selector is documented in section~\ref[tt].
-* Font modifiers are \"build in" or declared by \~`\moddef` command.
+* Font modifiers are \"built-in" or declared by \~`\moddef` command.
They do modifications in the font context but don't select any font.
\begitems
- * \"build-in" font modifiers are \^`\setfontsize` (see
+ * \"built-in" font modifiers are \^`\setfontsize` (see
section~\ref[setfontsize]), \~`\setff` (see section~\ref[setff]),
\~`\setfontcolor`, \~`\setletterspace` and \~`\setwordspace`
(see section~\ref[specff]). They are independent of font family.
@@ -995,7 +996,7 @@ all possibilities of extended `\font` primitive.
The \OpTeX/ format is initialized by `luatex` engine by default but
you can initialize it by `luahbtex` engine too. Then the harfbuzz library is
-ready to use for font rendering as an alternative to build-in font renderer
+ready to use for font rendering as an alternative to built-in font renderer
from Luaotfload. The harfbuzz library gives more features for rendering
Indic and Arabic scripts. But it is not used as default, you need to specify
`mode=harf` in the fontfeatures field when `\font` is used. Moreover, when
@@ -1010,6 +1011,7 @@ Luaotfload documentation for more information.
\endinput
+2021-07-16 \initunifonts: optex_hook_into_luaotfload added.
2021-05-23 concept of \_fontfeatures macro re-implemented
2021-05-02 simpler \_resizefont, better concept of doc, moving parts from fonts-resize
2021-04-22 \_ffonum introduced
diff --git a/macros/optex/base/graphics.opm b/macros/optex/base/graphics.opm
index 1adb444b4e..4c72528e48 100644
--- a/macros/optex/base/graphics.opm
+++ b/macros/optex/base/graphics.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \inspic {Graphics <2021-03-19>} % preloaded in format
+\_codedecl \inspic {Graphics <2021-07-16>} % preloaded in format
\_doc -----------------------------
\`\inspic` accepts old syntax `\inspic <filename><space>`
@@ -231,8 +231,8 @@
are parameters, they can be set by user in optional brackets `[...]`.
For example `\fcolor=\Red` does `\_let\_fcolorvalue=\Red` and it means
filling color.\nl
- The \`\_setflcolor` uses the \^`\_fillstroke` macro to separate filling
- color and drawing color.
+ The \`\_setflcolors` uses the \^`\_setcolor` macro to separate filling (non-stroking)
+ color and stroking color.
\_cod -----------------------------
\_newdimen \_lwidth
@@ -245,10 +245,9 @@
\_def\_touppervalue#1{\_ifx#1n\_let#1=N\_fi}
\_def\_setflcolors#1{% use only in a group
- \_def\_setcolor##1{##1}%
- \_def\_fillstroke##1##2{##1}%
+ \_def\_setcolor##1##2##3{##1 ##2}%
\_edef#1{\_fcolorvalue}%
- \_def\_fillstroke##1##2{##2}%
+ \_def\_setcolor##1##2##3{##1 ##3}%
\_edef#1{#1\_space\_lcolorvalue\_space}%
}
\_optdef\_inoval[]{\_vbox\_bgroup
@@ -260,9 +259,7 @@
\_advance\_hsize by-2\_hhkern \_advance\_hsize by-2\_roundness \_fi
\_setbox0=\_hbox\_bgroup\_bgroup \_aftergroup\_inovalA \_kern\_hhkern \_let\_next=%
}
-\_def\_inovalA{\_isnextchar\_colorstackpop\_inovalB\_inovalC}
-\_def\_inovalB#1{#1\_isnextchar\_colorstackpop\_inovalB\_inovalC}
-\_def\_inovalC{\_egroup % of \setbox0=\hbox\bgroup
+\_def\_inovalA{\_egroup % of \setbox0=\hbox\bgroup
\_ifdim\_vvkern=\_zo \_else \_ht0=\_dimexpr\_ht0+\_vvkern \_relax
\_dp0=\_dimexpr\_dp0+\_vvkern \_relax \_fi
\_ifdim\_hhkern=\_zo \_else \_wd0=\_dimexpr\_wd0+\_hhkern \_relax \_fi
@@ -290,9 +287,7 @@
\_touppervalue\_overlapmarginsvalue \_touppervalue\_shadowvalue
\_setbox0=\_hbox\_bgroup\_bgroup \_aftergroup\_incircleA \_kern\_hhkern \_let\_next=%
}
-\_def\_incircleA {\_isnextchar\_colorstackpop\_incircleB\_incircleC}
-\_def\_incircleB #1{#1\_isnextchar\_colorstackpop\_incircleB\_incircleC}
-\_def\_incircleC {\_egroup % of \setbox0=\hbox\bgroup
+\_def\_incircleA {\_egroup % of \setbox0=\hbox\bgroup
\_wd0=\_dimexpr \_wd0+\_hhkern \_relax
\_ht0=\_dimexpr \_ht0+\_vvkern \_relax \_dp0=\_dimexpr \_dp0+\_vvkern \_relax
\_ifdim \_ratiovalue\_dimexpr \_ht0+\_dp0 > \_wd0
@@ -319,6 +314,39 @@
\_public \inoval \incircle \ratio \lwidth \fcolor \lcolor \shadow \overlapmargins ;
\_doc -----------------------------
+ Just before defining shadows, which require special graphics states, we
+ define means for managing these graphics states. This is important, because
+ otherwise our use of `\pdfpageresources` register might clash with other
+ packages (TikZ) or even with our other usage (slides).
+
+ The macro \`\addextgstate``<PDF name> <PDF dictionary>` shall be used for
+ adding more graphics states. It must be used {\em after} `\dump`. First use
+ of it detects PGF/TikZ and either uses its mechanism or defines our own. Our
+ mechanism is very similar though -- use single `/ExtGState` dictionary for all
+ pages (`\pdfpageresources` just points to it).
+ \_cod -----------------------------
+
+\_def\_initpageresources{%
+ \_glet\_initpageresources=\_relax
+ \_ifcsname pgf@sys@addpdfresource@extgs@plain\_endcsname
+ % TikZ loaded
+ \_global\_slet{_addextgstate}{pgf@sys@addpdfresource@extgs@plain}%
+ \_else
+ % TikZ not loaded
+ \_pdfobj reserveobjnum% not to be used in iniTeX
+ \_xdef\_extgstatesobj{\_the\_pdflastobj}%
+ \_expanded{\_global\_pdfpageresources={/ExtGState \_extgstatesobj\_space 0 R}}%
+ \_global\_addto\_byehook{\_immediate\_pdfobj useobjnum\_extgstatesobj {<<\_extgstates>>}}%
+ \_gdef\_extgstates{}%
+ \_gdef\_addextgstate##1{\_xdef\_extgstates{\_extgstates\_space##1}}%
+ \_fi
+}
+% first initialize page resources, then execute new meaning of itself
+\_def\_addextgstate#1{\_initpageresources \_addextgstate{#1}}
+
+\_public \addextgstate ;
+
+ \_doc -----------------------------
A shadow effect is implemented here. The shadow is equal to the
silhouette of the given path in a gray-transparent color shifted by
\`\_shadowmoveto` vector and with blurred boundary.
@@ -333,27 +361,11 @@
\_def\_shadowmoveto{1.8 -2.5} % vector defines shifting layer (in bp)
\_def\_shadowb{1} % 2*shadowb = blurring area thickness
- \_doc -----------------------------
- The `\_pdfpageresources` primitive is used to define transparency.
- It does not work when used in a box. So, we use it at the beginning of
- the output routine. The modification of the output routine is done
- using \`\_insertshadowresources` only once when the shadow effect is used first.
- \_cod -----------------------------
-
\_def\_insertshadowresources{%
- \_global\_addto\_begoutput{\_setshadowresources}%
- \_xdef\_setshadowresources{%
- \_pdfpageresources{/ExtGState
- <<
- /op1 <</Type /ExtGState /ca \_shadowdarknessA>>
- /op2 <</Type /ExtGState /ca \_shadowdarknessB>>
- \_morepgresources
- >>
- }%
- }%
- \_global\_let\_insertshadowresources=\_relax
+ \_addextgstate{/op1 <</ca \_shadowdarknessA>>}%
+ \_addextgstate{/op2 <</ca \_shadowdarknessB>>}%
+ \_glet\_insertshadowresources=\_relax
}
-\_def\_morepgresources{}
\_doc -----------------------------
The \`\_doshadow``{<curve>}` does the shadow effect.
@@ -441,6 +453,7 @@ the \^`\transformbox{<transformation>}{\copy\mypic}`.
\_endinput
+2021-07-16: \inoval, \incircle are more simple, using attribitecolor features
2021-03-19: \inkinspic: pictures in subdirectories, bug fixed
2020-12-21: \puttext: \box0 in goup, bugfix
2020-04-12: \_public \clipinoval \clipincircle ; added, bug fixed
diff --git a/macros/optex/base/hi-syntax.opm b/macros/optex/base/hi-syntax.opm
index eb6d747914..040390db51 100644
--- a/macros/optex/base/hi-syntax.opm
+++ b/macros/optex/base/hi-syntax.opm
@@ -1,28 +1,27 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \hisyntax {Syntax highlithing of verbatim listings <2020-04-04>} % preloaded in format
+\_codedecl \hisyntax {Syntax highlighting of verbatim listings <2020-04-04>} % preloaded in format
\_doc -----------------------------
- The following macros `\replfromto` and `\replthis` manipulate with the
- verbatim text which has been read already and stored in the `\_tmpb` macro.
-
- The \`\replfromto` `{<from>}{<to>}{<what>}` finds first `<from>` then the
- first `<to>` following by `<from>` pattern and the
- `<text>` between them is packed to `#1`.
- Then `<from><text><to>` is replaced by `<what>`. The `<what>` parameter
- can use `#1` which is replaced by the `<text>`.
-
- The `\replfromto` continues by finding next `<from>`, then, next `<to>`
- repeatedly over the whole verbatim text. If the verbatim text is ended by
- opened `<from>` but not closing by `<to>` then `<to>` is appended to the
+ The macros `\replfromto` and `\replthis` manipulate the
+ verbatim text that is already stored in the `\_tmpb` macro.
+
+ \`\replfromto` `{<from>}{<to>}{<replacement>}` finds the first
+ occurrence of `<from>` and the first occurrence of `<to>` following it. The
+ `<text>` between them is packed into `#1` and available to `<replacement>`
+ which ultimately replaces `<text>`.
+
+ `\replfromto` continues by finding next `<from>`, then, next `<to>`
+ repeatedly over the whole verbatim text. If the verbatim text ends with
+ opening `<from>` but has no closing `<to>`, then `<to>` is appended to the
verbatim text automatically and the last part of the verbatim text is replaced too.
- First two parameters are expanded before usage of `\replfromto`. You can
+ The first two parameters are expanded before use of `\replfromto`. You can
use `\csstring\%` or something else here.
\_cod -----------------------------
\_def\_replfromto #1#2{\_edef\_tmpa{{#1}{#2}}\_ea\_replfromtoE\_tmpa}
-\_def\_replfromtoE#1#2#3{% #1=from #2=to #3=what to replace
+\_def\_replfromtoE#1#2#3{% #1=from #2=to #3=replacement
\_def\_replfrom##1#1##2{\_addto\_tmpb{##1}%
\_ifx\_end##2\_ea\_replstop \_else \_afterfi{\_replto##2}\_fi}%
\_def\_replto##1#2##2{%
@@ -36,7 +35,8 @@
\_def\_finrepl{}
\_doc -----------------------------
- The \`\replthis` `{<pattern>}{<what>}` replaces each `<pattern>` by `<what>`.
+ The \`\replthis` `{<pattern>}{<replacement>}` replaces each `<pattern>`
+ by `<replacement>`.
Both parameters of `\replthis` are expanded first.
\_cod -----------------------------
@@ -46,18 +46,18 @@
\_doc -----------------------------
The patterns `<from>`, `<to>` and `<pattern>` are not found when they are
- hidden in braces `{...}`. Example:
+ hidden in braces `{...}`. E.g.
\begtt
\replfromto{/*}{*/}{\x C{/*#1/*}}
\endtt
replaces all C comments by `\x C{...}`. The patterns inside `{...}` are
not used by next usage of `\replfromto` or `\replthis` macros.
- The \`\_xscan` macro does replacing `\x` by `\z` in the post-processing
- phase. The `\x <letter>{<text>}` expands to `\_xscan {<letter>}<text>^^J^`.
+ The \`\_xscan` macro replaces occurrences of `\x` by `\z` in the post-processing
+ phase. The construct `\x <letter>{<text>}` expands to `\_xscan {<letter>}<text>^^J^`.
If `#3` is `\_end` then it signals that something wrong happens, the
`<from>` was not terminated by legal `<to>` when `\replfromto` did work.
- We must to fix it by the \`\_xscanR` macro.
+ We must to fix this by using the \`\_xscanR` macro.
\_cod -----------------------------
\_def\_xscan#1#2^^J#3{\_ifx\_end#3 \_ea\_xscanR\_fi
@@ -66,7 +66,7 @@
\_def\_xscanR#1\_fi#2^{^^J}
\_doc -----------------------------
- The \`\hicolor` `<letter> <color>` defines `\_z<letter>{<text>}`
+ The \`\hicolor` `<letter> <color>` defines `\_z:<letter>{<text>}`
as `{<color><text>}`. It should be used in the context of
`\x <letter>{<text>}` macros.
\_cod -----------------------------
@@ -74,13 +74,13 @@
\_def\_hicolor #1#2{\_sdef{_z:#1}##1{{#2##1}}}
\_doc -----------------------------
- The \`\hisyntax``{<name>}` re-defines default \^`\_prepareverbdata``<macro><verbtext>`
- in order to it does more things:
+ \`\hisyntax``{<name>}` re-defines default \^`\_prepareverbdata``<macro><verbtext>`,
+ but in order to do it does more things:
It saves `<verbtext>` to `\_tmpb`, appends `\n` around spaces and
- `^^J` characters in pre-processing phase, it opens `hisyntax-<name>.opm`
- file if `\_hisyntax<name>` is not defined. Then `\_the\_isyntax<name>`
+ `^^J` characters in pre-processing phase, opens `hisyntax-<name>.opm`
+ file if `\_hisyntax<name>` is not defined. Then `\_the\_hisyntax<name>`
is processed. Finally, the post-processing phase is realized by setting
- appropriate values to `\x` and `\y` macros and doing
+ appropriate values to the `\x` and `\y` macros and doing
`\_edef\_tmpb{\_tmpb}`.
\_cod -----------------------------
@@ -132,15 +132,15 @@
The user can write
\begtt \adef/{\_csstring\\}
-\begtt \hisytnax{C}
+\begtt \hisyntax{C}
...
/endtt
\endtt
-and the code is colorized by C syntax.
-The user can write `\everytt={\hisyntax{C}}` and all verbatim listings are
+to colorize the code using C syntax.
+The user can also write `\everytt={\hisyntax{C}}` to have all verbatim listings
colorized.
-The \^`\hisyntax``{<name>}` reads the file `hisyntax-<name>.opm` where the
+\^`\hisyntax``{<name>}` reads the file `hisyntax-<name>.opm` where the
colorization is declared. The parameter `<name>` is case insensitive and the
file name must include it in lowercase letters. For example, the file
`hisyntax-c.opm` looks like this:
@@ -150,40 +150,40 @@ file name must include it in lowercase letters. For example, the file
\OpTeX/ provides `hisyntax-{c,python,tex,html}.opm` files.
You can take inspiration from these files and declare more languages.
-User can re-declare colors by `\hicolors={...}` This value has precedence
-before `\_hicolors<name>` values declared in the `hicolors-<name>.opm` file.
-What exactly to do: copy `\_hicolors<name>={...}`
+Users can re-declare colors by `\hicolors={...}` This value has precedence
+over `\_hicolors<name>` values declared in the `hicolors-<name>.opm` file.
+The steps are: copy `\_hicolors<name>={...}`
from `hicolors-<name>.opm` to your document,
-rename it as `\hicolors={...}` and do you own colors modifications.
+rename it to `\hicolors={...}` and do your own colors modifications.
Another way to set non-default colors is to declare
-`\newtoks\hicolors<name>` (without the `_` prefix) and set the colors palette here.
+`\newtoks\hicolors<name>` (without the `_` prefix) and set the color palette there.
It has precedence before `\_hicolors<name>` (with the `_` prefix) declared in
the `hicolors-<name>.opm` file.
This is useful when there are more hi-syntax languages used in one document.
\secl4 Notes for hi-syntax macro writers
-The file `hisyntax-<name>.opm` is read only once in the \TeX/ group.
+The file `hisyntax-<name>.opm` is read only once and in a \TeX/ group.
If there are definitions then they must be declared as global.
-The `hisyntax-<name>.opm` file must (globally) declare `\_hisyntax<name>` tokens string
-where the action over verbatim text is declared typically by `\replfromto` or
+The file `hisyntax-<name>.opm` must (globally) declare `\_hisyntax<name>` token list
+where the action over verbatim text is declared typically by using the `\replfromto` or
`\replthis` macros.
-The verbatim text is prepared by {\em pre-processing phase}, then the
-`\_hisyntax<name>` is applied and then {\em post-processing phase} does final
+The verbatim text is prepared by the {\em pre-processing phase}, then
+`\_hisyntax<name>` is applied and then the {\em post-processing phase} does final
corrections. Finally, the verbatim text is printed line by line.
The pre-processing phase does:
\begitems
-* Each space is replaced by {\visiblesp`\n\ \n`}, so `\n<word>\n` should be a pattern to
- finding whole words (no subwords). The `\n` control sequence is removed in
+* Each space is replaced by {\visiblesp`\n\ \n`}, so `\n<word>\n` is the pattern for
+ matching whole words (no subwords). The `\n` control sequence is removed in
the post-processing phase.
* Each end of line is represented by `\n^^J\n`.
* The `\_start` control sequence is added before the verbatim text and the `\_end` control
- sequence is appended to the end of the verbatim text. These control
- sequences are removed in the post-processing phase.
+ sequence is appended to the end of the verbatim text. Both are removed
+ in the post-processing phase.
\enditems
Special macros are working only in a group when processing the verbatim
@@ -191,33 +191,35 @@ text.
\begitems
-* `\n` means noting but it should be used as a boundary of words as mentioned above.
-* `\t` means a tabulator. It is prepared as `\n\t\n` because it can be at
- the boundary of a word.
-* `\x <letter>{<text>}` can be used as replacing text. Suppose the example
+* `\n` represents nothing but it should be used as a boundary of words as mentioned above.
+* `\t` represents a tabulator. It is prepared as `\n\t\n` because it can be at
+ the boundary word boundary.
+* `\x <letter>{<text>}` can be used as replacing text. Consider the example
\begtt
\replfromto{/*}{*/}{\x C{/*#1*/}}
\endtt
- This replaces all C comments `/*...*/` by `\x C{/*...*/}`. But the
- C comments may span more lines, i.e. the `^^J` should be inside it.
+ This replaces all C comments `/*...*/` by `\x C{/*...*/}`. But
+ C comments may span multiple lines, i.e. the `^^J` should be inside it.
- The macro `\x <letter>{<text>}` is replaced by one or more
- `\z <letter>{<text>}` in post-processing phase where each parameter `<text>` of
- `\z` keeps inside one line. Inside-line parameters are represented
- by `\x C{<text>}` and they are replaced to `\z C{<text>}` without any change.
+ The macro `\x <letter>{<text>}` is replaced by one or more occurrences of
+ `\z <letter>{<text>}` in the post-processing phase, each parameter `<text>` of
+ `\z` is from from a single line. Parameters not crossing line boundary are represented
+ by `\x C{<text>}` and replaced by `\z C{<text>}` without any change.
But:
\begtt \catcode`\<=13
- \x C{<text1>^^J<text3>^^J<text3>}
+ \x C{<text1>^^J<text2>^^J<text3>}
+ \endtt
is replaced by
+ \begtt \catcode`\<=13
\z C{<text1>}^^J\z C{<text2>}^^J\z C{<text3>}
\endtt
- The `\z <letter>{<text>}` is expanded to `\_z:<letter>{<text>}` and if
+ `\z <letter>{<text>}` is expanded to `\_z:<letter>{<text>}` and if
`\hicolor <letter> <color>` is declared then
`\_z:<letter>{<text>}` expands to `{<color><text>}`. So, required color is
- activated at all lines (separately) where C comment spans.
-* `\y {<text>}` is replaced by `\<text>` in the post processing phase. It should
- be used for macros without a parameter. You cannot use unprotected macros
+ activated for each line separately (e.g. for C comments spanning multiple lines).
+* `\y {<text>}` is replaced by `\<text>` in the post-processing phase. It should
+ be used for macros without a parameters. You cannot use unprotected macros
as replacement text before the post-processing phase, because the post-processing
- phase is based on expansion whole verbatim text.
+ phase is based on the expansion of the whole verbatim text.
\enditems
diff --git a/macros/optex/base/hisyntax-python.opm b/macros/optex/base/hisyntax-python.opm
index 6250eed0e3..12f7ebeeb4 100644
--- a/macros/optex/base/hisyntax-python.opm
+++ b/macros/optex/base/hisyntax-python.opm
@@ -69,8 +69,8 @@
}
\_gdef\_hipystrpre#1\x#2{\x#2{#1}\x#2}
-\_ifx\LightBlue\_undefined \_gdef\LightBlue {\_setcmykcolor{1 0.43 0 0}}\_fi
-\_ifx\Orange\_undefined \_gdef\Orange {\_setcmykcolor{0 0.64 1 0}}\_fi
+\_ifx\LightBlue\_undefined \_gdef\LightBlue {\_setcmykcolor{1 .43 0 0}}\_fi
+\_ifx\Orange\_undefined \_gdef\Orange {\_setcmykcolor{0 .64 1 0}}\_fi
\_endcode %------------------------------------------------
diff --git a/macros/optex/base/if-macros.opm b/macros/optex/base/if-macros.opm
index 462e496017..6c6318b841 100644
--- a/macros/optex/base/if-macros.opm
+++ b/macros/optex/base/if-macros.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \newif {Special if-macros, is-macros and loops <2021-02-03>} % preloaded in format
+\_codedecl \newif {Special if-macros, is-macros and loops <2021-08-02>} % preloaded in format
\_doc ----------------------------
\secc Classical \code{\\newif}
@@ -118,9 +118,9 @@
\_ea\_fornumB\_ea{\_the\_numexpr#3\_ea}\_ea{\_the\_numexpr#1}%
}
\_def\_fornumB #1#2{\_ifnum#1\_ifnum#2>0<\_else>\_fi \_frnum \_getforstack
- \_else \_ea\_fbody\_ea{\_the\_frnum}%
+ \_else \_afterfi{\_ea\_fbody\_ea{\_the\_frnum}%
\_immediateassignment\_global\_advance\_frnum by#2
- \_afterfi{\_fornumB{#1}{#2}}\_fi
+ \_fornumB{#1}{#2}}\_fi
}
\_def\fornum#1..#2\do{\_fornumstep 1:#1..#2\_do}
\_def\fornumstep#1:#2..#3\do{\_fornumstep #1:#2..#3\_do}
@@ -304,6 +304,7 @@
\_endcode
+2021-08-02 more robust \fornum: \fi moved by \afterfi
2021-02-03 public version of \loop and \foreach are \long
2020-05-22 \foreach, \fornum: all settings are global, independent on TeX group
2020-05-06 \isnextchar: \let\tmp=#1 -> \let\tmp= #1 (bug fix, #1 should be space)
diff --git a/macros/optex/base/makeindex.opm b/macros/optex/base/makeindex.opm
index 64ff2ca228..4de0d815fd 100644
--- a/macros/optex/base/makeindex.opm
+++ b/macros/optex/base/makeindex.opm
@@ -245,10 +245,10 @@
be whatever. It does not influence the sorting. \OpTeX/ uses comma at
this place for sorting indexes: `\,<word1> \,<word2> \,<word3> ...`.
- The actual language (chosen for hyphenation patterns) is used for
- sorting data. If the `\_sortinglang` macro
- is defined as `<iso-code>`(for example `\def\sortinglang{de}`)
- then this has precedence and actual language is not used.
+ The current language (chosen for hyphenation patterns) is used for
+ sorting data. If the macro \`\_sortinglang`
+ is defined as `<iso-code>` (for example `\def\sortinglang{de}`)
+ then this has precedence and current language is not used.
Moreover, if you specify \`\_asciisortingtrue` then ASCII
sorting will be processed and all language sorting data will be ignored.
\_cod -----------------------------
diff --git a/macros/optex/base/maketoc.opm b/macros/optex/base/maketoc.opm
index 8dfd821640..928618db6b 100644
--- a/macros/optex/base/maketoc.opm
+++ b/macros/optex/base/maketoc.opm
@@ -1,6 +1,6 @@
% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \maketoc {Macros for maketoc <2020-02-09>} % preloaded in format
+\_codedecl \maketoc {Macros for maketoc <2021-07-18>} % preloaded in format
\_doc ------------------------------------
\`\_Xtoc` `{<level>}{<type>}{<number>}{<o-title>}<title>` (in `.ref` file) reads
@@ -73,7 +73,8 @@
Parameters are `{<number>}{<title>}{<pageno>}`.
\_cod -----------------------------------
-\_sdef{_tocl:1}#1#2#3{\_nofirst\_bigskip \_bf\_llaptoclink{#1}{#2}\_hfill \_pgn{#3}\_tocpar}
+\_sdef{_tocl:1}#1#2#3{\_nofirst\_bigskip
+ \_bf\_llaptoclink{#1}{#2}\_nobreak\_hfill \_pgn{#3}\_tocpar}
\_sdef{_tocl:2}#1#2#3{\_llaptoclink{#1}{#2}\_tocdotfill \_pgn{#3}\_tocpar}
\_sdef{_tocl:3}#1#2#3{\_advance\_leftskip by\_iindent \_cs{_tocl:2}{#1}{#2}{#3}}
@@ -148,6 +149,7 @@
\_endcode
+2021-07-18 _tocl:1, \nobreak added, bug fixed
2021-02-09 \thisoutline implemented
2020-04-23 \_tocpar introduced (incompatible change)
2020-04-22 \_pg -> \_pgn (incompatible change)
diff --git a/macros/optex/base/math-macros.opm b/macros/optex/base/math-macros.opm
index 8a956ee2d0..83d3c5ab51 100644
--- a/macros/optex/base/math-macros.opm
+++ b/macros/optex/base/math-macros.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \sin {Math macros plus mathchardefs <2021-04-25>} % preloaded in format
+\_codedecl \sin {Math macros plus mathchardefs <2021-08-02>} % preloaded in format
\_doc -----------------------------
The category code of the character `_` remains as the letter (11) and the mathocode
@@ -1059,14 +1059,15 @@
\_def\_mathbox#1{{\_mathstyles{\_hbox{%
\_ifnum\_stylenum<2 \_everymath{\_currstyle}%
\_else
- \_ifnum\_stylenum=2 \_def\_textmff{+ssty=0;}\_fi
- \_ifnum\_stylenum=3 \_def\_textmff{+ssty=1;}\_def\_scriptmff{+ssty=1;}\_fi
+ \_ifnum\_stylenum=2 \_def\_textmff{ssty=1;}\_fi
+ \_ifnum\_stylenum=3 \_def\_textmff{ssty=2;}\_def\_scriptmff{ssty=2;}\_fi
\_typoscale[\_dobystyle{}{}{700}{500}/]\_fi #1}}}%
}
\_public \mathbox ;
\_endcode %---------------------------------------------------
+2021-08-02 ssty fontfeatures rewritten
2021-04-25 \triangleright: typo fixed
2021-03-22 \(l)eqalignno: \hbox instead \llap, \rlap (\par error suppressed)
2021-03-19 allow text mode \{ and \}
diff --git a/macros/optex/base/math-unicode.opm b/macros/optex/base/math-unicode.opm
index e9ec87f30f..eaa0e72fbf 100644
--- a/macros/optex/base/math-unicode.opm
+++ b/macros/optex/base/math-unicode.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \loadmath {Unicode Math fonts <2021-04-05>} % preloaded in format
+\_codedecl \loadmath {Unicode Math fonts <2021-08-16>} % preloaded in format
\_doc -----------------------------
\`\loadmath` `{<Unicode-math font>}` loads the given font. It does:
@@ -85,9 +85,8 @@
\_setunimathdimens
}%
\_def\_setunimathdimens{% PlainTeX sets these dimens for 10pt size only:
- \_delimitershortfall=0.5\_fontdimen6\_textfont3
- \_nulldelimiterspace=0.12\_fontdimen6\_textfont3
- \_scriptspace=0.05\_fontdimen6\_textfont3
+ \_delimitershortfall=0.5\_fontdimen6\_textfont1
+ \_nulldelimiterspace=0.12\_fontdimen6\_textfont1
\_setbox0=\_hbox{\_everymath{}$\_fam1\_displaystyle{0\_atop0}$}%
\_Umathfractiondelsize\_displaystyle = \_dimexpr(\_ht0-\_Umathaxis\_displaystyle)*2\_relax
\_setbox0=\_box\_voidbox
@@ -111,18 +110,21 @@
\endtt
\`\_loadumathfamily` `<number> {<font>}{<font features>}`
- loads the given Unicode-math fonts in three sizes given by the
- \^`\setmathsizes` macro and sets it as the math family `<number>`.
+ loads the given Unicode-math fonts in three sizes
+ using single <font> with different `mathsize=1,2,3` font features.
+ The math font family is set with given `<number>`.
The `<font features>` are added to the default
- \`\_mfontfeatures` and to the size-dependent features `+ssty=0`
- if script size is asked or `+ssty=1` if scriptscriptsize is asked.
- If the math family 1 is loaded then the family 2 and 3 are set by the same
- font because \TeX/ needs to read dimension information about generating
- math formulae from these three math families. All information needed by
- \TeX/ is collected in single Unicode-math font.\nl
+ \`\_mfontfeatures` and to the size-dependent features `ssty=1`
+ if script size is asked or `ssty=2` if scriptscriptsize is asked.\nl
+ \`\_mparams``<number>` inserts additional font feature `nomathparam`
+ if the <number> of the family is greater than 3. Lua\TeX/ sets math
+ parameters (thickness of fraction rules etc., see section 7.4 in Lua\TeX/
+ documentation) repeatedly from loaded math
+ fonts if `nomathparam` is not given. We want to load these parameters only
+ from fonts at families 0--3 (and actually we are using only family 1 as main math font).\nl
The \^`\_corrmsize` `<factor><space>` can be used just before
`\_loadumathfamily`, see section~\ref[math-preload] for more information.\nl
- The \`\_textmff`, \`\_scriptmff` and \`\_sscriptmff` are additional font
+ The \`\_textmff`, \`\_scriptmff` and \`\_sscriptmff` are font
features for text, script and sscript sizes respectively. They are
locally re-defined in \^`\mathbox` macro.
\_cod -----------------------------
@@ -131,16 +133,15 @@
\_def\_mfontfeatures{mode=base;script=math;}
\_def\_loadumathfamily #1 #2#3 {%
- \_edef\_optsizesave{\_the\_optsize}%
- \_optsize=\_sizemtext \_font\_mF=\_umathname{#2}{\_textmff #3} at\_optsize
- \_textfont#1=\_mF \_ifnum#1=1 \_textfont2=\_mF \_textfont3=\_mF \_fi
- \_optsize=\_sizemscript \_font\_mF=\_umathname{#2}{\_scriptmff #3} at\_optsize
- \_scriptfont#1=\_mF \_ifnum#1=1 \_scriptfont2=\_mF \_scriptfont3=\_mF \_fi
- \_optsize=\_sizemsscript \_font\_mF=\_umathname{#2}{\_sscriptmff #3} at\_optsize
- \_scriptscriptfont#1=\_mF \_ifnum#1=1 \_scriptscriptfont2=\_mF \_scriptscriptfont3=\_mF \_fi
- \_optsize=\_optsizesave \_ptmunit=\_ptunit
+ \_font\_mF=\_umathname{#2}{\_textmff \_mparams{#1}#3} at\_sizemtext \_textfont #1=\_mF
+ \_font\_mF=\_umathname{#2}{\_scriptmff \_mparams{#1}#3} at\_sizemtext \_scriptfont #1=\_mF
+ \_font\_mF=\_umathname{#2}{\_sscriptmff\_mparams{#1}#3} at\_sizemtext \_scriptscriptfont#1=\_mF
+ \_ptmunit=\_ptunit
}
-\_def\_textmff{} \_def\_scriptmff{+ssty=0;} \_def\_sscriptmff{+ssty=1;}
+\_def\_textmff {ssty=0;mathsize=1;}
+\_def\_scriptmff {ssty=1;mathsize=2;}
+\_def\_sscriptmff{ssty=2;mathsize=3;}
+\_def\_mparams#1{\_ifnum#1>3 nomathparam;\_fi}
\_doc -----------------------------
Unicode math font includes all typical math alphabets together, user needs not to
@@ -258,6 +259,9 @@ the section~\ref[math-macros].
\_endinput
+2021-08-16 \_loadumathfamily simplified, used mathsize= font feature.
+2021-08-16 nomathparam font feature used for families > 3 (bug fixed).
+2021-08-02 ssty fontfeatures rewritten; fam2, fam3 unused, \scriptspace not set
2021-04-04 \_setunimathdimens: \setbox0=\box\voidbox added
2021-03-09 \_setunimathdimes: \_begin/end/group instead {}, bug fixed
2021-02-15 \_textmff, \_scriptmff and \_sscriptmff introduced
diff --git a/macros/optex/base/optex.ini b/macros/optex/base/optex.ini
index be081adac8..e51a8824df 100644
--- a/macros/optex/base/optex.ini
+++ b/macros/optex/base/optex.ini
@@ -21,7 +21,7 @@
% OpTeX version
-\def\optexversion{1.03 Jun.2021}
+\def\optexversion{1.04 Aug.2021}
\def\fmtname{OpTeX}
\let\fmtversion=\optexversion
@@ -95,13 +95,13 @@
\_everyjob = {%
\_message{This is OpTeX (Olsak's Plain TeX), version <\optexversion>^^J}%
- \_mathchardef\_fnotestack=\_pdfcolorstackinit page {0 g 0 G}%
\_directlua{lua.bytecode[1]()}% load OpTeX's Lua code
\_mathsbon % replaces \int_a^b to \int _a^b
\_inputref % inputs \jobname.ref if exists
}
-\_dump
+\dump % You can redefine \dump if additional macros are needed. Example:
+ % \let\dump=\relax \input optex.ini \input mymacros \_dump
\_endcode % ------------------------------
diff --git a/macros/optex/base/optex.lua b/macros/optex/base/optex.lua
index 3738acaefb..5114ea21e9 100644
--- a/macros/optex/base/optex.lua
+++ b/macros/optex/base/optex.lua
@@ -2,7 +2,11 @@
-- The basic lua functions and declarations used in \OpTeX/ are here
--- GENERAL
+-- \medskip\secc General^^M
+--
+-- Define namespace where some \OpTeX/ functions will be added.
+
+optex = optex or {}
-- Error function used by following functions for critical errors.
local function err(message)
@@ -15,7 +19,17 @@ function registernumber(name)
return token.create(name).index
end
--
--- ALLOCATORS
+-- MD5 hash of given file.
+function mdfive(file)
+ local fh = io.open(file, "rb")
+ if fh then
+ local data = fh:read("*a")
+ fh:close()
+ tex.print(md5.sumhexa(data))
+ end
+end
+--
+-- \medskip\secc[lua-alloc] Allocators^^M
alloc = alloc or {}
--
-- An attribute allocator in Lua that cooperates with normal \OpTeX/ allocator.
@@ -32,10 +46,20 @@ function alloc.new_attribute(name)
end
end
--
+-- Allocator for Lua functions ("pseudoprimitives"). It passes variadic
+-- arguments (\"`...`") like `"global"` to `token.set_lua`.
+local function_table = lua.get_functions_table()
+local luafnalloc = 0
+function define_lua_command(csname, fn, ...)
+ luafnalloc = luafnalloc + 1
+ token.set_lua(csname, luafnalloc, ...) -- WARNING: needs LuaTeX 1.08 (2019) or newer
+ function_table[luafnalloc] = fn
+end
+--
-- `provides_module` is needed by older version of luaotfload
provides_module = function() end
--
--- CALLBACKS
+-- \medskip\secc[callbacks] Callbacks^^M
callback = callback or {}
--
-- Save `callback.register` function for internal use.
@@ -181,6 +205,7 @@ end
-- callbacks, that are called manually by user using `call_callback` or for
-- standard callbacks that have default functions -- like `mlist_to_hlist` (see
-- below).
+local call_callback
function callback.add_to_callback(name, fn, description)
if user_callbacks[name] or callback_functions[name] or default_functions[name] then
-- either:
@@ -193,9 +218,9 @@ function callback.add_to_callback(name, fn, description)
-- register a proxy function as a real callback. Assert, so we know
-- when things break, like when callbacks get redefined by future
-- luatex.
- assert(callback_register(name, function(...)
- return callback.call_callback(name, ...)
- end))
+ callback_register(name, function(...)
+ return call_callback(name, ...)
+ end)
else
err("cannot add to callback '"..name.."' - no such callback exists")
end
@@ -307,6 +332,7 @@ function callback.call_callback(name, ...)
end
return not changed or head
end
+call_callback = callback.call_callback
--
-- Create \"virtual" callbacks `pre/post_mlist_to_hlist_filter` by setting
-- `mlist_to_hlist` callback. The default behaviour of `mlist_to_hlist` is kept by
@@ -317,7 +343,7 @@ callback.create_callback("pre_mlist_to_hlist_filter", "list")
callback.create_callback("post_mlist_to_hlist_filter", "reverselist")
callback_register("mlist_to_hlist", function(head, ...)
-- pre_mlist_to_hlist_filter
- local new_head = callback.call_callback("pre_mlist_to_hlist_filter", head, ...)
+ local new_head = call_callback("pre_mlist_to_hlist_filter", head, ...)
if new_head == false then
node.flush_list(head)
return nil
@@ -326,9 +352,9 @@ callback_register("mlist_to_hlist", function(head, ...)
end
-- mlist_to_hlist means either added functions or standard luatex behavior
-- of node.mlist_to_hlist (handled by default function)
- head = callback.call_callback("mlist_to_hlist", head, ...)
+ head = call_callback("mlist_to_hlist", head, ...)
-- post_mlist_to_hlist_filter
- new_head = callback.call_callback("post_mlist_to_hlist_filter", head, ...)
+ new_head = call_callback("post_mlist_to_hlist_filter", head, ...)
if new_head == false then
node.flush_list(head)
return nil
@@ -338,6 +364,27 @@ callback_register("mlist_to_hlist", function(head, ...)
return head
end)
--
+-- For preprocessing boxes just before shipout we define custom callback. This
+-- is used for coloring based on attributes.
+-- There is however a challenge - how to call this callback? We could redefine
+-- `\shipout` and `\pdfxform` (which both run `ship_out` procedure internally),
+-- but they would lose their primtive meaning – i.e. `\immediate` wouldn't work
+-- with `\pdfxform`. The compromise is to require anyone to run
+-- \`\_preshipout``<destination box number><box specification>` just before
+-- `\shipout` or `\pdfxform` if they want to call `pre_shipout_filter` (and
+-- achieve colors and possibly more).
+callback.create_callback("pre_shipout_filter", "list")
+
+local tex_setbox = tex.setbox
+local token_scanint = token.scan_int
+local token_scanlist = token.scan_list
+define_lua_command("_preshipout", function()
+ local boxnum = token_scanint()
+ local head = token_scanlist()
+ head = call_callback("pre_shipout_filter", head)
+ tex_setbox(boxnum, head)
+end)
+--
-- Compatibility with \LaTeX/ through luatexbase namespace. Needed for
-- luaotfload.
luatexbase = {
@@ -352,3 +399,206 @@ luatexbase = {
call_callback = callback.call_callback,
callbacktypes = {}
}
+--
+-- `\tracingmacros` callback registered.
+-- Use `\tracingmacros=3` or `\tracingmacros=4` if you want to see the result.
+callback.add_to_callback("input_level_string", function(n)
+ if tex.tracingmacros > 3 then
+ return "[" .. n .. "] "
+ elseif tex.tracingmacros > 2 then
+ return "~" .. string.rep(".",n)
+ else
+ return ""
+ end
+end, "_tracingmacros")
+--
+-- \medskip\secc[lua-colors] Handling of colors using attributes^^M
+--
+-- Because \LuaTeX/ doesn't do anything with attributes, we have to add meaning
+-- to them. We do this by intercepting \TeX/ just before it ships out a page and
+-- inject PDF literals according to attributes.
+--
+local node_id = node.id
+local glyph_id = node_id("glyph")
+local rule_id = node_id("rule")
+local glue_id = node_id("glue")
+local hlist_id = node_id("hlist")
+local vlist_id = node_id("vlist")
+local disc_id = node_id("disc")
+local token_getmacro = token.get_macro
+
+local direct = node.direct
+local todirect = direct.todirect
+local tonode = direct.tonode
+local getfield = direct.getfield
+local setfield = direct.setfield
+local getwhd = direct.getwhd
+local getid = direct.getid
+local getlist = direct.getlist
+local setlist = direct.setlist
+local getleader = direct.getleader
+local getattribute = direct.get_attribute
+local insertbefore = direct.insert_before
+local copy = direct.copy
+local traverse = direct.traverse
+local one_bp = tex.sp("1bp")
+local string_format = string.format
+--
+-- The attribute for coloring is allocated in `colors.opm`
+local color_attribute = registernumber("_colorattr")
+--
+-- Now we define function which creates whatsit nodes with PDF literals. We do
+-- this by creating a base literal, which we then copy and customize.
+--
+local pdf_base_literal = direct.new("whatsit", "pdf_literal")
+setfield(pdf_base_literal, "mode", 2) -- direct mode
+local function pdfliteral(str)
+ local literal = copy(pdf_base_literal)
+ setfield(literal, "data", str)
+ return literal
+end
+optex.directpdfliteral = pdfliteral
+--
+-- The function {\Red`colorize`}`(head, current, current_stroke)` goes through
+-- a node list and injects PDF literals according to attributes.
+-- Its arguments are the head of the list to be colored and the current color
+-- for fills and strokes. It is a recursive function – nested
+-- horizontal and vertical lists are handled in the same way. Only the
+-- attributes of “content” nodes (glyphs, rules, etc.) matter. Users drawing
+-- with PDF literals have to set color themselves.
+--
+-- Whatsit node with color setting PDF literal is injected only when a
+-- different color is needed. Our injection does not care about boxing levels,
+-- but this isn't a problem, since PDF literal whatsits just instruct the
+-- `\shipout` related procedures to emit the literal.
+--
+-- We also set the stroke and non-stroke colors separately. This is because
+-- stroke color is not always needed – \LuaTeX/ itself only uses it for rules
+-- whose one dimension is less than or equal to 1 bp and for fonts whose `mode`
+-- is set to 1 (outline) or 2 (outline and fill). Catching these cases is a
+-- little bit involved. For example rules are problematic, because at this
+-- point their dimensions can still be running ($-2^{30}$) – they may or may
+-- not be below the one big point limit. Also the text direction is involved.
+-- Because of the negative value for running dimensions the simplistic check,
+-- while not fully correct, should produce the right results. We currently
+-- don't check for the font mode at all.
+--
+-- Leaders (represented by glue nodes with leader field) are not handled fully.
+-- They are problematic, because their content is repeated more times and it
+-- would have to be ensured that the coloring would be right even for e.g.
+-- leaders that start and end on a different color. We came to conclusion that
+-- this is not worth, hence leaders are handled just opaquely and only the
+-- attribute of the glue node itself is checked. For setting different colors
+-- inside leaders, raw PDF literals have to be used.
+--
+-- We use the `node.direct` way of working with nodes. This is less safe, and
+-- certainly not idiomatic Lua, but faster and codewise more close to the way
+-- \TeX/ works with nodes.
+local function is_color_needed(head, n, id, subtype) -- returns non-stroke, stroke color needed
+ if id == glyph_id then
+ return true, false
+ elseif id == glue_id then
+ n = getleader(n)
+ if n then
+ id = getid(n)
+ if id == hlist_id or id == vlist_id then
+ -- leaders with hlist/vlist get single color
+ return true, false
+ else -- rule
+ -- stretchy leaders with rules are tricky,
+ -- just set both colors for safety
+ return true, true
+ end
+ end
+ elseif id == rule_id then
+ local width, height, depth = getwhd(n)
+ if width <= one_bp or height + depth <= one_bp then
+ -- running (-2^30) may need both
+ return true, true
+ end
+ return true, false
+ end
+ return false, false
+end
+
+local function colorize(head, current, current_stroke)
+ for n, id, subtype in traverse(head) do
+ if id == hlist_id or id == vlist_id then
+ -- nested list, just recurse
+ local list = getlist(n)
+ list, current, current_stroke = colorize(list, current, current_stroke)
+ setlist(n, list)
+ elseif id == disc_id then
+ -- at this point only no-break (replace) list is of any interest
+ local replace = getfield(n, "replace")
+ if replace then
+ replace, current, current_stroke = colorize(replace, current, current_stroke)
+ setfield(n, "replace", replace)
+ end
+ else
+ local nonstroke_needed, stroke_needed = is_color_needed(head, n, id, subtype)
+ local new = getattribute(n, color_attribute) or 0
+ local newcolor = nil
+ if current ~= new and nonstroke_needed then
+ newcolor = token_getmacro("_color:"..new)
+ current = new
+ end
+ if current_stroke ~= new and stroke_needed then
+ local stroke_color = token_getmacro("_color-s:"..current)
+ if stroke_color then
+ if newcolor then
+ newcolor = string_format("%s %s", newcolor, stroke_color)
+ else
+ newcolor = stroke_color
+ end
+ current_stroke = new
+ end
+ end
+ if newcolor then
+ head = insertbefore(head, n, pdfliteral(newcolor))
+ end
+ end
+ end
+ return head, current, current_stroke
+end
+--
+-- Colorization should be run just before shipout. We use our custom callback
+-- for this. See the definition of `pre_shipout_filter` for details on
+-- limitations.
+callback.add_to_callback("pre_shipout_filter", function(list)
+ -- By setting initial color to -1 we force initial setting of color on
+ -- every page. This is useful for transparently supporting other default
+ -- colors than black (although it has a price for each normal document).
+ local list = colorize(todirect(list), -1, -1)
+ return tonode(list)
+end, "_colors")
+--
+-- We also hook into `luaotfload`'s handling of color. Instead of the default
+-- behavior (inserting colorstack whatsits) we set our own attribute. The hook
+-- has to be registered {\em after} `luaotfload` is loaded.
+function optex_hook_into_luaotfload()
+ if not luaotfload.set_colorhandler then
+ return -- old luaotfload, colored fonts will be broken
+ end
+ local setattribute = direct.set_attribute
+ local token_setmacro = token.set_macro
+ local color_count = registernumber("_colorcnt")
+ local tex_getcount, tex_setcount = tex.getcount, tex.setcount
+ luaotfload.set_colorhandler(function(head, n, rgbcolor) -- rgbcolor = "1 0 0 rg"
+ local attr = tonumber(token_getmacro("_color::"..rgbcolor))
+ if not attr then
+ attr = tex_getcount(color_count)
+ tex_setcount(color_count, attr + 1)
+ local strattr = tostring(attr)
+ token_setmacro("_color::"..rgbcolor, strattr)
+ token_setmacro("_color:"..strattr, rgbcolor)
+ -- no stroke color set
+ end
+ setattribute(n, color_attribute, attr)
+ return head, n
+ end)
+end
+
+ -- History:
+ -- 2021-07-16 support for colors via attributes added
+ -- 2020-11-11 optex.lua released
diff --git a/macros/optex/base/others.opm b/macros/optex/base/others.opm
index 6ff15d4332..a6dc2064eb 100644
--- a/macros/optex/base/others.opm
+++ b/macros/optex/base/others.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \uv {Miscenaleous <2020-05-22>} % preloaded in format
+\_codedecl \uv {Miscenaleous <2020-08-02>} % preloaded in format
\_doc ----------------------------
\`\useOpTeX` and \`\useoptex` are declared as `\relax`.
@@ -92,6 +92,7 @@
\_def\_lipsumload{{%
\_setbox0=\_vbox{\_tmpnum=0 % vertical mode during \input lipsum.ltd.tex
\_def\ProvidesFile##1[##2]{}%
+ \_def\SetLipsumLanguage##1{}%
\_def\NewLipsumPar{\_incr\_tmpnum \_sxdef{_lip:\_the\_tmpnum}}%
\_opinput {lipsum.ltd.tex}%
\_global\_let\_lipsumload=\_empty
@@ -101,6 +102,7 @@
\_endcode
+2021-08-02 \SetLipsumLanguage added, fix for new lipusm version
2021-01-04 \lipsumtext introduced
2020-05-22 \lipsum uses \fornum (expandable after first usage)
2020-04-02 released
diff --git a/macros/optex/base/output.opm b/macros/optex/base/output.opm
index 5bb93c2477..ffe41c5387 100644
--- a/macros/optex/base/output.opm
+++ b/macros/optex/base/output.opm
@@ -1,13 +1,17 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \nopagenumbers {Output routine <2021-02-25>} % preloaded in format
+\_codedecl \nopagenumbers {Output routine <2021-07-16>} % preloaded in format
\_doc -----------------------------
- \`\_optexoutput` is the default output routine. You can create another...
+ \`\_optexoutput` is the default output routine. You can create another...\nl
+ The \^`\_preshipout``<destination box number><box specification>` used
+ here behaves similarly like `\setbox` but it does not only copy the box
+ contents but adds the color literals depending on used attributes.
+ It is defined using lua code, see section~\ref[lua].
\_cod -----------------------------
\_output={\_optexoutput}
-\_def \_optexoutput{\_begoutput \_shipout\_completepage \_endoutput}
+\_def \_optexoutput{\_begoutput \_preshipout0\_completepage \_shipout\_box0 \_endoutput}
\_doc -----------------------------
Default \`\_begoutput` and \`\_endoutput` is defined.
@@ -58,24 +62,19 @@
The \`\_completepage` is similar to what plain \TeX/ does in its output routine.
New is only \`\_backgroundbox`. It is `\vbox` with zero height with its
contents (from \^`\pgbackground`) extended down. It is shifted directly to the
- left-upper corner of the paper.
-
- The \`\_ensureblack` sets the typesetting of its parameter locally to `\Black`
- color. We needn't do this if colors are never used in the document. So,
- the default value of the `\_ensureblack` macro is empty. But the first usage of
- color macros in the document re-defines `\_ensureblack`.
- See the section~\ref[colors] for more details.
+ left-upper corner of the paper.\nl
+ The \^`\_resetcolor` used here means that all newly created texts in
+ output routine (texts used in headline, footline) have default color.
\_cod -----------------------------
\_def\_completepage{\_vbox{%
+ \_resetcolor
\_istoksempty \_pgbackground
- \_iffalse \_ensureblack{\_backgroundbox{\_the\_pgbackground}}\_nointerlineskip \_fi
- \_ensureblack{\_makeheadline}%
+ \_iffalse \_backgroundbox{\_the\_pgbackground}\_nointerlineskip \_fi
+ \_makeheadline
\_vbox to\_vsize {\_boxmaxdepth=\_maxdepth \_pagecontents}% \pagebody in plainTeX
- \_ensureblack{\_makefootline}}%
+ \_makefootline}%
}
-\_def \_ensureblack #1{#1} % will be re-defined by color macros
-\_let \_openfnotestack = \_relax % will be re-defined by color macros
\_def \_backgroundbox #1{\_moveleft\_hoffset\_vbox to\_zo{\_kern-\_voffset #1\_vss}}
\_doc -----------------------------
@@ -102,17 +101,16 @@
\_doc -----------------------------
The \`\_pagecontents` is similar as in plain \TeX/. The only differnece is
- that the \`\_pagedest` is inserted at the top of `\_pagecontents` and
- \^`\_ensureblack` is applied to the \^`\topins` and \^`\footins` material.\nl
+ that the \`\_pagedest` is inserted at the top of `\_pagecontents`.\nl
The \`\_footnoterule` is defined here.
\_cod -----------------------------
\_def\_pagecontents{\_pagedest % destination of the page
- \_ifvoid\_topins \_else \_ensureblack{\_unvbox\_topins}\_fi
+ \_ifvoid\_topins \_else \_unvbox\_topins\_fi
\_dimen0=\_dp255 \_unvbox255 % open up \box255
\_ifvoid\_footins \_else % footnote info is present
\_vskip\_skip\_footins
- \_ensureblack{\_footnoterule \_openfnotestack \_unvbox\_footins}\_fi
+ \_footnoterule \_unvbox\_footins\_fi
\_kern-\_dimen0 \_vskip \_pgbottomskip
}
\_def \_pagedest {{\_def\_destheight{25pt}\_dest[pg:\_the\_gpageno]}}
@@ -157,7 +155,7 @@
\_def \_opfootnote #1#2{\_insert\_footins\_bgroup
\_interlinepenalty=\_interfootnotelinepenalty
\_leftskip=\_zo \_rightskip=\_zo \_spaceskip=\_zo \_xspaceskip=\_zo \_relax
- \_let\_colorstackcnt=\_fnotestack % special color stack for footnotes
+ \_resetcolor
#1\_relax % local settings used by \fnote macro
\_splittopskip=\_ht\_strutbox % top baseline for broken footnotes
\_splitmaxdepth=\_dp\_strutbox \_floatingpenalty=20000
@@ -165,10 +163,8 @@
\_isnextchar \_bgroup
{\_bgroup \_aftergroup\_vfootA \_afterassignment\_ignorespaces \_let\_next=}{\_vfootB}%
}
-\_def\_vfootA{\_unskip\_strut\_isnextchar\_colorstackpop\_closefncolor\_vfootF}
-\_def\_vfootB #1{#1\_unskip\_strut\_vfootF}
-\_def\_vfootF{\_egroup} % close \_insert\_footins\_bgroup
-\_def\_closefncolor#1{#1\_isnextchar\_colorstackpop\_closefncolor\_vfootF}
+\_def\_vfootA{\_unskip\_strut\_egroup}
+\_def\_vfootB #1{#1\_unskip\_strut\_egroup}
\_def \_footstrut {\_vbox to\_splittopskip{}}
\_skip\_footins=\_bigskipamount % space added when footnote is present
\_count\_footins=1000 % footnote magnification factor (1 to 1)
@@ -190,7 +186,7 @@
\_skip\_topins=\_zoskip % no space added when a topinsert is present
\_count\_topins=1000 % magnification factor (1 to 1)
\_dimen\_topins=\_maxdimen % no limit per page
-\_def \_oins {\_par \_begingroup\_setbox0=\_vbox\_bgroup} % start a \_vbox
+\_def \_oins {\_par \_begingroup\_setbox0=\_vbox\_bgroup\_resetcolor} % start a \_vbox
\_def \_endinsert {\_par\_egroup % finish the \_vbox
\_ifumid \_dimen0=\_ht0 \_advance\_dimen0 by\_dp0 \_advance\_dimen0 by\_baselineskip
\_advance\_dimen0 by\_pagetotal \_advance\_dimen0 by-\_pageshrink
@@ -214,11 +210,11 @@
\_fontdef\_draftfont{\_setfontsize{at10pt}\_bf}%
\_global\_let\_draftfont=\_draftfont
}
-\_def \_draftbox #1{\_setbox0=\_hbox{#1}%
+\_def \_draftbox #1{\_setbox0=\_hbox{\_setgreycolor{.8}#1}%
\_kern.5\_vsize \_kern\_voffset \_kern4.5\_wd0
\_hbox to0pt{\_kern.5\_xhsize \_kern\_hoffset \_kern-2\_wd0
\_pdfsave \_pdfrotate{55}\_pdfscale{10}{10}%
- \_hbox to0pt{\_localcolor\_setgreycolor{.8}\_box0\_hss}%
+ \_hbox to0pt{\_box0\_hss}%
\_pdfrestore
\_hss}%
}
@@ -261,6 +257,7 @@ The output routine \^`\_optexoutput` is similar as in plain \TeX. It does:
\_endinput
+2021-07-16 output routine supports colors via attributes
2021-02-25 \_draftbox improved
2021-02-15 \_advance -> \_decr
2020-05-12 \vfootB: \uskip -> \unskip bug fixed
diff --git a/macros/optex/base/parameters.opm b/macros/optex/base/parameters.opm
index e03bef6ef3..5379617d6c 100644
--- a/macros/optex/base/parameters.opm
+++ b/macros/optex/base/parameters.opm
@@ -58,7 +58,7 @@
\_doc -----------------------------
\secc Plain \TeX/ registers
- Declared registers used in plain \TeX/
+ Allocate registers that are used just like in plain \TeX/.
\_cod -----------------------------
% We also define special registers that function like parameters:
@@ -100,14 +100,14 @@
\_normalbaselines % baseline setting, 10 pt font size
\_doc -----------------------------
- Different values than in plain \TeX/ have the following primitive registers.
+ The following primitive registers have different values than in plain \TeX/.
We prohibit orphans, set more information for tracing boxes, set page origin
to the upper left corner of the paper (no at 1\,in, 1\,in coordinates)
- and set default page dimensions as A4, no letter.
+ and set default page dimensions as A4, not letter.
\_cod -----------------------------
-\_emergencystretch=20pt % we want to use third pass of paragraph building algoritmh
- % we need not keep the compatibility with old documents
+\_emergencystretch=20pt % we want to use third pass of paragraph building algorithm
+ % we don't need compatibility with old documents
\_clubpenalty=10000 % after first line of paragraph
\_widowpenalty=10000 % before last line of paragraph
@@ -115,10 +115,10 @@
\_showboxbreadth=150 % for tracing boxes
\_showboxdepth=7
\_errorcontextlines=15
-\_tracinglostchars=2 % missing chracter warnings on terminal too
+\_tracinglostchars=2 % missing character warnings on terminal too
-\_outputmode=1 % PDF ouput
-\_pdfvorigin=0pt % orgin is exatly at left upper corner
+\_outputmode=1 % PDF output
+\_pdfvorigin=0pt % origin is exactly at upper left corner
\_pdfhorigin=0pt
\_hoffset=25mm % margins are 2.5cm, no 1in
\_voffset=25mm
@@ -374,7 +374,7 @@
\_newtoks\_everymnote
\_newdimen\_mnotesize \_mnotesize=20mm % the width of the mnote paragraph
-\_newdimen\_mnoteindent \_mnoteindent=10pt % ditance between mnote and text
+\_newdimen\_mnoteindent \_mnoteindent=10pt % distance between mnote and text
\_public \everymnote \mnotesize \mnoteindent ;
\_doc -----------------------------
@@ -428,8 +428,8 @@
\_doc -----------------------------
The \^`\eqalign` macro can be configured by \`\eqlines` and \`\eqstyle`
- tokens lists. The default values are set in order these macro beahaves
- as in Plain \TeX. The \`\eqspace` is horizontal space put
+ tokens lists. The default values are set in order these macro behaves
+ like in Plain \TeX. The \`\eqspace` is horizontal space put
between equation systems if more columns in \^`\eqalign` are used.
\_cod -----------------------------
@@ -447,8 +447,8 @@
\_public \lmfil ;
\_doc -----------------------------
- The output routine uses token list \`\headline` and \`\footline` in the
- same sense as in plain \TeX/. If they are non-empty then `\hfil` or `\hss`
+ The output routine uses token lists \`\headline` and \`\footline` in the
+ same sense as plain \TeX/ does. If they are non-empty then `\hfil` or `\hss`
must be here because they are used inside `\hbox to\hsize`.
Assume that page-body text can be typeset in different sizes and
diff --git a/macros/optex/base/prefixed.opm b/macros/optex/base/prefixed.opm
index f8edf5d135..6dec64c7e5 100644
--- a/macros/optex/base/prefixed.opm
+++ b/macros/optex/base/prefixed.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \public {Prefixing and code syntax <2020-02-25>} % preloaded in format
+\_codedecl \public {Prefixing and code syntax <2021-08-16>} % preloaded in format
\_doc ---------
All \TeX/ primitives have alternative control sequence `\_hbox` `\_string`, ...
@@ -61,17 +61,18 @@
such file more than once. Else the <info> is printed to the terminal
and the file is read.\nl
The {\`\_endcode`} is defined as `\endinput` in the `optex.ini` file.
- \`\wterm` `{<text>}` prints `<text>`
- to the terminal and to the `.log` file (as in plain \TeX/).
+ \`\wterm` `{<text>}` prints the `<text>` to the terminal and to the `.log` file,
+ \`\wlog` `{<text>}` prints the `<text>` only to the `.log` file (as in plain \TeX)
\_cod -----------------------
\_def \_codedecl #1#2{%
- \_ifx #1\_undefined \_wterm{#2}%
+ \_ifx #1\_undefined \_wlog{#2}%
\_else \_ea \_endinput \_fi
}
\_def \_wterm {\_immediate \_write16 }
+\_def \_wlog {\_immediate\_write-1 } % write on log file (only)
-\_public \wterm ;
+\_public \wterm \wlog ;
\_doc ------------------------
The `\optexversion` and `\fmtname` are defined in the `optex.ini` file.
@@ -314,6 +315,7 @@ can look like.
\endinput
+2021-08-16 \_wlog moved from basic macros, \_codedecl uses \_wlog only.
2021-04-25 \_checkexists introduced
2021-02-15 \_expandafter -> \_ea in \_codedecl
2020-02-14 released
diff --git a/macros/optex/base/ref-file.opm b/macros/optex/base/ref-file.opm
index 8c459f7de5..95e960bc12 100644
--- a/macros/optex/base/ref-file.opm
+++ b/macros/optex/base/ref-file.opm
@@ -1,85 +1,97 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \openref {File for references <2021-04-13>} % preloaded in format
+\_codedecl \openref {File for references <2021-07-19>} % preloaded in format
\_doc --------------------------
- The \`\_inputref` macro is used in `\everyjob`. It reads `\jobname.ref` file
- if it exists. After the file is read then it is removed and opened to write
- a new contents to this file.
+ The \`\_inputref` macro is executed in `\everyjob`. It reads the
+ `\jobname.ref` file, if it exists. After the file is read then it is removed
+ and opened for writing.
\_cod --------------------------
\_newwrite\_reffile
\_def\_inputref {%
\_isfile{\_jobname.ref}\_iftrue
- \_input {\_jobname.ref}
+ \_input {\_jobname.ref}%
+ \_edef\_prevrefhash{\_mdfive{\_jobname.ref}}%
\_gfnotenum=0 \_lfnotenum=0 \_mnotenum=0
- \_openrefA{\_string\_inputref}%
+ \_openref
\_fi
}
\_doc --------------------------
- If the file does not exist then it is not created by default. It means that if you
+ \`\_mdfive``{<file>}` expands to the MD5 hash of a given file.
+ We use it to do consistency checking of the `.ref` file. First, we read the MD5 hash
+ of `.ref` file from previous \TeX/ run before it is removed and opened for
+ writing again in the \^`\_inputref` macro. The hash is saved to \`\_prevrefhash`.
+ Second, we read the MD5 hash in the \^`\_byehook` macro again and if
+ these hashes differ, warning that \"ref file has changed" is
+ printed. Try running `optex op-demo` twice to see the effect.
+ \_cod --------------------------
+
+\_def\_mdfive#1{\_directlua{mdfive("#1")}}
+\_def\_prevrefhash{}
+
+ \_doc --------------------------
+ If the `.ref` file does not exist, then it is not created by default. This means that if you
process a document without any forward references then no `\jobname.ref`
- file is created because it is unusable. The \^`\_wref` macro is a dummy in
- this case.
+ file is created (it would be unusable). The \^`\_wref` macro is a dummy in
+ that case.
\_cod --------------------------
\_def\_wrefrelax#1#2{}
\_let\_wref=\_wrefrelax
\_doc ---------------------
- If a macro needs to create and to use `.ref` file then such macro must use
- \`\openref`. When the file is created (using internal \`\_openrefA`) then
- the \`\_wref` `\<macro>{<data>}` is redefined in order to
- save the line `\<macro><data>` to the `.ref` file using asynchronous
- `\write` primitive. Finally, the `\_openref` destroys itself, because we
- need not open the file again.\nl
- The `\_wref``<csname>{<params>}` does exactly `\write\_reffile{\string<csname><params>}`
- in this case and \`\_ewref``<csname>{<params>}` does
+ If a macro needs to create and use the `.ref` file, then such macro must
+ first use \`\openref`. It creates the file and redefines
+ \`\_wref` `\<macro>{<data>}` so that it
+ saves the line `\<macro><data>` to the `.ref` file using the asynchronous
+ `\write` primitive. Finally, `\_openref` destroys itself, because we
+ don't need to open the file again.\nl
+ `\_wref``<csname>{<params>}` in fact does `\write\_reffile{\string<csname><params>}`
+ and similarly \`\_ewref``<csname>{<params>}` does
`\write\_reffile{\string<csname><expanded-params>}`.
\_cod ---------------------
\_def\_openref {%
- \_ifx \_wref\_wrefrelax \_openrefA{\_string\openref}\_fi
- \_gdef\_openref{}%
-}
-\_def\_openrefA #1{%
\_immediate\_openout\_reffile="\_jobname.ref"\_relax
\_gdef\_wref ##1##2{\_write\_reffile{\_bslash\_csstring##1##2}}%
- \_immediate\_write\_reffile {\_pcent\_pcent\_space OPTeX <\_optexversion> - REF file (#1)}%
+ \_immediate\_write\_reffile {\_pcent\_pcent\_space OpTeX <\_optexversion> - REF file}%
\_immediate\_wref \Xrefversion{{\_REFversion}}%
+ \_gdef\_openref{}%
}
\_def\_ewref #1#2{\_edef\_ewrefA{#2}\_ea\_wref\_ea#1\_ea{\_ewrefA}}
\_def\openref{\_openref}
\_doc ----------------------
We are using the convention that the macros used in `.ref` file are named
- `\_X<foo>`. If there is a new version of \OpTeX/ with a different collection
- of such macros then we don't want to read the `.ref` files produced by an
- old version of \OpTeX/ or by OPmac. So the first line of `.ref` file is in
- the form
+ `\_X<foo>`.
+ We don't want to read `.ref` files from old, incompatible versions of
+ \OpTeX/ (and OPmac). This is ensured by using a version number and the
+ \`\Xrefversion` macro at the beginning of the `.ref` file:
\begtt \catcode`\<=13
\Xrefversion{<version>}
\endtt
- We can check the version compatibility by this macro.
+ The macro checks the version compatibility.
Because OPmac does not understand `\_Xrefversion` we use
- \`\Xrefversion` (with a different number of `<version>` form OPmac) here.
- The result: OPmac skips the `.ref` files produced by \OpTeX/ and vice
+ `\Xrefversion` (with a different number of `<version>` than OPmac) here.
+ The result: OPmac skips `.ref` files produced by \OpTeX/ and vice
versa.
\_cod ----------------------
-\_def\_REFversion{6} % actual version of .ref files in OpTeX
+\_def\_REFversion{6} % current version of .ref files in OpTeX
\_def\_Xrefversion#1{\_ifnum #1=\_REFversion\_relax \_else \_endinput \_fi}
\_public \Xrefversion ; % we want to ignore .ref files generated by OPmac
\_doc -----------------------
- You cannot define your special `.ref` macros before `.ref` file is read
- because it is read in `\everyjob`. But you can define such macros using
+ You cannot define your own `.ref` macros before `.ref` file is read
+ because it is read in `\everyjob`. But you can define such macros by using
\`\refdecl``{<definitions of your ref macros>}`.
- This command sends to `.ref` file your `<definitions of your ref macros>`
- immediately. Next lines in `.ref` file should include our macros. Example
- from CTUstyle2:
+ This command immediately writes `<definitions of your ref macros>` to the
+ `.ref` file. Then the next lines written to the `.ref` file can include
+ your macros.
+ An example from CTUstyle2:
\begtt
\refdecl{%
\def\totlist{} \def\toflist{}^^J
@@ -87,8 +99,8 @@
\def\Xfig#1#2#3{\addto\toflist{\tofline{#1}{#2}{#3}}}
}
\endtt
- We must read `<definition of your ref macros>` when the catcode of `#` is 12
- because we needn't duplicate each `#` in the `.ref` file.
+ We must read `<definitions of your ref macros>` while `#` has the catcode 12,
+ because we don't want to duplicate each `#` in the `.ref` file.
\_cod \_fin -----------------
\_def\_refdecl{\_bgroup \_catcode`\#=12 \_refdeclA}
@@ -100,13 +112,11 @@
\_endcode % ================================================
-
-The `.ref` file has the name `\jobname.ref` and
-it saves information about references, TOC lines, etc.
-All data needed in next \TeX/ run are saved here.
-\OpTeX/ reads this file at the beginning of the document
-(using `\everyjob`) if such file exists.
-The `.ref` file looks like:
+A so called `.ref` (`\jobname.ref`) file is used to store data that will be
+needed in the next \TeX/ run (information about references, TOC lines, etc.).
+If it exists it is read by `\everyjob`, when processing of the document starts,
+but it is not created at all if the document doesn't need any forward
+references. Here are the typical contents of a `.ref` file:
\begtt \catcode`\<=13
\Xrefversion{<ref-version>}
@@ -119,29 +129,28 @@ The `.ref` file looks like:
\_Xlabel{<label>}{<text>}
...
\endtt
-%
-where <gpageno> is internal page number globally numbered from one and
-`<pageno>` is a page number (`\the\pageno`) used in pagination (they may differ).
-Each page begins with \^`\_Xpage`.
-The `<label>` is a label used by user in `\label[<label>]` and `<text>` is a
-text which should be referenced (the number of section or table, for
-example `2.3.14`). The `<title>` is the title of the chapter (`<level>`=1,
-`<type>`=`chap`), section (`<level>`=2, `<type>`=`sec`), subsection
-(`<level>`=3, `<type>`=`secc`). The \^`\_Xpage` is written at the beginning of each
-page, the `\_Xtoc` is written when chapter or section or subsection title
-exists on the page and `\_Xlabel` when labeled object prefixed by
-`\label[<label>]` exists on the page.
-
-The `.ref` file is read when the processing of the document starts using
-`\everyjob`. It is read, removed, and opened to writing immediately.
-But the `.ref` file should be missing. If none forward references are needed
-in the document then `.ref` file is not created. For example, you only want
-to test a simple plain \TeX/ macro, you create `test.tex` file, you do
-`optex test` and you don't need to see an empty `test.ref` file in your directory.
+
+\begitems
+* \^`\_Xpage` corresponds to the beginning of a page. <gpageno> is an internal
+page number, globally numbered from one. `<pageno>` is the page number
+(`\the\pageno`) used in pagination (they may differ).
+
+* \^`\_Xtoc` corresponds to a chapter, section or subsection title on a page.
+`<title>` is the title of the chapter (`<level>`=1, `<type>`=`chap`), section
+(`<level>`=2, `<type>`=`sec`) or subsection (`<level>`=3, `<type>`=`secc`).
+
+* \^`\_Xlabel` corresponds to a labelled object on a page. `<label>` is the
+label provided by the user in \^`\label[<label>]`, while `<text>` is the text
+which should be used for the reference (section or table number, for example
+`2.3.14`).
+\enditems
+
\_endinput
History:
+2021-07-19 \openrefA merged to \openref
+2021-07-18 ref file consistency checking added
2021-04-13 \Xrefversion incremented (6), new format of \_Xbib
2021-02-05 \_ewref introduced
2020-02-14 released
diff --git a/macros/optex/base/references.opm b/macros/optex/base/references.opm
index a4c2e694db..eb884c4f1d 100644
--- a/macros/optex/base/references.opm
+++ b/macros/optex/base/references.opm
@@ -11,6 +11,12 @@
\_doc ----------------------------
Counter for the number of unresolved references \`\_unresolvedrefs`.
+ It is set but unused in OpTeX versions 1.04+. You can add the report, for
+ example:
+ \begtt
+ \_addto\_byehook{\_ifnum\_unresolvedrefs>0 \_opwarning
+ {There are \_the\_unresolvedrefs\_space unresolved references}\_fi}
+ \endtt
\_cod ----------------------------
\_newcount\_unresolvedrefs
diff --git a/macros/optex/base/slides.opm b/macros/optex/base/slides.opm
index a491d1f5ad..0fed12ac7f 100644
--- a/macros/optex/base/slides.opm
+++ b/macros/optex/base/slides.opm
@@ -53,19 +53,20 @@
\_doc -----------------------------
The \`\pshow``<num>` prints the text in invisible
(transparent) font when \^`\layernum`\code{<}`<num>`.
- The transparency is set by `\pdfpageresoyrces` primitive.
+ For transparency we need to define special graphics states.
\_cod -----------------------------
-\pdfpageresources{/ExtGState << /Invisible << /Type /ExtGState /ca 0 /CA 0 >>
- /Visible << /Type /ExtGState /ca 1 /CA 1 >> >>}
-\addto\_morepgresources{/Invisible << /Type /ExtGState /ca 0 /CA 0 >>
- /Visible << /Type /ExtGState /ca 1 /CA 1 >>}
-\def\Invisible {\_pdfliteral{/Invisible gs}}
-\def\Visible {\_pdfliteral{/Visible gs}}
-\def\Transparent {\Invisible \_aftergroup \Visible}
+\_addextgstate{/Invisible <</ca 0 /CA 0>>}
+\_addextgstate {/Visible <</ca 1 /CA 1>>}
+
+\_def\_Invisible {\_pdfliteral{/Invisible gs}}
+\_def\_Visible {\_pdfliteral{/Visible gs}}
+\_def\_Transparent {\_Invisible \_aftergroup \_Visible}
+
+\_public \Invisible \Visible \Transparent ;
\_def\_use#1#2{\_ifnum\_layernum#1\_relax#2\_fi}
-\_def\_pshow#1{\_use{=#1}\Red \_use{<#1}\Transparent \_ignorespaces}
+\_def\_pshow#1{\_use{=#1}\Red \_use{<#1}\_Transparent \_ignorespaces}
\_doc -----------------------------
The main level list of items is activated here. The `\_item:X` and
diff --git a/macros/optex/base/table.opm b/macros/optex/base/table.opm
index b29aabbf4a..d10e916bbe 100644
--- a/macros/optex/base/table.opm
+++ b/macros/optex/base/table.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \table {Basic macros for OpTeX <2021-06-03>} % preloaded in format
+\_codedecl \table {Basic macros for OpTeX <2021-08-04>} % preloaded in format
\_doc -----------------------------
The result of the \`\table``{<declaration>}{<data>}` macro is inserted into
@@ -84,16 +84,6 @@
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 create the 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
The <data> are re-tokenized by `\_scantextokens` in order to be more
robust to catcode changing inside the <data>. But inline verbatim cannot
work in special cases here like \code{`\{`} for example.
@@ -116,8 +106,7 @@
\_halign\_tablew \_tableC
\_fi \_egroup
}
-\_def\_tableC{\_ea{\_ea\_bgroup\_the\_tabdata\_egroup\_tabskip=\_tabskipr\_cr
- \_scantextokens\_ea{\_tmpb\_crcr}}}
+\_def\_tableC{\_ea{\_the\_tabdata\_tabskip=\_tabskipr\_cr \_scantextokens\_ea{\_tmpb\_crcr}}}
\_doc -----------------------------
\`\_tabreplstrings` replaces each `\crl` etc. to `\crcr\crl`.
@@ -143,11 +132,11 @@
For example, the
following result is generated when `<declaration>=|cr||cl|`.
\begtt
- tabdata: \_vrule\_the\_tabiteml\_hfil#\_unsskip\_hfil\_the\_tabitemr\_tabstrutA
- &\_the\_tabiteml\_hfil#\_unsskip\_the\_tabitemr
+ 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
+ &\_the\_tabiteml{\_hfil#\_unsskip\_hfil}\_the\_tabitemr\_tabstrutA
+ &\_the\_tabiteml{\_relax#\_unsskip\_hfil}\_the\_tabitemr\_vrule\_tabstrutA
ddlinedata: &\_dditem &\_dditem\_vvitem &\_dditem &\_dditem
\endtt
The second result in the \`\_ddlinedata` macro is a template of one row of the table
@@ -200,7 +189,7 @@
\_public \colnum ;
\_def\_addtabitemx{\_ifnum\_colnum>0
- \_addtabdata{\_egroup &\_bgroup}\_addto\_ddlinedata{&\_dditem}\_fi
+ \_addtabdata{&}\_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}}
@@ -222,44 +211,67 @@
\_doc -----------------------------
The default \"declaration letters" `c`, `l`, `r` and `p` are declared
by setting \`\_tabdeclarec`, \`\_tabdeclarel`, \`\_tabdeclarer` and
- \`\_paramtabdeclarep` macros. In general, define
+ \^`\_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.
You can declare more such \"declaration letters" if you want.
+
+ Note, that the `##` with fills are in group. The reason can be explained
+ by following example:
+ \begtt
+ \table{|c|c|}{\crl \Red A & B \crl}
+ \endtt
+ We don't want vertical line after red A to be in red.
\_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 \_partabitem{##}}\_the\_tabitemr}
+\_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}
\_doc -----------------------------
- \`\_partabitem``{<data>}` prints the table item in a paragraph format.
- This macro solves two things. Fist, the setting of parameters for the
- paragraph formatting. The `\hsize` and parameters from macros
- \^`\fC`, \^`\fR` etc. are set already.\nl
- Second thing: if the `\hsize` is negative then first pass of `pxto` table is processed.
- We print nothing in such case but we advance the \`\_tsizesum`.
+ The \`\_paramtabdeclarep``{<data>}` is invoked when `p{<data>}`
+ declarator is used. First, it saves the `\hsize` value
+ and then it runs \`\_tablepar`.
+ The \^`\_tablepar` macro behaves like \`\_tableparbox` (which is `\vtop`) in normal cases.
+ But there is a special case: if the first pass of `pxto` table is
+ processed then `\hsize` is negative. We print nothing in this case, i.e.\
+ \^`\_tableparbox` is \^`\ignoreit` and we advance the \`\_tsizesum`.
The auxiliary macro \`\_tsizelast` is used to do advancing
only in the first row of the table.
- \^`\_tsizesum` and \^`\_tsizelast` are initialized in the \^`\_tableB` macro.\nl
- \`\_partabitemA``{<data>}` only copies <data>, but it is redefined by \^`\fS`.
+ \^`\_tsizesum` and \^`\_tsizelast` are initialized in the \^`\_tableB` macro.
\_cod -----------------------------
-\_newdimen \_tsizesum
-\_def \_tsizelast{0}
-\_long\_def\_partabitem#1{%
+\_def\_paramtabdeclarep#1{\_hsize=#1\_relax
+ \_the\_tabiteml \_tablepar{\_tableparB ##\_tableparC}\_the\_tabitemr
+}
+\_def\_tablepar{%
\_ifdim\_hsize<0pt
\_ifnum\_tsizelast<\_colnum \_global\_advance\_tsizesum by-\_hsize
\_xdef\_tsizelast{\_the\_colnum}\_fi
- \_else
- \_baselineskip=\_normalbaselineskip
- \_lineskiplimit=\_zo \_noindent \_hskip\_zo \_relax \_partabitemA{#1}\_unsskip
- \_ifvmode\_vskip\_dp\_tstrutbox \_else\_lower\_dp\_tstrutbox\_hbox{}\_fi
+ \_let\_tableparbox=\_ignoreit
\_fi
+ \_tableparA \_tableparbox
+}
+\_let \_tableparbox=\_vtop
+\_let \_tableparA=\_empty
+\_newdimen \_tsizesum
+\_def \_tsizelast{0}
+
+ \_doc -----------------------------
+ The \`\_tableparB` initializes the paragraphs inside the table item and
+ \`\_tableparC` closes them. They are used in the \^`\_paramtabdeclarep` macro.
+ The first paragraph is no indented.
+ \_cod -----------------------------
+
+\_def\_tableparB{%
+ \_baselineskip=\_normalbaselineskip \_lineskiplimit=\_zo \_noindent
+ \_raise\_ht\_tstrutbox\_null \_hskip\_zo \_relax
+}
+\_def\_tableparC{%
+ \_unsskip
+ \_ifvmode\_vskip\_dp\_tstrutbox \_else\_lower\_dp\_tstrutbox\_null\_fi
}
-\_let\_partabitemA=\_useit
\_doc -----------------------------
Users put optional spaces around the table item typically, i.e.\ they write
@@ -274,19 +286,33 @@
\_doc -----------------------------
The \`\fL`, \`\fR`, \`\fC` and \`\fX` macros only do 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 -----------------------------
+ for paragraph building algorithm.
+ \_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}
-\_def\_fS{\_long\_def\_partabitemA##1{%
- \_setbox0=\_vbox{\_noindent ##1\_endgraf \_ea}\_ifnum\_prevgraf=1 \_hfil \_fi ##1%
-}}
-\_public \fL \fR \fC \fX \fS ;
+\_public \fL \fR \fC \fX ;
+
+ \_doc -----------------------------
+ The \`\fS` macro is more tricky. The \^`\_tableparbox` isn't printed
+ immediatelly, but `\setbox2=` is prefixed by the macro \`\_tableparA`,
+ which is empty by default (used in \^`\_tablepar`). The \`\_tableparD`
+ is processed after the box is set: it checks if there is only one line
+ and prints `\hbox to\hsize{\hfil<this line>\hfil}` in this case. In other
+ cases, the box2 is printed.
+ \_cod -----------------------------
+
+\_def\_fS{\_relax
+ \_ifdim\_hsize<0pt \_else \_def\_tableparA{\_setbox2=}\_fi
+ \_addto\_tableparC{\_aftergroup\_tableparD}%
+}
+\_def\_tableparD{\_setbox0=\_vbox{\_unvcopy2 \_unskip \_global\_setbox1=\_lastbox}%
+ \_ifdim\_ht0>0pt \_box2 \_setbox0=\_box1
+ \_else \_hbox to\_hsize{\_hfil \_unhbox1\_unskip\_unskip\_hfil}\_setbox0=\_box2 \_fi
+}
+\_public \fS ;
\_doc -----------------------------
The family of `\_cr*` macros
@@ -334,7 +360,7 @@
\_def\_mspan{\_omit \_afterassignment\_mspanA \_mscount=}
\_def\_mspanA[#1]#2{\_loop \_ifnum\_mscount>1 \_cs{_span}\_omit \_advance\_mscount-1 \_repeat
\_count1=\_colnum \_colnum=0 \_def\_tmpa{}\_tabdata={}\_scantabdata#1\_relax
- \_colnum=\_count1 \_setbox0=\_vbox{\_halign\_ea{\_ea\_bgroup\_the\_tabdata\_egroup\_cr#2\_cr}%
+ \_colnum=\_count1 \_setbox0=\_vbox{\_halign\_ea{\_the\_tabdata\_cr#2\_cr}%
\_global\_setbox8=\_lastbox}%
\_setbox0=\_hbox{\_unhbox8 \_unskip \_global\_setbox8=\_lastbox}%
\_unhbox8 \_ignorespaces}
@@ -557,6 +583,9 @@ after the second one.
\_endinput
+2021-08-04 \_patamtabdeclarep reimplemented.
+2021-07-16 grouping based on colors via attributes.
+2021-06-03 \scantextokens added to \_partabitem, bug fixed.
2021-06-03 \fS corrected, re-implemented.
2021-06-02 \table in \table allowed, bug fixed.
2021-06-01 pxto: sum of \tsize's allowed different than 1