summaryrefslogtreecommitdiff
path: root/macros/optex/base
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2023-11-17 03:02:29 +0000
committerNorbert Preining <norbert@preining.info>2023-11-17 03:02:29 +0000
commitd91bb5cad66508ec34d77ea60c0a02c79308edef (patch)
tree69c363099e912a77d55b67d891020bcc1f407d80 /macros/optex/base
parente0db3f0709a737e7258fd40a7cbfe9a461ea0756 (diff)
CTAN sync 202311170302
Diffstat (limited to 'macros/optex/base')
-rw-r--r--macros/optex/base/basic-macros.opm19
-rw-r--r--macros/optex/base/bib-iso690.opm51
-rw-r--r--macros/optex/base/bib-simple.opm12
-rw-r--r--macros/optex/base/cite-bib.opm6
-rw-r--r--macros/optex/base/colors.opm4
-rw-r--r--macros/optex/base/f-clara.opm24
-rw-r--r--macros/optex/base/f-culmus.opm25
-rw-r--r--macros/optex/base/f-fraunces.opm69
-rw-r--r--macros/optex/base/f-heuristica.opm5
-rw-r--r--macros/optex/base/f-oldstandard.opm22
-rw-r--r--macros/optex/base/fams-ini.opm21
-rw-r--r--macros/optex/base/fonts-catalog.opm27
-rw-r--r--macros/optex/base/fonts-resize.opm2
-rw-r--r--macros/optex/base/fonts-select.opm38
-rw-r--r--macros/optex/base/hisyntax-python.opm6
-rw-r--r--macros/optex/base/if-macros.opm29
-rw-r--r--macros/optex/base/keyval.opm25
-rw-r--r--macros/optex/base/lang-data.opm32
-rw-r--r--macros/optex/base/lang-decl.opm2
-rw-r--r--macros/optex/base/lists.opm9
-rw-r--r--macros/optex/base/makeindex.opm11
-rw-r--r--macros/optex/base/math-macros.opm4
-rw-r--r--macros/optex/base/math-preload.opm2
-rw-r--r--macros/optex/base/optex-tricks.opm756
-rw-r--r--macros/optex/base/optex.ini2
-rw-r--r--macros/optex/base/optex.lua6
-rw-r--r--macros/optex/base/others.opm43
-rw-r--r--macros/optex/base/parameters.opm14
-rw-r--r--macros/optex/base/references.opm13
-rw-r--r--macros/optex/base/table.opm5
-rw-r--r--macros/optex/base/unimath-macros.opm31
-rw-r--r--macros/optex/base/usebib.opm620
32 files changed, 1652 insertions, 283 deletions
diff --git a/macros/optex/base/basic-macros.opm b/macros/optex/base/basic-macros.opm
index 9227505678..f2047cadf0 100644
--- a/macros/optex/base/basic-macros.opm
+++ b/macros/optex/base/basic-macros.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \sdef {Basic macros for OpTeX <2023-01-22>} % preloaded in format
+\_codedecl \sdef {Basic macros for OpTeX <2023-11-11>} % preloaded in format
\_doc ------------------------------
\`\bgroup`, \`\egroup`, \`\empty`, \`\space`, and \`\null`
@@ -56,12 +56,20 @@
\_public \sdef \sxdef \slet ;
\_doc ------------------------------
- \`\adef` `{<char>}{<body>}` puts the <char> as active character and defines it
- as `{<body>}`. You can declare a macro with parameters too. For example
- `\adef @#1{...#1...}`.
+ \`\adef` `<char>{<body>}` defines active `<char>` as <body> and then
+ puts the <char> as active character. I.e. the `<body>` can include the
+ <char> as non-active charter (if it is non-active before `\adef`).
+ For example `\adef ?{\,?}`.
+ If the character is special, you can escape it, for example `\adef\%{...}`.
+ The space can be declared by `\adef{ }{<body>}`.
+ You can declare a macro with parameters too, for example
+ `\adef @#1{...#1...}`. You can use prefixes `\protected`, `\global`,
+ `\long` before `\adef`, they behave like prefixes before `\def`.
\_cod ------------------------------
-\_def \_adef #1{\_catcode`#1=13 \_begingroup \_lccode`\~=`#1\_lowercase{\_endgroup\_def~}}
+\_def\_adef#1#2#{\_adefA{#1}{#2}}
+\_def\_adefA#1#2#3{\_ea\_def\_directlua{tex.cprint(13,"\_luaescapestring{\_csstring#1}")}#2{#3}%
+ \_catcode`#1=13 }
\_public \adef ;
\_doc ------------------------------
@@ -142,6 +150,7 @@
\_endcode % -------------------------------------
+2023-11-11: \adef reimplemented, \protected, \long, \global allowed before \adef
2023-01-22: \trycs: afterfi used for second parameter
2022-11-22: \_banner definition moved here
2022-11-18: \ahead introduced
diff --git a/macros/optex/base/bib-iso690.opm b/macros/optex/base/bib-iso690.opm
index fcdbd5d48d..5595d65877 100644
--- a/macros/optex/base/bib-iso690.opm
+++ b/macros/optex/base/bib-iso690.opm
@@ -1,6 +1,6 @@
% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \_undefined {BIB style (iso690) <2023-04-22>} % loaded on demand by \usebib
+\_codedecl \_undefined {BIB style (iso690) <2023-09-13>} % loaded on demand by \usebib
\_ifx\_optexbibstyle\_undefined \_errmessage
{This file can be read by: \_string\usebib/? (iso690) bibfiles command only}
@@ -116,7 +116,7 @@
\_bibmark=\_ea{\_tmp}%
}
\_def\_createbibmark #1;#2,#3;#4,#5\_fin{% #1=year #2=LastName #3=FirstName #4=nextAuthor
- #2\_ifx^#4^\_else \_Mtext{bib.etal}\_fi, #1%
+ #2\_ifx^#4^\_else \_Mtext{bib.etal}\_fi \_ifx^#1^\_else, #1\_fi
}
\_doc -----------------------------
@@ -151,24 +151,10 @@
}
\_doc -----------------------------
- Non-standard field names.
- \_cod -----------------------------
-
-\_CreateField {ednote}
-\_CreateField {citedate}
-\_CreateField {numbering}
-\_CreateField {isbn}
-\_CreateField {issn}
-\_CreateField {doi}
-\_CreateField {url}
-\_CreateField {bibmark}
-
- \_doc -----------------------------
Sorting.
\_cod -----------------------------
-\_SortingOrder{name,year}{lfvj}
-\_SpecialSort {key}
+\_fieldalias {key} {sortedby}
\_doc -----------------------------
Supporting macros.
@@ -305,9 +291,21 @@
\_bprintb [url] {\_preurl\_url{##1}. }{}%
}
\_sdef{_print:phdthesis}{\_def\_thesistype{\_Mtext{bib.phdthesis}}\_cs{_print:thesis}}
-\_sdef{_print:mastershesis}{\_def\_thesistype{\_Mtext{bib.masthesis}}\_cs{_print:thesis}}
+\_sdef{_print:mastersthesis}{\_def\_thesistype{\_Mtext{bib.masthesis}}\_cs{_print:thesis}}
\_sdef{_print:bachelorsthesis}{\_def\_thesistype{\_Mtext{bib.bachthesis}}\_cs{_print:thesis}}
+\_sdef{_print:online}{%
+ \_bprintb [!author] {\_doauthor1{##1}\:\ }{}%
+ \_bprintb [title] {{\_em##1}\_bprintc\_titlepost{\:\ *}\_bprintv[howpublished]{}{\:}\ }%
+ {\_bibwarning}%
+ \_bprinta [howpublished] {[*].\ }{}%
+ \_bprinta [ednote] {\_prepareednote*\_bprintv[citedate]{}{.}\ }{}%
+ \_bprinta [year] {}{}%
+ \_bprinta [accessed] {\_docitedate*///\_relax.\ }{\_bibwarning}%
+ \_bprintb [doi] {\_predoi DOI \_ulink[http://dx.doi.org/##1]{##1}.\ }{}%
+ \_bprintb [url] {\_preurl\_url{##1}. }{\_bibwarning}%
+}
+
\_sdef{_print:generic}{%
\_bprintb [!author] {\_doauthor1{##1}\:\ }{\_bibwarning}%
\_bprintb [title] {{\_em##1}\_bprintc\_titlepost{\:\ *}\_bprintv[howpublished]{}{\:}\ }%
@@ -784,6 +782,12 @@ There are nearly equivalent entries: `@BACHELORSTHESIS`, `@MASTERSTHESIS` and
automatically. The type field is optional in this case. If it is used then
it has precedence before the default setting.
+\secccc The @ONLINE entry
+
+It is intended for online publications.
+
+Fields: author, title(!), howpublished, ednote, publisher, accessed, doi, url(!), note.
+
\secccc The @MISC entry
It is intended for various usage.
@@ -835,19 +839,20 @@ yearprint value) is also used in the text-oriented bib-marks when
`\nonumcitations` is set.
If you have some problems with name sorting, you can use the hidden field
-`key`, which is used for sorting instead of the \"Lastname Firstname(s)"
-of authors. If the `key` field is unset then the \"Lastname Firstname(s)"
+`sortedby` (or `key` field with the same effect).
+It can be used for sorting instead of the \"Lastname Firstname(s)"
+of the first author. If the `sortedby` field is unset then the \"Lastname Firstname(s)"
is used for sorting normally. Example:
\begtt
author = "Světla Čmejrková",
-key = "Czzmejrkova Svetla",
+sortedby = "Czzmejrkova Svetla",
\endtt
This entry is now sorted between C and D.
The norm recommends placing the auto-citations at the top of the list of
-references. You can do this by setting `key = "@"`, to each entry with your
+references. You can do this by setting `sortedby = "@"`, to each entry with your
name because the `@` character is sorted before `A`.
@@ -928,6 +933,8 @@ Other options in the option field are silently ignored.
\_endinput
+2023-09-13 ... \_createbibmark: no comma if year is missing
+2023-06-23 ... @ONLINE entry introduced
2023-04-22 ... incollection: typo corrected
2023-03-25 ... \_createbibmark introduced
2022-05-10 ... \. -> \:, collision with \oldaccents fixed.
diff --git a/macros/optex/base/bib-simple.opm b/macros/optex/base/bib-simple.opm
index e61e94d7e2..c70bb12be7 100644
--- a/macros/optex/base/bib-simple.opm
+++ b/macros/optex/base/bib-simple.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \_undefined {BIB style (simple) <2023-04-22>} % loaded on demand by \usebib
+\_codedecl \_undefined {BIB style (simple) <2023-09-13>} % loaded on demand by \usebib
\_ifx\_optexbibstyle\_undefined \_errmessage
{This file can be read by: \_string\usebib/? (simple) bibfiles command only}
@@ -39,7 +39,7 @@
\_edef\_tmp{\_ea\_createbibmark\_expanded{\_tmp;\_authlist;,;,;,;}\_fin}\_fi
\_bibmark=\_ea{\_tmp}%
}
-\_def\_createbibmark#1;#2,#3\_fin{#2, #1}
+\_def\_createbibmark#1;#2,#3\_fin{#2\_ifx^#1^\_else, #1\_fi}
\_def\_preurl{\_hfil\_break}
\_def\_Inclause{In:~}
@@ -156,6 +156,14 @@
\_bprinta [institution] {*.\ }{}%
\_bprintb [url] {\_preurl\_url{##1}. }{}%
}
+\_sdef{_print:online}{%
+ \_bprinta [!author] {*.\ }{}%
+ \_bprintb [title] {{\_em##1}\:\ }{}%
+ \_bprinta [howpublished] {*.\ }{}%
+ \_bprinta [institution] {*.\ }{}%
+ \_bprinta [series] {*.\ }{}%
+ \_bprintb [url] {\_preurl\_url{##1}. }{\_bibwarning}%
+}
\_sdef{_print:misc}{%
\_bprinta [!author] {*.\ }{}%
\_bprintb [title] {{\_em##1}\:\ }{}%
diff --git a/macros/optex/base/cite-bib.opm b/macros/optex/base/cite-bib.opm
index 9dc32a2632..805b84de03 100644
--- a/macros/optex/base/cite-bib.opm
+++ b/macros/optex/base/cite-bib.opm
@@ -1,4 +1,4 @@
-%% This is part of the OpTeX project, see http://petr.olsak.net/optex
+% This is part of the OpTeX project, see http://petr.olsak.net/optex
\_codedecl \cite {Cite, Biblioraphy <2021-04-13>} % preloaded in format
@@ -97,7 +97,7 @@
\_cod -----------------------------
\_def\_citeA #1#2,{\_if#1,\_else
- \_if *#1\_addcitelist{*}\_ea\_skiptorelax \_fi
+ \_if *#1\_addcitelist{*}\_sxdef{_bib:\_bibp*}{}\_ea\_skiptorelax \_fi
\_ifcsname _bib:\_bibp#1#2\_endcsname \_else
\_addcitelist{#1#2}%
\_opwarning{{\_the\_bibpart} \_noexpand\cite [#1#2] unknown. Try to TeX me again}\_openref
@@ -125,7 +125,7 @@
distinguished by <bibpart>, the \`\_addcitelist``{<label>}` macro
must add the <label> to given `\_ctlst:<bibpart>/`.\nl
When `\_addcitelist` is processed before \^`\usebib`,
- then \`\_citeI``[<label>]` is added. \^`\usebib` will use this list for selecting
+ then \^`\_citeI``[<label>]` is added. \^`\usebib` will use this list for selecting
right records from `.bib` file. Then \^`\usebib` sets
`\_ctlst:<bibpart>/` to `\_write`.\nl
If `\_addcitelist` is processed after \^`\usebib`, then
diff --git a/macros/optex/base/colors.opm b/macros/optex/base/colors.opm
index 36afcb3862..e43a40c779 100644
--- a/macros/optex/base/colors.opm
+++ b/macros/optex/base/colors.opm
@@ -381,6 +381,10 @@ 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.
+The concept with color attributes has one limitation: the colors cannot be changed
+inside a ligature unless the ligature is broken manually. It means that
+`{\Red f}i` doesn't lead to the expected result but `{\Red f\null}i` does.
+
\secc Color mixing
The color mixing processed by the \^`\colordef` is done in the subtractive color
diff --git a/macros/optex/base/f-clara.opm b/macros/optex/base/f-clara.opm
new file mode 100644
index 0000000000..1410965dd2
--- /dev/null
+++ b/macros/optex/base/f-clara.opm
@@ -0,0 +1,24 @@
+%% This is part of the OpTeX project, see http://petr.olsak.net/optex
+
+\_famdecl [Clara] \Clara {Clara, a serif font family}
+ {\caps} {\rm \bf \it \bi}
+ {XITSMath} {[clarar]}
+ {\_def\_fontnamegen {[clara\_currV]:\_capsV\_fontfeatures}}
+
+\_wlog{\_detokenize{%
+Modifiers:^^J
+ \caps ...... caps & small caps (only \rm with simple alphabet!)^^J
+}}
+
+% Modes
+\_moddef \resetmod {\_fsetV caps={} \_fvars r b i bi }
+\_moddef \caps {\_fsetV caps=+smcp; } % onum; set by smcp; feature
+\_moddef \nocaps {\_fsetV caps={} }
+
+\_initfontfamily % New font family must be initialized
+
+\_loadmath {[XITSMath-Regular]}
+\_loadboldmath {[XITSMath-Bold]} \to {[XITSMath-Regular]}
+
+\_endcode
+
diff --git a/macros/optex/base/f-culmus.opm b/macros/optex/base/f-culmus.opm
new file mode 100644
index 0000000000..66d2952d3f
--- /dev/null
+++ b/macros/optex/base/f-culmus.opm
@@ -0,0 +1,25 @@
+%% This is part of the OpTeX project, see http://petr.olsak.net/optex
+
+\_famdecl [Culmus] \Culmus {Hebrew fonts from the Culmus project}
+ {\roman \sans \mono} {\rm \bf \it \bi} {}
+ {[DavidCLM-Medium]}
+ {\_def\_fontnamegen {[\_subfamV CLM-\_currV]:script=hebr;\_fontfeatures}}
+
+\_wlog{\_detokenize{%
+script=hebr is set by default,^^J
+use e.g \setff{script={}}\rm^^J
+to suppress this.^^J
+Modifiers (subfamilies):^^J
+ \roman ...... \rm, \it = Medium, \bf, \bi = Bold (Roman)^^J
+ \sans ...... \rm, \it = Light, \bf, \bi = Bold (Sans)^^J
+ \mono ...... \rm, \it = Book, \bf, \bi = Bold (Mono)^^J
+}}
+
+% modifiers (they select a subfamily)
+\_moddef \resetmod {\_fsetV subfam=David \_fvars Medium Bold MediumItalic BoldItalic }
+\_moddef \roman {\_fsetV subfam=David \_fvars Medium Bold MediumItalic BoldItalic }
+\_moddef \sans {\_fsetV subfam=Nachlieli \_fvars Light Bold LightOblique BoldOblique }
+\_moddef \mono {\_fsetV subfam=MiriamMono \_fvars Book Bold BookOblique BoldOblique }
+\_initfontfamily % new font family must be initialized
+
+\_endcode
diff --git a/macros/optex/base/f-fraunces.opm b/macros/optex/base/f-fraunces.opm
new file mode 100644
index 0000000000..7684dbc4e8
--- /dev/null
+++ b/macros/optex/base/f-fraunces.opm
@@ -0,0 +1,69 @@
+%% This is part of the OpTeX project, see http://petr.olsak.net/optex
+
+\_famdecl [Fraunces] \Fraunces {Display, "Old Style" soft serif typeface}
+ {\wonky} {\rm \bf \it \bi} {Bonum}
+ {[Fraunces-VariableFont_SOFT,WONK,opsz,wght]}
+ {\_def\_fontnamegen {[Fraunces-\_currV VariableFont_SOFT,WONK,opsz,wght]:-liga;%
+ axis={wght=\_f_getwght{+300},opsz=\_the\_f_opsz,soft=\_the\_f_soft};\_wonkyV\_fontfeatures}}
+
+% \_f_getwght{+300} returns \the\wght but if \bf or \bi is processed then it returns \wght+300.
+\_def \_f_getwght#1{\_if b\_ea\_ignoresecond\_famv \_the\_numexpr \_f_wght#1\_relax \_else \_the\_f_wght \_fi}
+
+\_wlog{\_detokenize{%
+Modifiers:^^J
+ \wonky ..... alternative strokes^^J
+ \thin ...... \rm, \it = Thin, \bf, \bi = Normal^^J
+ \light ..... \rm, \it = Light, \bf, \bi = Medium^^J
+ \normal .... \rm, \it = Normal, \bf, \bi = Bold^^J
+ \bolder .... \rm, \it = Medium, \bf, \bi = Black^^J%
+Variable font parameters:^^J
+ \wght ...... 100--1000 (default 400): weight of the strokes^^J
+ \opsz ...... 6--144 (default 14): optical size modifiation^^J
+ \ssoft ..... 0--100 (default 0): softness of serifs^^J
+ Use \wght=650 \ssoft=50 (for example). It acts like others font modifiers.^^J%
+Extended variants:^^J
+ \tf \ti .... Thin, ThinItalic^^J
+ \lf \li .... Light, LightItalic^^J
+ \mf \mi .... Medium, MediumItalic^^J
+ \kf \ki .... Black, BlackItalic^^J
+}}
+
+\_ifx\_f_wght\_undefined \_newcount\_f_wght \_f_wght=400 \_newpublic \_let\wght=\_f_wght \_fi
+\_ifx\_f_opsz\_undefined \_newcount\_f_opsz \_f_opsz=14 \_newpublic \_let\opsz=\_f_opsz \_fi
+\_ifx\_f_soft\_undefined \_newcount\_f_soft \_f_soft=0 \_newpublic \_let\ssoft=\_f_soft \_fi
+
+\_moddef \resetmod {\_fsetV wonky={} \_fvars {} {} Italic- Italic- }
+\_moddef \wonky {\_fsetV wonky=+ss01; }
+\_moddef \thin {\_f_wght=100 }
+\_moddef \light {\_f_wght=250 }
+\_moddef \normal {\_f_wght=400 }
+\_moddef \medium {\_f_wght=550 }
+\_let\_thinM=\thin \_let\_lightM=\light \_let\_mediumM=\medium
+
+\_famvardef \tf {\_thinM \_rm}
+\_famvardef \ti {\_thinM \_it}
+\_famvardef \lf {\_lightM \_rm}
+\_famvardef \li {\_lightM \_it}
+\_famvardef \mf {\_mediumM \_rm}
+\_famvardef \mi {\_mediumM \_it}
+\_famvardef \kf {\_mediumM \_bf}
+\_famvardef \ki {\_mediumM \_bi}
+
+\_initfontfamily % new font family must be initialized
+
+\_loadmath {[texgyrebonum-math]}
+
+\_endcode
+
+This is an example of a font-file used for a variable fonts.
+
+\begitems
+* Declare counters with the same names as parameters of axis.
+* Use `\_ifx\_...\_undefined` in order to more font-files with variable fonts can be loaded.
+* Use `axis={...}` in font features area in the `\_fontnamegen` macro.
+* Print about axis parameters of given font to the log using `\_wlog`.
+* The `\_f_getwght` macro should be declared same in all font-files with variable fonts.
+ It enables \bf and \bi variants implemented as the given shift of the current wght parameter.
+* You can declare more variants by `\famvardef`.
+* You can declare font modifiers and font variants using values of axis parameters.
+\enditems
diff --git a/macros/optex/base/f-heuristica.opm b/macros/optex/base/f-heuristica.opm
index bca6c0f318..d231774729 100644
--- a/macros/optex/base/f-heuristica.opm
+++ b/macros/optex/base/f-heuristica.opm
@@ -3,14 +3,15 @@
\_famdecl [Heuristica] \Heuristica {Extends the Utopia font}
{} {\rm \bf \it \bi} {}
{[Heuristica-Regular]}
- {\_def\_fontnamegen {[Heuristica-\_currV]:\_capsV\_fontfeatures}}
+ {\_def\_fontnamegen {[Heuristica-\_currV]:script=latn;\_capsV\_fontfeatures}}
\_wlog{\_detokenize{%
No modifiers.^^J
-% \caps ...... caps & small caps^^J
+ \caps ...... caps & small caps (\rm only)^^J
}}
\_moddef \resetmod {\_fsetV caps={} \_fvars regular bold italic bolditalic }
+\_moddef \caps {\_fsetV caps=+smcp;\_ffonum; }
\_initfontfamily % new font family must be initialized
diff --git a/macros/optex/base/f-oldstandard.opm b/macros/optex/base/f-oldstandard.opm
new file mode 100644
index 0000000000..68d01da26c
--- /dev/null
+++ b/macros/optex/base/f-oldstandard.opm
@@ -0,0 +1,22 @@
+%% This is part of the OpTeX project, see http://petr.olsak.net/optex
+
+\_famdecl [OldStandard] \Oldstandard {inspired by a typeface most commonly used in old books}
+ {\caps} {\rm \bf \it \bi} {}
+ {[OldStandard-Regular]}
+ {\_def\_fontnamegen {[OldStandard-\_currV]:script=latn;\_capsV\_fontfeatures}}
+
+\_wlog{\_detokenize{%
+Modifier:^^J
+ \caps ...... caps & small caps^^J
+}}
+
+\_moddef \resetmod {\_fsetV caps={} \_fvars Regular Bold Italic BoldItalic }
+\_moddef \caps {\_fsetV caps=+smcp;\_ffonum; }
+
+\_initfontfamily % new font family must be initialized
+
+\_endcode
+
+See the file `f-heros.opm` for information about principles of such
+font-macro-files.
+
diff --git a/macros/optex/base/fams-ini.opm b/macros/optex/base/fams-ini.opm
index adfc1050c5..6dc19ca9b1 100644
--- a/macros/optex/base/fams-ini.opm
+++ b/macros/optex/base/fams-ini.opm
@@ -139,9 +139,16 @@
{ -,\caps: {\rm\bf\it\bi} }
\_famalias [Baskervald ADF] \_famalias [ADFBaskerville]
+\_famfrom {Undercase Type https://undercase.xyz/}
+\_faminfo [Fraunces] {Display, old-style soft serif typeface} {f-fraunces}
+ { -: {\tf\ti\lf\li\rm\it\mf\mi\bf\bi\kf\ki}
+ \wonky: {\rm\it}
+ \ssoft=70: {\rm\it}
+ }
+
\_famfrom {Andrey V. Panov}
\_faminfo [Heuristica] {Extends the Utopia font} {f-heuristica}
- { -: {\rm\bf\it\bi} }
+ { -: {\rm\bf\it\bi} \caps: {\rm} }
\_faminfo [Erewhon] {Derived from Heuristica with slanted variants} {f-erewhon}
{ -: {\rm\bf\it\bi\sl\bs} \caps: {\rm\bf\it\bi} }
@@ -252,6 +259,18 @@
\_faminfo [Inconsolata] {A monospaced font for code listing} {f-inconsolata}
{ -,\narrow: {\rm\bf} }
+\_famfrom {Alexey Kryukov}
+\_faminfo [OldStandard] {inspired by a typeface most commonly used in old books} {f-oldstandard}
+ { -,\caps: {\rm\bf\it\bi} }
+
+\_famfrom {Séamas Ó Brógáin}
+\_faminfo [Clara] {Clara, a serif font family} {f-clara}
+ { -: {\rm\bf\it\bi} \caps: {\rm} }
+
+\_famfrom {Maxim Iorsh}
+\_faminfo [Culmus] {Hebrew roman, sans and mono fonts from the Culmus project} {f-culmus}
+ {\roman,\sans,\mono: {\rm\bf\it\bi}}
+
\_endcode
Once you have prepared a font family file with the name `f-<famname>.opm` and
diff --git a/macros/optex/base/fonts-catalog.opm b/macros/optex/base/fonts-catalog.opm
index 893c731df0..1ea403b9c8 100644
--- a/macros/optex/base/fonts-catalog.opm
+++ b/macros/optex/base/fonts-catalog.opm
@@ -1,13 +1,13 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \_undefined {Font catalogue <2023-03-09>} % loaded on demand by \fontfam[catalog]
+\_codedecl \_undefined {Font catalogue <2023-06-04>} % loaded on demand by \fontfam[catalog]
\_tracinglostchars=1 % only to log file
\_initunifonts
\_raggedbottom
\_begingroup
-\_istoksempty\_catalogmathsample \_iftrue \_noloadmath \_fi
+\_istoksempty\_catalogmathsample \_iftrue \_noloadmath \_else \_input{unimath-codes.opm}\_fi
\_global\_font\_ttfixed=[LMMono10-Regular]\_relax
\_fontlet\_smalltt=\_ttfixed at7pt
\_suppressfontnotfounderror=1
@@ -26,6 +26,7 @@
\_def\_faminfo [#1]#2#3#4{%
\_bgroup
+ \_rightskip=0sp plus 1fill
\_lowercase{\_edef\_famname{\_ea\_removespaces #1 {} }}%
\_edef\_act{\_noexpand\_isinlist{,\_cataloglist,}{,\_famname,}}\_act
\_iftrue \def\_cataloglist{}\_fi
@@ -33,12 +34,14 @@
\_iftrue \def\_cataloglist{.}\_fi
\_ifx\_cataloglist\_empty
\_ifx^#4^\_else
- \_bigskip {\_ttfixed\_string\fontfam [#1] -- (#2)\_par}
+ \_the\_catalognextfam
+ {\_ttfixed\_string\fontfam [#1] -- (#2)\_par}\_nobreak
\_input #3.opm
- \_ifexistfam \_nobreak\_medskip \_dosamples #4:{}
+ \_ifexistfam
+ \_nobreak\_medskip \_dosamples #4:{}\_par
\_ifx\_mathfaminfo\_empty
\_else \_istoksempty\_catalogmathsample
- \_iftrue {\_ttfixed \$Default math font\$: \_mathfaminfo \_par}
+ \_iftrue {\_nobreak \_ttfixed \$Default math font\$: \_mathfaminfo \_par}
\_else Default math font (\_mathfaminfo): \_the\_catalogmathsample \_par
\_fi\_fi
\_else {\_qquad\_ttfixed ... family skipped, fonts not found in your system.\_nl
@@ -60,14 +63,15 @@
}
\_def\_dosamplesB#1{%
\_ifx\_relax#1 \_else
+ \_ifhmode \_nl \_fi
{\_ttfixed \_detokenize\_ea{\_usemodifiers}\_detokenize{#1}\_unskip:}
{\_usemodifiers #1\_ea\_ifx\_the\_font \_nullfont
\_ttfixed ... This font isn't available in your system.%
- \_else \_the\_catalogsample \_fi }\_par
+ \_else \_the\_catalogsample \_fi }%
\_ea \_dosamplesB \_fi
}
-\_def\_wlog#1{\_nobreak\_smallskip
+\_def\_wlog#1{\_smallskip
\_hbox to\_hsize{\_hskip25pt
\_edef\_tmp{#1}\_replstring\_tmp{^^J}{\_endgraf}%
\_smalltt \_noindent \_ea \string \_csname \_currfamily\_endcsname
@@ -88,6 +92,8 @@
\_endgroup
+\_the\_catalognextfam {}
+
\parindent=0pt
\nonum\sec Customization of the catalog
@@ -128,6 +134,11 @@ printed but families listed in the \code{\\catalogexclude} are excluded. For exa
The \code{\\cataogexclude} is empty by default.
+\bigskip The material printed at the beginning of each font family is stored in the
+\code{\\catalognextfam} tokens register. Default value is \code{\\bigskip} but you can
+set (for example) \code{\\catalognextfam={\\vfil\\break}} in order to start
+each font family on a next page.
+
\bigskip The font families printed in the catalogue must be declared by the
\code{\\_faminfo} command in the file \code{fams-ini.opm} (declarations used
as default for \OpTeX/) or in the file \code{fams-local.opm}. The second file
@@ -136,6 +147,8 @@ described in the \code{fams-ini.opm} file.
\_endcode % -------------------------------------
+2023-06-04 line breaking optimized
+2023-06-01 \_catalognextfam introduced, \_nobreak inserted
2023-03-09 \_famsrc introduced
2022-07-11 \_raggedbottom added
2022-02-22 \_ttfixed, \footline set as global, bug fixed
diff --git a/macros/optex/base/fonts-resize.opm b/macros/optex/base/fonts-resize.opm
index 4fc8ab1e28..323e1d72a0 100644
--- a/macros/optex/base/fonts-resize.opm
+++ b/macros/optex/base/fonts-resize.opm
@@ -167,7 +167,7 @@ You can declare a new {\em font switch} by `\font` primitive:
\begtt \catcode`\<=13
\font \<font switch> = <font file name> <size spec>
% for example:
-\font \tipa = tipa10 at12pt % the font tipa10 at 10pt is loaded
+\font \tipa = tipa10 at12pt % the font tipa10 at 12pt is loaded
% usage:
{\tipa TEXT} % the TEXT is printed in the loaded font.
\endtt
diff --git a/macros/optex/base/fonts-select.opm b/macros/optex/base/fonts-select.opm
index cd70dab03c..d403a490d5 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 <2023-04-22>} % preloaded in format
+\_codedecl \fontfam {Fonts selection system <2023-06-16>} % preloaded in format
\_doc -----------------------------
The main principle of the Font Selection System is: run one or more
@@ -131,7 +131,7 @@
\_unless\_ifcsname _f:\_csstring#2:main.fam\_endcsname
\_isfont{#7}\_iffalse
\_opwarning{Family [#1] skipped, font "#7" not found}\_endinput
- \_lowercase{\_ifcsname _fams:#1\_endcsname}\_famsubstitute \_fi
+ \_ifcsname _fams:\_famfile\_endcsname \_famsubstitute \_fi
\_else
\_edef\_currfamily {\_csstring #2}\_def\_mathfaminfo{#6}%
\_wterm {FONT: [#1] -- \_string#2 \_detokenize{(#3)^^J mods:{#4} vars:{#5} math:{#6}}}%
@@ -311,12 +311,12 @@
\_protected\_def \_fontfam [#1]{%
\_lowercase{\_edef\_famname{\_ea\_removespaces \_expanded{#1} {} }}%
- \_isfile {f-\_famname.opm}\_iftrue \_opinput {f-\_famname.opm}%
+ \_isfile {f-\_famname.opm}\_iftrue \_edef\_famfile{f-\_famname}\_opinput {f-\_famname.opm}%
\_else
\_tryloadfamslocal
\_edef\_famfile{\_trycs{_famf:\_famname}{}}%
\_ifx\_famfile\_empty
- \_ifcsname _fams:\_famname \_endcsname \_famsubstitute
+ \_ifcsname _fams:f-\_famname \_endcsname \_edef\_famfile{f-\_famname}\_famsubstitute
\_else \_listfamnames
\_fi
\_else \_opinput {\_famfile.opm}%
@@ -352,17 +352,19 @@
family installed.
\`\_famsubstitute` is internal macro used in \^`\fontfam` and \^`\_famdecl` macros.
It consumes the rest of the macro, runs \^`\nospacefuturelet` in order to
- do `\endpinput` to the current `f-file` and runs \^`\fontfam` again.
- The table of such substutitions are saved in the macros `\_fams:<family>`.
+ do `\endinput` to the current `f-file` and runs \^`\fontfam` again.
+ The table of such substutitions are saved in the macros `\_fams:<family-file>`.
\_cod -----------------------------
-\_def \_fontfamsub [#1]#2[#3]{\_lowercase{\_sxdef{_fams:#1}{#3}}}
-
+\_def \_fontfamsub [#1]#2[#3]{\_tryloadfamslocal
+ \_lowercase{\_edef\_tmp{\_removespaces #1 {} }}%
+ \_sxdef{_fams:\_trycs{_famf:\_tmp}{f-\_tmp}}{#3}%
+}
\_def\_famsubstitute #1\_empty\_fi{\_fi\_fi\_fi
- \_wterm {FONT: Family [\_famname] not found, substituted by [\_cs{_fams:\_famname}]}%
+ \_wterm {FONT-SUB: \_famfile\_space -> [\_cs{_fams:\_famfile}]}%
\_nospacefuturelet\_tmp\_famsubstituteA % we want to \endinput current f-file
}
-\_def\_famsubstituteA{\_fontfam[\_cs{_fams:\_famname}]}
+\_def\_famsubstituteA{\_fontfam[\_cs{_fams:\_famfile}]}
\_public \fontfamsub ;
@@ -413,17 +415,19 @@
pairs. The user can declare different samples and different behavior of
the catalog, see the end of catalog listing for more information.
The default parameters
- \`\catalogsample`, \`\catalogmathsample`, \`\catalogonly` and
- \`\catalogexclude` of the catalog are declared here.
+ \`\catalogsample`, \`\catalogmathsample`, \`\catalogonly`,
+ \`\catalogexclude` and \`\catalognextfam` of the catalog are declared here.
\_cod -----------------------------
\_newtoks \_catalogsample
\_newtoks \_catalogmathsample
\_newtoks \_catalogonly
\_newtoks \_catalogexclude
+\_newtoks \_catalognextfam
\_catalogsample={ABCDabcd Qsty fi fl áéíóúüů řžč ÁÉÍÓÚ ŘŽČ 0123456789}
+\_catalognextfam={\_bigskip}
-\_public \catalogonly \catalogexclude \catalogsample \catalogmathsample ;
+\_public \catalogonly \catalogexclude \catalogsample \catalogmathsample \catalognextfam ;
\_doc -----------------------------
The font features are managed in the \`\_fontfeatures` macro.
@@ -587,6 +591,12 @@ described in the section~\ref[fontfamfiles]. Font modifiers and variant
selectors may be declared here.
The loaded family is set as current and `\rm` variant selector is processed.
+When \^`\fontfam` `[<Font Family>]` is used and the given
+family isn't found in the current \TeX/ system and
+the <Font Family> is previously declared by
+\^`\fontfamsub``[<Font Family>][<Other Family>]`
+then \OpTeX/ does the given substitution and runs \^`\fontfam``[<Other Family>]`.
+
The available declared font modifiers and declared variant selectors are
listed in the log file when the font family is load. Or you can print
`\fontfam[catalog]` to show available font modifiers and variant selectors.
@@ -935,6 +945,8 @@ with Unicode fonts loaded by \^`\fontfam`.
\endinput
+2023-06-16 \fontfamsub improved.
+2023-05-30 \catalognextfam introduced.
2023-04-22 \setwordspace: \fontdimens reset, bug fixed.
2023-03-09 \_famsrc, \fontfamsub introduced
2022-12-01 \faminfo saves f-<filename> to the format only when needed
diff --git a/macros/optex/base/hisyntax-python.opm b/macros/optex/base/hisyntax-python.opm
index 12f7ebeeb4..b38fd9477a 100644
--- a/macros/optex/base/hisyntax-python.opm
+++ b/macros/optex/base/hisyntax-python.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \_hisyntaxpython {Syntax highlighting for Python sources <2020-04-04>}
+\_codedecl \_hisyntaxpython {Syntax highlighting for Python sources <2023-10-25>}
\_newtoks \_hisyntaxpython \_newtoks \_hicolorspython
@@ -57,7 +57,7 @@
\_replthis{E\e\o+\c}{E+}\_replthis{E\e\o-\c}{E-}
\_replthis{\e j}{j\e}
%
- \_replfromto{\n\o@\n}{^^J}{\z R{#1}^^J} % decorators
+ \_replfromto{\b\n\n\o@\n}{^^J}{\z K{@}\z R{#1}^^J} % decorators
%
\_def\o#1{\z O{#1}}
\_def\c#1\e{\z N{#1}}
@@ -80,3 +80,5 @@ This code was greatly inspired by the OPMac hisyntax macros for Python:
created by Petr Krajnik.
+2023-10-25 decorators: hi-syntax corrected
+2020-04-04 released
diff --git a/macros/optex/base/if-macros.opm b/macros/optex/base/if-macros.opm
index 148c855941..415b2c01c8 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 <2023-01-16>} % preloaded in format
+\_codedecl \newif {Special if-macros, is-macros and loops <2023-10-17>} % preloaded in format
\_doc ----------------------------
\secc Classical \code{\\newif}
@@ -336,6 +336,20 @@
\_public \casesof ;
\_doc -----------------------------
+ \`\qcasesof` `{<string>} <list of cases>` behaves like \^`\casesof` but it
+ compares phrases with the given <string> using \^`\isequal`.
+ The <list of cases> includes pairs
+ `{<phrase>} {<what to do if string=phrase>}` finalized by a
+ pair `\_finc {<what to do else>}`.
+ \_cod -----------------------------
+
+\_long\_def \_qcasesof #1#2#3{\_ifx\_finc#2\_ea\_ignoresecond \_else \_ea\_usesecond \_fi
+ {#3}{\_isequal{#1}{#2}\_iftrue \_ea\_ignoresecond \_else \_ea\_usesecond \_fi
+ {\_finc{#3}}{\_qcasesof{#1}}}%
+}
+\_public \qcasesof ;
+
+ \_doc -----------------------------
\`\xcasesof` `<list of pairs>` extends the features of the macro \^`\casesof`.
Each pair from the `<list of pairs>` is in the format
`{<if statement>}{<what to do>}`, only the last pair must have the different
@@ -346,22 +360,23 @@
\begtt
\message {The \tmpnum has \xcasesof
{\ifnum\tmpnum>0 } {positive}
- {\ifnum\tmpnum=0 } {equal to zero}
- \_finc {negative} value}
+ {\ifnum\tmpnum=0 } {zero}
+ \_finc {negative} value}
\endtt
The \^`\xcasesof` macro works with principle: first true condition wins,
next conditions are not evaluated.
\_cod -----------------------------
-\_long\_def \_xcasesof #1{\_xcasesofA #1\_finc}
-\_long\_def \_xcasesofA #1#2\_finc #3{%
- \_ifx #1\_finc \_ea\_ignoresecond\_else \_ea\_usesecond\_fi
- {#3}{#1#2\_ea\_ignoresecond\_else \_ea\_usesecond\_fi {\_finc{#3}}{\_xcasesof}}%
+\_def \_xcasesof {\_nospacefuturelet\_next\_xcasesofA}
+\_def \_xcasesofA {\_ifx\_next\_finc \_ea\_usesecond \_else \_ea \_xcasesofB \_fi}
+\_long\_def \_xcasesofB #1#2{%
+ #1\_ea\_ignoresecond\_else \_ea\_usesecond\_fi {\_finc{#2}}{\_xcasesof}%
}
\_public \xcasesof ;
\_endcode
+2023-10-17 \qcasesof introduced, \xcasesof reimplemented.
2023-01-16 \isnextchar created expandable.
2022-12-02 \xcasesof: its first parameter is \long too.
2022-11-29 renamed to \casesof, \xcasesof.
diff --git a/macros/optex/base/keyval.opm b/macros/optex/base/keyval.opm
index 11a8663b16..68f3fea536 100644
--- a/macros/optex/base/keyval.opm
+++ b/macros/optex/base/keyval.opm
@@ -1,12 +1,12 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \readkv {Key-value dictionaries <2023-03-11>} % preloaded in format
+\_codedecl \readkv {Key-value dictionaries <2023-10-23>} % preloaded in format
\_doc ----------------------------
{\bf Implementation.}\nl
The \`\readkv``<list>` expands its parameter and does replace-strings in order to
- remove spaces around equal signs and after commas.
- Then \`\_kvscan` reads the parameters list finished by `,\_fin,`
+ remove spaces around equal signs and commas.
+ Then \`\_kvscan` reads the parameters list finished by `,\_fin`
and saves values to `\_kv:<dict>:<key>` macros.
The `\_kvx:<dict>:<key>` is processed (if it is defined) with parameter
<value> after it.\nl
@@ -18,11 +18,11 @@
if the `<key>` is defined in current <dict>.
\_cod ----------------------------
-\_def\_readkv#1{\_ea\_def\_ea\_tmpb\_ea{#1}%
- \_replstring\_tmpb{= }{=}\_replstring\_tmpb{ =}{=}\_replstring\_tmpb{, }{,}%
- \_ea \_kvscan\_tmpb,\_fin,}
-\_def\_kvscan#1,{\_ifx\_fin#1\_empty\_ea\_ignoreit \_else\_ea\_useit \_fi
- {\_kvsd #1==\_fin \_kvscan}}
+\_def\_readkv#1{\_ea\_def\_ea\_tmpb\_ea{#1,}%
+ \_replstring\_tmpb{= }{=}\_replstring\_tmpb{ =}{=}\_replstring\_tmpb{ ,}{,}%
+ \_ea \_nospaceafter \_ea\_kvscan\_tmpb\_fin}
+\_def\_kvscan#1,#2{\_ifx^#1^\_else \_kvsd #1==\_fin \_fi
+ \_ifx\_fin#2\_empty \_ea\_ignoreit \_else\_ea\_useit \_fi {\_kvscan#2}}
\_def\_kvsd#1=#2=#3\_fin{\_sdef{\_kvcs#1}{#2}%
\_trycs{_kvx:\_the\_kvdict:#1}%
{\_trycs{_nokvx:\_the\_kvdict}{\_ea\_ignoreit}{#1}\_ea\_ignoreit}{#2}}
@@ -88,7 +88,7 @@ user can set the `draft` option without the value. Then you can do
\iskv{draft}\iftrue ...draft mode... \else ...final mode... \fi
...}
\endtt
-Maybe, you want to allow not ony `draft` option but `final` option (which is
+Maybe, you want to allow not only `draft` option but `final` option (which is
opposite to `draft`) too and you want to apply the result from the last given
option. Then `\iskv` doesn't work because you can only check if both options
are declared but you don't know what one is given as last. But you can
@@ -110,7 +110,7 @@ then `\readkv{opt=HELLO}` prints \"opt is HELLO".
The \^`\nokvx` `{<code>}` can declare a <code> processed for all <keys>
undeclared by \^`\kvx`. The `#1` and `#2` can be used in the <code>,
`#1` is <key>, `#2` is <value>. If `\nokvx` is unused then nothing is done
-for undeclared <key>. Example: `\nokvx{\opwarnig{Unknown option "#1"}}`.
+for undeclared <key>. Example: `\nokvx{\opwarning{Unknown option "#1"}}`.
The default dictionary name (where key-value pairs are processed) is
empty. You can use your specific dictionary by
@@ -123,9 +123,12 @@ Package options can be processed when
Recommendation: If the value of the key-value pair includes `=` or `,` or
`]`, then use the syntax `<key>={<value>}`.
-\_endinput
+A more extensive example can be found in
+\ulink[http://petr.olsak.net/optex/optex-tricks.html\#roundframe]{\OpTeX/ trick 0073}.
+\_endinput
+2023-10-23 minor changes in \readkv, empty key isn't processed.
2023-03-11 \nokvx: \fi bug (due to \afterfi in \trycs) fixed.
2023-01-13 \kvx parameter added, \nokvx introduced.
2023-01-07 \kvdict, \kvx, \iskv added.
diff --git a/macros/optex/base/lang-data.opm b/macros/optex/base/lang-data.opm
index 5b24c0999a..17aa26c4bf 100644
--- a/macros/optex/base/lang-data.opm
+++ b/macros/optex/base/lang-data.opm
@@ -162,10 +162,40 @@
\_monthw et jaanuar veebruar märts aprill mai juuni
juuli august september oktoober november detsember
\_sdef{_mt:today:et}{\_the\day.~\_mtext{m\_the\_month} \_the\_year}
-\_quotationmarks{„“„“}
+\_quotationmarks et {„“„“}
+
+\_langdata he {Hebrew} % -----------------------------------------------
+\_langw he פרק טבלה איור נושא
+\_langb he {, ו- } { ועמיתים.} {\,מהדורה} {מצוטט מ-~} {כרך~} {מס׳~} {עמודים~} {עמ׳~} {:מחבר~} {:מחברים~}
+ {זמין מ- } {זמין גם מ- }
+ {עבודת גמר לתואר בוגר אוניברסיטה} {עבודת גמר לתואר מוסמך אוניברסיטה} {דיסרטציה}
+\_monthw he ינואר פברואר מרץ אפריל מאי יוני
+ יולי אוגוסט ספטמבר אוקטובר נובמבר דצמבר
+\_sdef{_mt:today:he}{{\_textdir TLT\_the\_day} ב\_mtext{m\_the\_month}, {\_textdir TLT\_the\_year}}
+\_quotationmarks he {„”‚’}
+
+\_def \_sortingdatahe {%
+ /,{ },-,&,@,%
+ אﬡאּאָאַ,בבֿבּ,גגּ,דﬢדּ,הﬣהּ,ווּוֹ,זזּ,ח,טטּ,ייּיִ,%
+ כﬤכּכֿךךּ,לﬥלּ,ממּםﬦ,ננּן,ססּ,עﬠ,פפּפֿףףּ,%
+ צצּ,קקּ,ררּﬧ,ששּשׁשּׁשׂשּׂ,תתּﬨ,%
+ 0,1,2,3,4,5,6,7,8,9,'%
+}
+\_def \_ignoredcharshe {%
+^^^^0591,^^^^0592,^^^^0593,^^^^0594,^^^^0595,^^^^0596,^^^^0597,^^^^0598,%
+^^^^0599,^^^^059a,^^^^059b,^^^^059c,^^^^059d,^^^^059e,^^^^059f,%
+^^^^05a0,^^^^05a1,^^^^05a2,^^^^05a3,^^^^05a4,^^^^05a5,^^^^05a6,^^^^05a7,%
+^^^^05a8,^^^^05a9,^^^^05aa,^^^^05ab,^^^^05ac,^^^^05ad,^^^^05ae,^^^^05af,%
+^^^^05b0,^^^^05b1,^^^^05b2,^^^^05b3,^^^^05b4,^^^^05b5,^^^^05b6,^^^^05b7,%
+^^^^05b8,^^^^05b9,^^^^05ba,^^^^05bb,^^^^05bc,^^^^05bd,^^^^05be,^^^^05bf,%
+^^^^05c0,^^^^05c1,^^^^05c2,^^^^05c3,^^^^05c4,^^^^05c5,^^^^05c6,^^^^05c7,%
+^^^^05f3,^^^^05f4%
+}
+\_def \_compoundcharshe {}
\_endcode
+2023-08-30: Hebrew data added
2022-10-11: \postexhyphenchar setting added to cs and sk languages
2022-10-10: { ed.} changed to {\,ed.}
2022-08-31: \_sortingdatahu corrected
diff --git a/macros/optex/base/lang-decl.opm b/macros/optex/base/lang-decl.opm
index 753df5f82e..2d8d2cd017 100644
--- a/macros/optex/base/lang-decl.opm
+++ b/macros/optex/base/lang-decl.opm
@@ -157,7 +157,7 @@
example:
\begtt
\_preplangmore ru {\_frenchspacing \_setff{script=cyrl}\selectcyrlfont}
- \_addto\_langdefaut {\_setff{}\selectlatnfont}
+ \_addto\_langdefault {\_setff{}\selectlatnfont}
\endtt
The macros `\selectcyrlfont` and `\selectlatnfont` are not defined in
\OpTeX/. If you follow this example, you have to define them after your
diff --git a/macros/optex/base/lists.opm b/macros/optex/base/lists.opm
index e7785678dd..b372edf635 100644
--- a/macros/optex/base/lists.opm
+++ b/macros/optex/base/lists.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \begitems {Lists: begitems, enditems <2022-02-25>} % preloaded in format
+\_codedecl \begitems {Lists: begitems, enditems <2023-10-20>} % preloaded in format
\_doc -----------------------------
\`\_aboveliskip` is used above the list of items,\nl
@@ -71,11 +71,11 @@
The \`\style` `<letter>` does \`\_printitem``={\_item:<letter>}`.
More exactly: \^`\begitems` does \^`\_printitem=`\^`\defaultitem` first,
then \^`\style` `<letter>` does \^`\_printitem``={\_item:<letter>}`
- when it is used and finally, `\_startitem` alias `*` uses \^`\_printitem`.
+ when it is used and finally, \^`\_startitem` alias `*` uses \^`\_printitem`.
\_cod -----------------------------
\_def\_style#1{%
- \_ifcsname _item:#1\_endcsname \_printitem=\ea{\_csname _item:#1\_endcsname}%
+ \_ifcsname _item:#1\_endcsname \_printitem=\_ea{\_csname _item:#1\_endcsname}%
\_else \_printitem=\_defaultitem \_fi
}
\_sdef{_item:o}{\_raise.4ex\_hbox{$\_scriptscriptstyle\_bullet$} }
@@ -88,6 +88,8 @@
\_sdef{_item:A}{\_uppercase\_ea{\_athe\_itemnum}) }
\_sdef{_item:x}{\_raise.3ex\_fullrectangle{.6ex}\_kern.4em}
\_sdef{_item:X}{\_raise.2ex\_fullrectangle{1ex}\_kern.5em}
+\_sdef{_item:d}{\_aftergroup\_dword}
+\_def\_dword#1#2{{\_bf #2 }\_ignorespaces} % #1 is \_ignorespaces from \_startitem
\_doc -----------------------------
\`\_athe``{<num>}` returns the `<num>`s lowercase letter from the alphabet.\nl
@@ -121,6 +123,7 @@
\_endcode % -------------------------------------
+2023-10-20 \style d moved from OpTeX trick 0108 to the format
2022-02-25 \olistskipamount, \ilistskipamount, \itemskipamount introduced
2021-03-10 \_ifmmode*\_else\_ea\_startitem\_fi added to * defintition
2020-04-21 \isnextchar\par added to \enditems
diff --git a/macros/optex/base/makeindex.opm b/macros/optex/base/makeindex.opm
index d939d9ea64..a3af094f26 100644
--- a/macros/optex/base/makeindex.opm
+++ b/macros/optex/base/makeindex.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \makeindex {Makeindex and sorting <2023-03-12>} % preloaded in format
+\_codedecl \makeindex {Makeindex and sorting <2023-06-02>} % preloaded in format
\_doc -----------------------------
\^`\makeindex` implements sorting algorithm at \TeX/ macro-language level.
@@ -203,11 +203,14 @@
The \`\_preparesorting` `\,<string>` converts `<string>` to `\_tmpb`
with respect to the data initialized in \^`\_setprimarysorting` or
\^`\_setsecondarysorting`.\nl
- The compoud characters are converted by the \`\_docompound` macro.
+ The part of the string after `^^^` is ignored (you can have the same
+ sorting key for different things) and
+ the compoud characters are converted by the \`\_docompound` macro.
\_cod -----------------------------
\_def \_preparesorting #1{%
- \_edef \_tmpb {\_ea\_ignoreit\_csstring #1}% \,<string> -> <string>
+ \_edef \_tmpb {\_ea\_ignoreit\_csstring #1}% \,<string> -> <string>
+ \_edef\_tmpb{\_ea \_stripfromcaret \_tmpb ^^^\_fin}% <string>^^^<ignore> -> <string>
\_ea \_docompound \_compoundchars \_relax:{} % replace compound characters
\_lowercase \_ea{\_ea\_def \_ea\_tmpb \_ea{\_tmpb}}% convert in respect to \_sortingdata
\_ea\_replstring \_ea\_tmpb \_ea{\_csstring\^^I}{}% remove ignored characters
@@ -215,6 +218,7 @@
\_def \_docompound #1:#2 {%
\_ifx\_relax#1\_else \_replstring\_tmpb {#1}{#2}\_ea\_docompound \_fi
}
+\_def\_stripfromcaret #1^^^#2\_fin{#1}
\_doc -----------------------------
Macro \`\_isAleB` `\,<string1> \,<string2>` returns the result of comparison
@@ -567,6 +571,7 @@
\_endcode % -------------------------------------
+2023-06-02 \_stripfromcaret introduced
2023-03-12 \_definefirstii introduced
2022-06-28 \_reversewords for French sorting introduced
2022-06-28 \_sortingdatalatin covers more languages
diff --git a/macros/optex/base/math-macros.opm b/macros/optex/base/math-macros.opm
index a132cb4176..00adc9f1aa 100644
--- a/macros/optex/base/math-macros.opm
+++ b/macros/optex/base/math-macros.opm
@@ -596,8 +596,8 @@
\_protected\_def\_cong{\_mathrel{\_mathpalette\_overeq\_sim}} % congruence sign
\_def\_overeq#1#2{\_lower.05em\_vbox{\_lineskiplimit\_maxdimen\_lineskip=-.05em
\_ialign{$\_math#1\_hfil##\_hfil$\_crcr#2\_crcr=\_crcr}}}
-\_protected\_def\_notin{\_mathrel{\_mathpalette\_cancel\_in}}
-\_def\_cancel#1#2{\_math\_ooalign{$\_hfil#1\_mkern1mu/\_hfil$\_crcr$#1#2$}}
+\_protected\_def\_notin{\_mathrel{\_mathpalette\_icancel\_in}}
+\_def\_icancel#1#2{\_math\_ooalign{$\_hfil#1\_mkern1mu/\_hfil$\_crcr$#1#2$}}
\_protected\_def\_rightleftharpoons{\_mathrel{\_mathpalette\_rlhp{}}}
\_def\_rlhp#1{\_vcenter{\_math\_hbox{\_ooalign{\_raise.2em
\_hbox{$#1\_rightharpoonup$}\_crcr
diff --git a/macros/optex/base/math-preload.opm b/macros/optex/base/math-preload.opm
index a3ac3e44b3..fbfdc8af1e 100644
--- a/macros/optex/base/math-preload.opm
+++ b/macros/optex/base/math-preload.opm
@@ -138,7 +138,7 @@
\`\_mfactor` sets scaling factor for given math fonts family
related to text font size. It does the setting `\_ptmunit=<factor>\_ptunit` where
the <factor> is defined by `\sdef{_mfactor:<family>}{<factor>}`.
- For eample, you can set `\sdef{_mfactor:1}{0.95}` if you found that
+ For example, you can set `\sdef{_mfactor:1}{0.95}` if you found that
this scaling of math family 1 gives better visual compatibility
with used text fonts. If not declared then scaling factor is~1.
\_cod -----------------------------
diff --git a/macros/optex/base/optex-tricks.opm b/macros/optex/base/optex-tricks.opm
new file mode 100644
index 0000000000..89fc7dd5e7
--- /dev/null
+++ b/macros/optex/base/optex-tricks.opm
@@ -0,0 +1,756 @@
+%% This is part of the OpTeX project, see http://petr.olsak.net/optex
+
+\_codedecl \_undefined {OpTeX tricks ready to autoload <2023-11-15>} % chunks loaded on demand
+
+% Selected OpTeX tricks are here, they are auto-loaded if the macro is used first
+% namespace: optextrick
+
+\_trick 0057 \begfile \createfile ;
+%%%%%%%%%%%%
+
+\newwrite\.outfile
+\def\begfile #1 {\_immediate\_openout\.outfile={#1}%
+ \_begingroup \_setverb \_endlinechar=`\^^J \.begfileA^^J%
+}
+\_ea\_def\_ea\.begfileA\_ea#\_ea1\_ea^^J\_csstring\\endfile#2^^J{\_endgroup
+ \_ifx^#1^\_else \_immediate\_write\.outfile{\_ignoreit #1}\_fi
+ \_immediate\_closeout\.outfile
+}
+\_let\createfile=\begfile
+
+\_trick 0054 \beglua \begLUA \logginglua ;
+%%%%%%%%%%%%
+
+\_newtoks\.luamacros
+\.luamacros={\_let\\=\_nbb \_edef\%{\_csstring\%}\_edef\#{\csstring\#}\_let\n=\_relax}
+\_def\beglua{\.savelineno\_bgroup \_setverb \_endlinechar=`\^^J \.begluaA}
+\_ea\_def\_ea\.begluaA\_ea#\_ea1\_csstring\\endlua^^J{\_egroup\.debuglua{#1}\_directlua{#1}}
+\_def\begLUA{\.savelineno\_bgroup \_setverb \_endlinechar=`\^^J \_catcode`\\=0 \.begLUAA}
+\_def\.begLUAA#1\endLUA^^J{\_the\.luamacros\.debuglua{#1}\_directlua{#1}\_egroup}
+\_def\.savelineno{\_edef\.tmp{\_the\_numexpr\_inputlineno+1}}
+\_let\.debuglua=\_ignoreit
+\_def\.printloglua#1{\_wlog{lua code processed (l.\.tmp):^^J#1-------------}}
+\_def\logginglua{\_let\.debuglua=\.printloglua}
+
+\_trick 0055 \sethours \setminutes \setseconds \setweekday ;
+%%%%%%%%%%%%
+
+\_newcount\.hours \_newcount\.minutes \_newcount\.seconds \_newcount\.weekday
+
+\_def\setminutes{%
+ \.minutes=\_directlua{tex.sprint(\_the\_time\_pcent 60)}\_relax
+ \.hours=\_directlua{tex.sprint(math.floor(\_the\_time/60))}\_relax
+}
+\_let\sethours=\setminutes
+\_def\setseconds{\_ea\.setsecondsA\_pdffeedback creationdate\_relax}
+\_def\.setsecondsA#1#2#3#4#5#6#7#8#9{\.setsecondsB}
+\_def\.setsecondsB#1#2#3#4#5#6#7#8\_relax{\.seconds=#6#7\_relax}
+\_def\setweekday{\.weekday=\_directlua{% Zeller's algorithm:
+ local m, y, K, J
+ m = \_the\_month \_ifnum\_month<3 +12 \_fi
+ y = \_the\_year \_ifnum\_month<3 -1 \_fi
+ K = y \_pcent 100
+ J = math.floor(y/100)
+ tex.sprint((\_the\_day + math.floor((13*(m+1))/5) + K +
+ math.floor(K/4) + math.floor(J/4) - 2*J + 6)\_pcent 7)
+ }\_relax
+}
+\_def\.Othe#1{\_ifnum#1<10 0\_fi\_the#1}
+
+\_nspublic \hours \minutes \seconds \weekday \Othe ;
+
+\_trick 0063 \showpglists ;
+%%%%%%%%%%%%
+
+\_def\.addshowpglists{\_directlua{
+ local nodetree = require("nodetree")
+ callback.add_to_callback("pre_shipout_filter", function(head)
+ nodetree.print(head)
+ return head
+ end, "showpglists") }}
+\_gdef\.removeshowpglists{\_directlua{
+ callback.remove_from_callback("pre_shipout_filter", "showpglists") }}
+
+\_def\showpglists #1 {\_addto\.showpgs{#1,}}
+\_def\.showpgs{,}
+
+\_addto\_begoutput{%
+ \_ea\_isinlist\_ea\.showpgs\_ea{\_ea,\_the\_pageno,}\_iftrue
+ \.addshowpglists
+ \_addto\_endoutput{\.removeshowpglists}%
+ \_fi
+}
+
+\_trick 0101 \runsystem ;
+%%%%%%%%%%%%
+
+\_newcount\.exitstatus
+\_def\runsystem#1{\.exitstatus=\_directlua{
+ texio.write_nl("")
+ local status = os.execute("\_luaescapestring{#1}")
+ texio.write("log", "\_nbb runsystem{\_luaescapestring{#1}} status: " .. (status or -1) .. "\_string\n")
+ tex.print(status or -1)
+} }
+
+\_nspublic \exitstatus ;
+
+\_trick 105 \directoutput ;
+%%%%%%%%%%%
+
+\_def\directoutput{\_begingroup \_afterassignment\.directoutputA \_setbox0=}
+\_def\.directoutputA{\_aftergroup \.directoutputB}
+\_def\.directoutputB{\_preshipout0\_box0
+ \_pdfpageheight=\_dimexpr\_ht0+\_dp0+2\_vvkern \_relax
+ \_pdfpagewidth=\_dimexpr\_wd0+2\_hhkern\_relax
+ \_hoffset=\_hhkern \_voffset=\_vvkern
+ \_shipout\_box0
+ \_incr\_pageno
+ \_endgroup
+}
+
+\_trick 0078 \algol ;
+%%%%%%%%%%%%
+
+\_newtoks \_hisyntaxalg
+\_hisyntaxalg = {
+ \_hicolor K \_bf % Keywords
+ \_foreach {Require:}{Ensure:}{Input:}
+ {while}{do}{if}{then}{else}{end}{function}{return}{print}
+ {for}{all}{range}{continue}{repeat}{until}{loop}
+ {not}{and}{or}{xor}{true}{false}
+ \_do {\_replthis{\n#1\n}{\z K{#1}}}
+}
+\_def\.algolmath#1${\_catcodetable\_optexcatcodes \_scantextokens{#1}$}
+
+\_def\algol{\_catcode`$=3 %
+ \_everymath={\.algolmath}%
+ \_def\_ttfont{\_rm}%
+ \_catcode`\!=13
+ \_bgroup \_lccode`\~=`\! \_lowercase{\_egroup \_def~##1~{\_ifx^##1^!\_else{\_bf##1}\_fi}}%
+ \_hisyntax{ALG}%
+}
+\_def\var#1{{\_it\_adef _{\_vrule height.4pt width4pt\_relax}#1}}
+
+\_trick 0079 \ttlineref ;
+%%%%%%%%%%%%
+
+\_def\ttlineref#1{\_adef#1[##1]{\.setlref{##1}}}
+\_protected\_def\.setlref#1{\_sxdef{ttlin:#1}{\_the\_ttline}}
+\_def\lref[#1]{\_trycs{ttlin:#1}{??}}
+
+\_trick 0011 \scaleto \scaletof ;
+%%%%%%%%%%%%
+
+\_def\scaleto#1#{\_def\.tmp{#1}\.scaletoA}
+\_def\.scaletoA#1{\_setbox0=\_hbox{{#1}}%
+ \_edef\.tmp{\_expr{\_bp{\.tmp}/\_bp{\_wd0}}}%
+ \_transformbox{\_pdfscale{\.tmp}{\.tmp}}{#1}}
+
+\_def\scaletof#1#{\_def\.tmp{#1}\.scaletofA}
+\_def\.scaletofA#1{\_setbox0=\_hbox{{#1}}%
+ \_edef\.tmpa{\_expr{\_bp{\.tmp}/\_bp{\_wd0}}}%
+ \.scaletoA{\_setfontsize{mag\.tmpa}\_currvar#1}}
+
+\_trick 0053 \ignoreinspic ;
+%%%%%%%%%%%%
+
+\_def\.trydef #1{\_ifx#1\_undefined \_afterfi{\_def#1}\_else \_afterfi{\_def\.tmp}\_fi}
+\.trydef\nopicw{5cm}
+\.trydef\nopicratio{1.7}
+
+\_let\.inspicBori=\_inspicB
+\_def\.inspicBnew#1{%
+ \_isfile{\_the\_picdir#1}\_iftrue
+ \_edef\.filename{\_the\_picdir#1}%
+ \_setbox0=\_hbox\_bgroup\.inspicBori{#1}% \egroup is in \inspicBori
+ \_else
+ \_edef\.filename{NONE: \_the\_picdir#1}%
+ \_ifdim\_picheight=0pt \_picheight=\_expr{1/\nopicratio}\_picwidth \_fi
+ \_ifdim\_picwidth=0pt \_picwidth=\nopicratio\_picheight \_fi
+ \_ifdim\_picwidth=0pt \_picwidth=\nopicw\_relax \_picheight=\_expr{1/\nopicratio}\_picwidth \_fi
+ \_setbox0=\_hbox to\_picwidth{\_vbox to\_picheight{}\_hss}%
+ \_fi
+ {\LightGrey \_vrule height\_ht0 width\_wd0\Black\_raise1ex\_llap{\.filename\ }}\_egroup
+}
+\_def\ignoreinspic{\_let\_inspicB=\.inspicBnew}
+
+\_trick 0047 \style m \keepstyle ;
+%%%%%%%%%%%%
+
+\_def\.iprefix#1{}
+\_addto\_setlistskip{\_ifnum\_ilevel>1 \_edef\.iprefix{\.iprefix.\_the\_itemnum}\_fi}
+\_sdef{_item:m}{\.iprefix.\_the\_itemnum. }
+\_def\keepstyle{\_defaultitem=\_printitem}
+
+\_trick 0048 \easylist ;
+%%%%%%%%%%%%
+
+\_def\easylist{\_adef*{\.countlist}\_def\enditems{\_fornum 1..\_ilevel\_do{\_enditems}}}
+\_def\.aast{\.countlist}
+\_def\.countlist{\_tmpnum=1 \.countlistA}
+\_def\.countlistA{\_futurelet\.next\.countlistB}
+\_def\.countlistB{\_ifx\.next\.aast \_ea\.countlistC\_else \_ea\.countlistD \_fi}
+\_def\.countlistC#1{\_incr\_tmpnum \.countlistA}
+\_def\.countlistD{%
+ \_ifnum\_tmpnum>\_ilevel \_fornum \_ilevel..\_tmpnum-1 \_do{\_begitems\easylist}\_else
+ \_ifnum\_tmpnum<\_ilevel \_fornum \_tmpnum..\_ilevel-1 \_do{\_enditems}\_fi\_fi
+ \_startitem}
+
+\_trick 0092 \fcread ;
+%%%%%%%%%%%%
+
+\_newtoks\.fcithook
+\_def\.fcitlist{}
+
+\_def\.xbibadd#1{%
+ \_unless \_ifcsname fcit:\_entrykey\_endcsname
+ \_sxdef{fcit:\_entrykey}{}\_xdef\.fcitlist{\.fcitlist\fcititem[\_entrykey]}\_fi
+ \_global \_ea\_addto\_csname fcit:\_entrykey\_ea\_endcsname\_ea{\_expanded{#1}}%
+}
+\_def\.ubibfield{\_unexpanded\_ea{\_bibfield}}
+\_def\.remdotspace #1. \_end #2\_relax #3{%
+ \_ifx ^#2^\_else \_ea \_gdef \_csname fcit:#3\_endcsname{#1}\_fi}
+\_def\.remdotxspace #1.\ \_end #2\_relax #3{%
+ \_ifx ^#2^\_else \_ea \_gdef \_csname fcit:#3\_endcsname{#1}\_fi}
+
+\.fcithook{
+ \_def\_dofullfield#1#2{\_def\_dofield##1{#1}\.xbibadd{\_ea\_dofield\_ea{\.ubibfield}}}
+ \_def\_dofemptyfield#1#2{\_def\_dofield##1{#2}\.xbibadd{\_ea\_dofield\_ea{\.ubibfield}}}
+ \_def\_bprintaB #1*#2*#3\_fin{%
+ \_ifx\_bibfield\.readauthor \_def\_bibfield{}\.readauthor \_fi
+ \_ifx\_bibfield\.readeditor \_def\_bibfield{}\.readeditor \_fi
+ \.xbibadd{\_if^#3^#1\_else\_ea\_bprintaC\_ea{\.ubibfield}{#1}{#2}\_fi}}
+ \_def\_authorini#1\_endcsname{\_edef\_bibfield{\.ubibfield\_authorname}}
+ \_def\_editorini#1\_endcsname{\_edef\_bibfield{\.ubibfield\_editorname}}
+ \_def\_addauthlist{}
+ \_def\_bprintv [#1]#2#3{#3}
+ \_def\_Inclause{\.xbibadd{In:~}}
+ \_def\_dobibmark{}
+ \_let\_url=\_relax \_let\_ulink=\_relax \_def\_preurl{}
+ \_def\_citelist{\_citeI[*]}
+ \_let\fcititem=\_relax
+}
+\_def\.readauthor{\_loopauthors {author}}
+\_def\.readeditor{\_loopauthors {editor}}
+
+\_def\fcread (#1) #2 {{%
+ \_setbox0=\_vbox{\_bibtexhook=\.fcithook
+ \_bibpart{fullcites}\_nocite[*]\_usebib/c (#1) #2 }
+ \_def\fcititem[##1]{%
+ \_ea\_ea\_ea \.remdotspace \_csname fcit:##1\_endcsname \_end . \_end \_relax {##1}%
+ \_ea\_ea\_ea \.remdotxspace \_csname fcit:##1\_endcsname \_end .\ \_end \_relax {##1}%
+ }\.fcitlist % removing last .\space or .space from each bib-record
+}}
+\_def\fullcite[#1]{\_trycs{fcit:#1}{??\_opwarning{\_string\fullcite[#1] unknown label}}}
+
+\_trick 0071 \shadedframe ;
+%%%%%%%%%%%%
+
+\_def\.shadedframedefaults {% defaults:
+ frame-color=\Grey, % color of frame rules
+ text-color=\Black, % color ot text inside the frame
+ shadow-color=\LightGrey, % color of shadow
+ bg-color=\Yellow, % background color inside the frame
+ rule-width=1pt, % width of rules used in the frame
+ v-margins=4pt, % vertical space between text and frame
+ h-margins=4pt, % horizontal space between text and frame
+ shade-width=4pt, % the width of the shadow
+ text-width=4cm, % width of the text inside the frame
+}
+\_optdef\shadedframe [] #1{\_bgroup
+ \_readkv\.shadedframedefaults \_readkv{\_the\_opt}%
+ \_vvkern=\_kv{v-margins}\_hhkern=\_kv{h-margins}%
+ \_rulewidth=\_kv{rule-width}\_hsize=\_kv{text-width}\relax
+ \_kv{frame-color}%
+ \_setbox0=\_hbox{\_frame{\_vbox{\_kv{text-color}\_noindent\_ignorespaces#1}}}%
+ \_edef\.htzo{\_the\_ht0}\_edef\.wdzo{\_the\_wd0}%
+ \_kv{shadow-color}%
+ \_hbox{\_vbox{\_hbox{\_rlap{\_kv{bg-color}\_vrule height\_ht0 width\_wd0 depth\_dp0}\_box0}%
+ \_nointerlineskip \_moveright\_kv{shade-width}
+ \_hbox{\_vrule height\_kv{shade-width}width\.wdzo}\_kern-\_kv{shade-width}}%
+ \_kern-\_kv{shade-width}\_vrule height\.htzo width\kv{shade-width}}%
+ \_egroup
+}
+
+\_trick 0073 \roundframe ;
+%%%%%%%%%%%%
+
+\_def \.roundframedefaults {% default parameters:
+ round-corner=3mm, % diameter of corners
+ title-bgcolor=\Blue, % background color of the title area
+ title-color=\White, % color of title text
+ title-font=\_bf, % font of title text
+ title-above=2pt, % space above the first line of title
+ title-below=1pt, % space below the last line of title
+ midrule-color=\Yellow, % color of the rule between title and text area
+ midrule-width=2pt, % thickness of the rule between title and text area
+ text-bgcolor=\LightGrey, % background color of the text area
+ text-color=\Black, % color of normal text
+ text-font=\_rm, % font of normal text
+ text-width=6cm, % text paragraph width; frame width = text width + margins
+ text-margins=3mm, % left and right margins
+ text-above=3pt, % space above the first line of text
+ text-below=1pt, % space below the last line of text
+ shadow-width=2pt, % shadow thickness (if 0pt then no shadow printed)
+}
+\_optdef \roundframe [] #1#2{\_bgroup
+ \_kvdict{_optextrick:roundframe}% dictionary of used key-value parameters
+ \_readkv\.roundframedefaults \_readkv{\_the\_opt}%
+ \_roundness=\_kv{round-corner}\_relax
+ \_hsize=\_kv{text-width}\_relax
+ \_leftskip=\_kv{text-margins}\_relax \_rightskip=\_leftskip
+ \_setbox0=\_vbox{%
+ \.bgbox{\_kv{title-bgcolor}}{\_kern\_kv{title-above}%
+ \_noindent\_strut\_kv{title-color}\_kv{title-font}#1\.parstrut\_kern\_kv{title-below}}
+ \_kv{midrule-color}\_hrule height\_kv{midrule-width}%
+ \.bgbox{\_kv{text-bgcolor}}{\_kern\_kv{text-above}%
+ \_noindent\_strut\_kv{text-color}\_kv{text-font}#2\.parstrut\_kern\_kv{text-below}}}
+ \_setbox1=\_vbox to\_dimexpr\_ht0-2\_roundness{}\_wd1=\_dimexpr\_wd0-2\_roundness\_relax
+ \_hbox{\_unless\_ifdim\_kv{shadow-width}=0pt \.roundframeshadow \_fi
+ \_clipinoval .5\_wd0 .5\_ht0 \_wd0 \_ht0 {\_box0}}%
+ \_egroup
+}
+\_def\.bgbox#1#2{\_setbox0=\_vbox{#2}\_hbox{\_rlap{#1\_vrule height\_ht0 depth\_dp0 width\_wd0}\_box0}}
+\_def\.parstrut{\_par\_kern-\_prevdepth\_kern\_dp\_strutbox}
+\_def\.roundframeshadow{\_raise\_roundness\_rlap{\_edef\_shadowb{\_bp{\_kv{shadow-width}}}%
+ \_inoval[\_fcolor=\Grey \_roundness=\_kv{round-corner} \_shadow=Y \_lwidth=0pt]{\_box1}}}
+\_edef\.tmp{\_the\_kvdict}
+{\_kvdict{_optextrick:roundframe} \_ea\_foreach\.roundframedefaults \_do #1#2=#3,{\_global\_kvx{#1#2}{}}
+ \_global\_nokvx{\_opwarning{\_string\roundframe: Unknown option "#1"}}}
+\_kvdict=\_ea{\.tmp} % restoring \_kvdict, because \globaldefs=1
+
+\_trick 0103 \cancel ;
+%%%%%%%%%%%%
+
+\_def\cancel#1#{\_isempty{#1}\_iftrue \_afterfi{\cancel/}
+ \_else
+ \_lowercase{\_casesof #1}
+ / {\_let\.cancline=\.drawFslash}
+ \\ {\_let\.cancline=\.drawBslash}
+ x {\_def\.cancline{\.drawBslash\.drawFslash}}
+ - {\_let\.cancline=\.drawHline}
+ \_finc {}%
+ \_ea\.cancelA
+ \_fi
+}
+\_def\.cancelA{\_ifmmode \_ea\.cancelM \_else \_ea\.cancelT \_fi}
+\_def\.cancelT#1{\_setbox0=\_hbox{#1}\.cancelF} % text mode
+\_def\.cancelM#1{\_mathstyles{\_setbox0=\_hbox{$\_currstyle#1$}\_cancelF}} % math mode
+\_def\.cancelF{\_edef\.tmp{\.cancline}\_quitvmode\_box0 \_pdfliteral{q \_useit{\cancelparams} \.tmp S Q}}
+\_def\.drawFslash{\_bp{-\_wd0} \_bp{-\_dp0} m 0 \_bp{\_ht0} l } % forward slash
+\_def\.drawBslash{\_bp{-\_wd0} \_bp{\_ht0} m 0 \_bp{-\_dp0} l } % backward slash
+\_def\.drawHline {\_bp{-\_wd0} \_bp{.5ex} m 0 \_bp{.5ex} l } % horizontal line
+\_ifx\cancelparams\_undefined \_def\cancelparams{1 0 0 RG 1 J .6 w}\_fi % color RG linetype J linewidth w
+
+\_trick 0070 \keystroke ;
+%%%%%%%%%%%%
+
+\_ifx\keysize\_undefined \_newdimen\keysize \keysize=1.3em \_fi
+\_ifx\keystrokefont\_undefined \_def\keystrokefont{\_setfontsize{mag.77}\_cs{sans}\_rm} \_fi
+
+\_newbox\.keylbox \_newbox\.keymbox \_newbox\.keyrbox
+\_edef\.picheight{\_the\_picheight}
+\_setbox\.keylbox=\_hbox{\_picheight=\keysize \_inspic{keystroke_left.pdf}}
+\_setbox\.keymbox=\_hbox{\_picheight=\keysize \_inspic{keystroke_middle.pdf}}
+\_setbox\.keyrbox=\_hbox{\_picheight=\keysize \_inspic{keystroke_right.pdf}}
+\_picheight=\.picheight
+
+\_def\keystroke#1{\_setbox0=\_hbox{\keystrokefont#1}%
+ \_leavevmode \_lower.2\keysize \_hbox{\_copy\.keylbox
+ \_tmpdim=\_wd\.keymbox
+ \_ifdim\_wd0>\_tmpdim \_tmpdim=\_wd0 \_fi
+ \_ifdim\_tmpdim>\_wd\.keymbox
+ \_pdfsave \_pdfscale{\_expr{\_bp{\_tmpdim}/\_bp{\_wd\.keymbox}}}{1}%
+ \_rlap{\_copy\.keymbox}\_pdfrestore
+ \_else \_rlap{\_copy\.keymbox}\_fi
+ \_raise.33\keysize \_hbox to\_tmpdim{\_hss\_box0\_hss}\_copy\.keyrbox}%
+}
+
+\_trick 0004 \colortab ;
+%%%%%%%%%%%%
+
+\_def\.tabdC{\_futurelet\.next\.setcellcolor##\_fin\_hfil\_hfil}
+\_def\.tabdL{\_futurelet\.next\.setcellcolor##\_fin\_relax\_hfil}
+\_def\.tabdR{\_futurelet\.next\.setcellcolor##\_fin\_hfil\_relax}
+\_def\.tabdP#1{\_futurelet\.next\.setcellcolor##\_fin\_vtop
+ {\_hsize=#1\_relax \_baselineskip=\_normalbaselineskip
+ \_lineskiplimit=0pt \_noindent\.tmp\_unsskip\_lower\_dp\_tstrutbox\_hbox{}}}
+\_def\colortab{\_tablinespace=0pt \_let\_paramtabdeclarep=\.tabdP
+ \_let\_tabdeclarec=\.tabdC \_let\_tabdeclarel=\.tabdL \_let\_tabdeclarer=\.tabdR}
+\_def\.setcellcolor{%
+ \_ifx\.next\_setcolor \_ea\.setcellcolorC\_else \_ea\.setcellcolorD\_fi}
+\_def\.setcellcolorC\_setcolor#1#2#3#4\_fin#5#6{%
+ \_ifx#5\_vtop \_def\.tmp{#4}%
+ \_setbox0=\_hbox{\_the\_tabiteml\_vtop{\_localcolor#6}\_the\_tabitemr}%
+ \_the\_tabstrut {\_localcolor\_setcolor{#1}{#2}{#3}\_vrule width\_wd0}\_kern-\_wd0 \_box0
+ \_else
+ \_setbox0=\_hbox{\_the\_tabiteml\_localcolor#4\_unsskip\_the\_tabitemr}%
+ {\_localcolor\_setcolor{#1}{#2}{#3}%
+ \_the\_tabstrut\_leaders\_vrule\_hskip\_wd0 \_ifx#5\_hfil plus1fil\_fi}\_kern-\_wd0 \_box0
+ \_ifx#6\_hfil
+ {\_kern-.3bp \_localcolor\_setcolor{#1}{#2}{#3}\_leaders\_vrule\_hskip.3bp plus1fil}\_fi
+ \_fi
+}
+\_def\.setcellcolorD{\_ifx\cellcolor\undefined \_let\.next=\.setcellcolorN
+ \_else \_def\.next{\_ea\_ea\_ea\.setcellcolorC\cellcolor}%
+ \_fi \.next
+}
+\_def\.setcellcolorN#1\_fin#2#3{#2\_the\_tabiteml{\_localcolor#1\_unskip}\_the\_tabitemr#3}
+
+\_def\multispanc#1#2#3{\_multispan{#1}%
+ \_ea\_ea\_ea\.cellcolexp#2#3\_fin\_hfil\_hfil\_ignorespaces}
+\_def\.cellcolexp{\_futurelet\.next\.setcellcolor}
+
+\_trick 0005 \crx ;
+%%%%%%%%%%%%
+
+\_newcount\.tabline \.tabline=1
+\_def\crx {\_crcr \_ifodd\.tabline \.colortabline \_else\_noalign{\_hrule height0pt}\_fi \_incr\.tabline}
+\_def\.colortabline{\_noalign{\_localcolor\LightGrey
+ \_hrule height\ht\_strutbox depth\_dimexpr\_dp\_strutbox +2\_tablinespace\_relax
+ \_kern-\_dimexpr\ht\_strutbox+\_dp\_strutbox +2\_tablinespace}}
+
+\_trick 0007 \crtop \crbot \crmid ;
+%%%%%%%%%%%%
+
+\_def\crtop{\_crcr \_noalign{\_hrule height.6pt \_kern2.5pt}}
+\_def\crbot{\_crcr \_noalign{\_kern2.5pt\_hrule height.6pt}}
+\_def\crmid{\_crcr \_noalign{\_kern1pt\_hrule height.4pt\_kern1pt}}
+
+\_trick 0016 \longtable ;
+%%%%%%%%%%%%
+
+\_def\longtable#1#2{\_goodbreak \_bgroup \_tablinespace=0pt \_let\_zerotabrule=\_empty
+ \_setbox0=\_table{#1}{\.strutT\_relax #2}
+ \_setbox1=\_vbox{\_unvbox0 \_setbox2=\_vbox{}\.revertbox}
+ \_setbox2=\_vbox{\_unvbox2 \_global\_setbox4=\_lastbox\_unskip \_global\_setbox5=\_lastbox\_unskip}
+ \.whatfree4 \_advance\_tmpdim by-.8pt \_ifdim\_tmpdim<\_baselineskip \_vfil\_break \_fi
+ \_offinterlineskip \.crule\.center4\.crule\.center5 \.printboxes
+ \.center5\.crule \_egroup \_goodbreak
+}
+\_def\.whatfree#1{\_tmpdim=\_vsize \_advance\_tmpdim by-\_pagetotal
+ \_advance\_tmpdim by-\_prevdepth \_advance\_tmpdim by-.4pt
+ \_advance\_tmpdim by-\_ht#1 \_advance\_tmpdim by-\_dp#1 \_advance\_tmpdim by-\_ht5 }
+\_def\.revertbox {\_setbox0=\_lastbox\_unskip
+ \_ifvoid0 \_else \_global\_setbox2=\_vbox{\_unvbox2\_box0} \_ea\.revertbox\_fi}
+\_def\.printboxes{\_setbox2=\_vbox{\_unvbox2 \_global\_setbox0=\_lastbox\_unskip}
+ \_ifvoid0 \_else \.whatfree0
+ \_ifdim\_tmpdim<0pt \.center5\.crule\_vfil\_break \.crule\.center4\.crule\.center5 \_fi
+ \.center0 \_nobreak \.printboxes \_fi}
+\_def\.crule{\_centerline{\_hbox to\_wd4{\_hrulefill}}\_nobreak}
+\_def\.center#1{\_centerline{\_copy#1}\_nobreak}
+
+\_def\.strutT {\_vrule height1.8em depth.8em width0pt} % strut for the title
+
+\_trick 0032 \vcent \vbot ;
+%%%%%%%%%%%%
+
+\_def\vbot {\_let\_tableparbox=\_vbox}
+\_def\vcent {\_toksapp\_tabiteml{$}\_tokspre\_tabitemr{$}\_let\_tableparbox=\_vcenter}
+
+\_trick 0046 \tnote ;
+%%%%%%%%%%%%
+
+\_newcount\.tnotenum
+\_def\.tnotelist{}
+\_def\.tnoteformat{$\Red^{\_rm\_athe\.tnotenum}$}
+\_def\tnote#1{\_incr\.tnotenum \.tnoteformat\_global\_addto\.tnotelist{{#1}}}
+\_def\tnoteprint{\_par\_noindent \.tnotenum=0
+ \_ea\_foreach\.tnotelist \_do{\_advance\.tnotenum by1 \.tnoteformat##1 }\_par
+ \_global\.tnotenum=0 \_gdef\.tnotelist{}%
+}
+
+\_trick 0050 \tabnodes \tablebefore ;
+%%%%%%%%%%%%
+
+\_def\tablebefore{\_ifvmode \_nointerlineskip\_null \_fi
+ \_incr\.tndnum \_setpos[t\_the\.tndnum:ori:b]\_ea\.tbpxpy\_ea{\_the\.tndnum}{b}\_decr\.tndnum
+}
+\_def\tableafter {\_setpos[t\_the\_tndnum:ori:e]\_ea\.tbpxpy\_ea{\_the\.tndnum}{e}}
+\_def\.tbpxpy#1#2{%
+ \_def\.tbpx[##1]{\_expr{\_bp{\_posx[t#1:##1]}-\_bp{\_posx[t#1:ori:#2]}}}%
+ \_def\.tbpy[##1]{\_expr{\_bp{\_posy[t#1:##1]}-\_bp{\_posy[t#1:ori:#2]}}}%
+}
+\_newcount\.tndnum \_newcount\.tablerownum
+\_def\.putnodeh#1{\_omit\_relax
+ \_setpos[t\_the\.tndnum:l#1]\_hskip0pt plus1fill\_relax \_setpos[t\_the\.tndnum:r#1]}
+\_def\.putnodelr{\_fornum 1..\_colnum-1\_do{\.putnodeh{##1}&}\.putnodeh{\_the\_colnum}%
+ \_gdef\.putnode{\_noalign{\.putnodev}}\_cr}
+\_def\.putnodev{\_setpos[t\_the\.tndnum:v\_the\.tablerownum]\_incr\.tablerownum}
+\_def\tabnodes{\_incr\.tndnum \.tablerownum=0
+ \_def\_tablepxpreset{\_everycr{}}\_let\.putnode=\.putnodelr \_everycr={\.putnode}}
+
+\_def\itl[#1,#2]{\_expr{\.tbpx[l\.enum{#2}]} \_expr{\.tbpy[v\.enum{#1-1}]}}
+\_def\icl[#1,#2]{\_expr{\.tbpx[l\.enum{#2}]}
+ \_expr{(\.tbpy[v\.enum{#1-1}]+(\.tbpy[v\.enum{#1}]))/2}}
+\_def\ibl[#1,#2]{\_expr{\.tbpx[l\.enum{#2}]} \_expr{\.tbpy[v\.enum{#1}]}}
+\_def\itc[#1,#2]{\_expr{(\.tbpx[l\.enum{#2}]+(\.tbpx[r\.enum{#2}]))/2}
+ \_expr{\.tbpy[v\.enum{#1-1}]}}
+\_def\icc[#1,#2]{\_expr{(\.tbpx[l\.enum{#2}]+(\.tbpx[r\.enum{#2}]))/2}
+ \_expr{(\.tbpy[v\.enum{#1-1}]+(\.tbpy[v\.enum{#1}]))/2}}
+\_def\ibc[#1,#2]{\_expr{(\.tbpx[l\.enum{#2}]+(\.tbpx[r\.enum{#2}]))/2}
+ \_expr{\.tbpy[v\.enum{#1}]}}
+\_def\itr[#1,#2]{\_expr{\.tbpx[r\.enum{#2}]} \_expr{\.tbpy[v\.enum{#1-1}]}}
+\_def\icr[#1,#2]{\_expr{\.tbpx[r\.enum{#2}]}
+ \_expr{(\.tbpy[v\.enum{#1-1}]+(\.tbpy[v\.enum{#1}]))/2}}
+\_def\ibr[#1,#2]{\_expr{\.tbpx[r\.enum{#2}]} \_expr{\.tbpy[v\.enum{#1}]}}
+\_def\iwd[#1,#2]{\_expr{\.tbpx[r\.enum{#2}]-(\.tbpx[l\.enum{#2}])}}
+\_def\iht[#1,#2]{\_expr{\.tbpy[v\.enum{#1-1}]-(\.tbpy[v\.enum{#1}])}}
+
+\_def\.enum#1{\_number\_numexpr#1\_relax}
+\_def\ishift #1{\_ea\.ishifta#1} % \ishift[2,3][1pt,2.5pt]
+\_def\.ishifta \_expr#1 \_expr#2#3#4,#5]{\_expr{#1+(\_bp{#4})} \_expr{#2+(\_bp{#5})}}
+\_def\tabpos#1#2{#1\_ifx\ishift#2\_afterfi{\_ea\_ea\_ea\_ea\_ea\_ea}\_fi\_ea\.tabposA#2}
+\_def\.tabposA\_expr#1 \_expr#2{\_expr{#1}bp \_expr{#2}bp}
+
+\_trick 0031 \framedblocks ;
+%%%%%%%%%%%%
+
+\_newcount\.blocklevel % nesting level of blocks
+\_def\begblock{\_par\_bgroup
+ \_advance\.blocklevel by1 \_advance\_leftskip by\_iindent \_rightskip=\_leftskip
+ \_medskip
+ \_openref\_pdfsavepos \_ea\_wref\_ea\.Xblock\_ea{\_ea{\_the\.blocklevel}B{\_the\_pdflastypos}}
+ \_nobreak \_medskip
+}
+\_def\endblock{\_par\_nobreak\_medskip
+ \_pdfsavepos \_ea\_wref\_ea\.Xblock\_ea{\_ea{\_the\.blocklevel}E{\_the\_pdflastypos}}
+ \_medskip \_egroup
+}
+\_newdimen\.frtop \_newdimen\.frbottom % positions of top and bottom text on the pages
+\_pgbackground={%
+ \_slet{_optextrick_tmp}{frm:\_the\_gpageno}
+ \_ifx\.tmp\_undefined \_def\.tmp{}\_fi
+ \.frtop=\_dimexpr \_pdfpageheight-\_voffset+\_smallskipamount\_relax
+ \.frbottom=\_dimexpr\_pdfpageheight-\_voffset-\_vsize-\_medskipamount\_relax
+ \_ifx\.frnext y \_edef\.tmp{B{\_number\.frtop}\.tmp}\_global\_let\.frnext n\_fi
+ \_ea\.printframes \.tmp B{0}E{\_number\.frbottom}
+ \_ifx\frameslist\_empty \_else
+ \_pdfliteral{q 1 0 0 1 0 \_bp{-\_pdfpageheight} cm \frameslist Q}\_fi
+}
+\_def\.printframes B#1#2E#3{\_ifnum#1=0 \_else
+ \printframe {\_hoffset}{#3sp}{\_xhsize}{\_ifnum#1=-1 \_number\.frtop\_else#1\_fi sp-#3sp}
+ \_ifx^#2^\_else \_global\_let\.frnext=y \_let\.printframes=\_relax \_fi
+ \_ea\.printframes\_fi
+}
+\_def\frameslist{}
+\_ifx\printframe\_undefined
+\_def\printframe #1#2#3#4{\_edef\frameslist{\frameslist
+ .8 g \_bp{#1} \_bp{#2} \_bp{#3} \_bp{#4} re f }%
+}
+\_fi
+\_def\framedblocks{} % for autoloading only, it redefines standard \begblock, \endblock
+\_globaldefs=0 % \refdecl needs to be processed when \localdefs=0
+\_refdecl{%
+ \_def\.Xblock#1#2#3{\_ifnum#1=1 \_edef\.tmp{frm:\_ea\_ignoresecond\_currpage}^^J
+ \_unless\_ifcsname \.tmp \_endcsname \_sxdef{\.tmp}{}\_fi^^J
+ \_sxdef{\.tmp}{\_cs{\.tmp}#2{#3}}\_fi}
+}
+
+\_trick 0086 \twoblocks ;
+%%%%%%%%%%%%
+
+\_newdimen\.pageblank
+\_newdimen\.columnsht
+
+\_def\.setcolumn{\_advance\_hsize by-\_colsep \_hsize=.5\_hsize \_penalty0 }
+\_def\twoblocks{\_par
+ \_begingroup \_hbadness=5000 \_splittopskip=1em plus1fil \_brokenpenalty=0
+ \_setbox0=\_vbox\_bgroup \.setcolumn
+ \_aftergroup\.twoblocksA
+ \_let\.next=%
+}
+\_def\.twoblocksA{%
+ \_setbox1=\_vbox\_bgroup \.setcolumn
+ \_aftergroup\.twoblocksB
+ \_let\.next=%
+}
+\_def\.twoblocksB{\_setbox2=\_vsplit0 to0pt \_setbox2=\_vsplit1 to0pt \.twoblocksC}
+\_def\.twoblocksC{%
+ \_penalty0 \_vskip\_parskip
+ \_ifdim\_pagegoal=\_maxdimen \.pageblank=\_vsize \_else \.pageblank=\_pagegoal \_fi
+ \_advance\.pageblank by-\_pagetotal
+ \_ifdim\.pageblank<24pt \_vfil\_break \.pageblank=\_vsize \_fi
+ \_ifdim\_ht0>\_ht1 \.columnsht=\_ht0 \_dimen0=\_dp0 \_else \.columnsht=\_ht1 \_dimen0=\_dp1 \_fi
+ \_ifdim\.columnsht>\.pageblank
+ \_setbox2=\_vsplit0 to\.pageblank \_setbox3=\_vsplit1 to\.pageblank
+ \_line{\.xvtop2\_hss\.xvtop3}
+ \_kern-\_baselineskip \_nobreak\_vfil\_break
+ \_ea\.twoblocksC
+ \_else
+ \_line{\.xvtop0\_hss\.xvtop1}
+ \_prevdepth=\_dimen0
+ \_endgroup
+ \_fi
+}
+\_def\.xvtop#1{\_vtop{\_null\_kern-\_splittopskip\_unvbox#1}}
+
+\_trick 0069 \pstart ;
+%%%%%%%%%%%%
+
+\_newcount\.firstlinenum
+\_newcount\.gprevgraf
+
+\_def\pstart{\_par \_setbox0=\_vbox\_bgroup
+ \_def\_par{\_endgraf\_advance\.gprevgraf by\_prevgraf \_prevgraf=0 }}
+\_def\pend{\_par \_global\_tmpnum=\.gprevgraf \_egroup
+ \_ifnum\.firstlinenum=0 \.firstlinenum=1 \_fi
+ \_advance\_tmpnum by\.firstlinenum
+ \.firstlinenum=\_tmpnum \_advance\_tmpnum by-1
+ \_setbox0=\_vbox{\_unvbox0
+ \_setbox2=\_hbox{}
+ \_loop
+ \_unskip\_unskip\_unpenalty \_setbox1=\_lastbox
+ \_ifvoid1 \_else
+ \_global\_setbox2=\_hbox{\_llap{\.pendprintnum}\_box1\_penalty0\_unhbox2}
+ \_advance\_tmpnum by-1
+ \_repeat
+ }\_noindent\_unhbox2 \_par
+}
+\_def\.pendprintnum{\_setfontsize{mag.6}\_rm\_the\_tmpnum\_kern.8em}
+
+\_trick 0021 \settabs ;
+%%%%%%%%%%%%
+
+\_def\tabs #1\cr{\_setbox0=\_hbox\_bgroup \.tabA #1&\cr&}
+\_def\.tabA #1&{\_ifx\cr#1\_egroup\_box0 \_else
+ \_egroup
+ \_tmpdim=\_maxdimen \_ea\.tabB \.tabsdata {}\_relax
+ \_ifdim \_tmpdim=\_maxdimen \_tmpdim=0pt
+ \_else \_advance\_tmpdim by-\_wd0 \_fi
+ \_setbox0=\_hbox\_bgroup \_unhbox0 \_kern\_tmpdim \_ignorespaces#1\_unskip\_kern1sp
+ \_ea\.tabA \_fi
+}
+\_def\.tabB #1{\_ifx^#1^\_else \_unless\_ifdim \_wd0>#1 \_tmpdim=#1 \.tabC \_fi \_ea\.tabB \_fi}
+\_def\.tabC #1\_relax {\_fi\_fi}
+
+\_def\settabs #1{\_def\.tabsdata{}\_ifx\tabs#1\_ea\.settabstext \_else\_ea\.settabscols \_fi #1}
+\_def\.settabscols #1\columns{\_tmpdim=\_hsize \_divide\_tmpdim by#1\_relax
+ \_fornum 0..#1 \_do {\_edef\.tabsdata{\.tabsdata{\_the\_dimexpr##1\_tmpdim\_relax}}}}
+
+\_def\.settabstext #1#2\cr{\_setbox0=\_hbox\_bgroup \.settabA #2&\cr&}
+\_def\.settabA #1&{\_ifx\cr#1\_egroup \_edef\.tabsdata{\.tabsdata{\_the\_wd0}}\_else
+ #1\_egroup \_edef\.tabsdata{\.tabsdata{\_the\_wd0}}%
+ \_setbox0=\_hbox\_bgroup \_unhbox0
+ \_ea\.settabA \_fi
+}
+\_def\.tabsdata{} % default: no tabulators set
+
+\_trick 0035 \import ;
+%%%%%%%%%%%%
+
+\_def\import#1#2{\_def\.tmp{\_gtoksapp\_picdir{#1/}\input{#2}}%
+ \_ea\.tmp\_ea\_global\_ea\_picdir\_ea{\_the\_picdir}}
+\_def\input#1{\_input{\_the\_picdir#1}}
+
+\_trick 0051 \incrpp ;
+%%%%%%%%%%%%
+
+\_openref
+\_def\thepp#1{\_trycs{pp:\_csstring#1}{?\_the#1}}
+\_def\thepplast#1#2{\_trycs{lastpp:\_csstring#1:#2}{?\_the#1}}
+\_def\truepage{?\_the\_pageno}
+\_def\incrpp#1{\_incr#1%
+ \_isdefined{_pgref:pp:\_csstring#1:\_the#1}\_iftrue
+ \_edef\.tmp{\_cs{_pgref:pp:\_csstring#1:\_the#1}}%
+ \_ea\_ifx\_csname currpp:\_csstring#1\_endcsname\.tmp
+ \_sxdef{pp:\_csstring#1}{\_the\_numexpr\_cs{pp:\_csstring#1}+1\_relax}%
+ \_else \_sxdef{pp:\_csstring#1}{\_trycs{resetpp:\csstring#1}{1}}%
+ \_sxdef{currpp:\csstring#1}{\.tmp}\_fi
+ \_xdef\truepage{\_ea\_ea\_ea\_usesecond \_csname currpp:\_csstring#1\_endcsname}%
+ \_sxdef{lastpp:\_csstring#1:\truepage}{\_cs{pp:\_csstring#1}}%
+ \_else \_incr\_unresolvedrefs \_openref \_fi
+ \_ewref \_Xlabel {{pp:\csstring#1:\the#1}{}}%
+}
+
+\_trick 0115 \ispageodd ;
+
+\_def\ispageodd#1{%
+ \_incr\_mnotenum
+ \_ifcsname _mn:\_the\_mnotenum \_endcsname
+ \_expanded{\_let \_noexpand\.pgtype =\_cs{_mn:\_the\_mnotenum}}\_else
+ \_let\.pgtype=\_right \_opwarning{pageside is unknown, TeX me again}\_openref
+ \_fi
+ \_wref\_Xmnote{}%
+ #1\_else \_ea\_unless\_fi \_ifx\.pgtype\_right
+}
+
+\_trick 0033 \iniseccc \seccc ;
+
+\_newcount \_secccnum
+\_def \_thesecccnum {\_othe\_chapnum.\_the\_secnum.\_the\_seccnum.\_the\_secccnum}
+
+\_optdef\_seccc[]{\_trylabel \_scantoeol\_inseccc}
+
+\_def\_inseccc #1{\_par \_sectionlevel=4
+ \_def \_savedtitle {#1}% saved to .ref file
+ \_ifnonum \_else {\_globaldefs=1 \_incr\_secccnum \_secccx}\_fi
+ \_edef \_therefnum {\_ifnonum \_space \_else \_thesecccnum \_fi}%
+ \_printseccc{\_scantextokens{#1}}%
+ \_resetnonumnotoc
+}
+\public \seccc ;
+
+\_def \_seccx {\_secccx \_secccnum=0 }
+\_def \_secccx {}
+
+\_def\_printseccc#1{\_par
+ \_abovetitle{\_penalty-100}{\_medskip}
+ {\_bf \_noindent \_raggedright \_printrefnum[@\_quad]#1\_nbpar}%
+ \_nobreak \_belowtitle{\_smallskip}%
+ \_firstnoindent
+}
+
+\_def\iniseccc{} % use it for autoloading the OpTeX trick code before \maketoc
+\_sdef{_tocl:4}#1#2#3{\_advance\_leftskip by2\_iindent \_cs{_tocl:2}{#1}{#2}{#3}}
+
+\_trick 0066 \makeLOF \makeLOT \captionT \captionF ;
+%%%%%%%%%%%%
+
+\_def\captionT [#1]#2{\_caption/t[#1]\_ewref\.Xtab{{#1}{\_thetnum}{#2}}\_ignorespaces}
+\_def\captionF [#1]#2{\_caption/f[#1]\_ewref\.Xfig{{#1}{\_thefnum}{#2}}\_ignorespaces}
+
+\_def\.lline#1#2#3#4#5{\_line{\_hskip2em\_llap{\_bf#2 } #3 \_tocdotfill\ \_ilink[pg:#4]{#5}}}
+
+\_def\.makell#1#2{\_par
+ \_ifx#1\_undefined \_opwarning{no data for list of #2, try to run TeX again}\_openref
+ \_else #1\_fi
+}
+\_def\makeLOF{\.makell\.loflist{figures}}
+\_def\makeLOT{\.makell\.lotlist{tables}}
+
+\_globaldefs=0 % \refdecl needs to be processed when \localdefs=0
+\_refdecl{%
+\_def\.lotlist{} \_def\.loflist{}^^J
+\_def\.Xtab#1#2#3{\_addto\.lotlist{\.lline{#1}{#2}{#3}}\_ea\_addto\_ea\.lotlist\_ea{\_currpage}}^^J
+\_def\.Xfig#1#2#3{\_addto\.loflist{\.lline{#1}{#2}{#3}}\_ea\_addto\_ea\.loflist\_ea{\_currpage}}
+}
+
+\_trick 0121 \correctvsize ;
+%%%%%%%%%%%%
+
+\_def\correctvsize{%
+ \_vsize=\_dimexpr
+ \_expr[0]{\_bp{\_vsize-\_topskip}//\_bp{\_baselineskip}}\_baselineskip
+ +\_topskip \_relax
+}
+
+\_trick end ;
+
+\_endcode
+
+2023-11-15 \correctvsize added
+2023-11-09 \makeLOF, \makeLOT aded
+2023-11-08 \ispageodd, \seccc added
+2023-11-07 \settabs \import \incrpp added
+2023-11-05 \twoblocks, \pstart added
+2023-11-03 \framedblocks added
+2023-11-01 \longtable, \vcent, \vbot, \tnote, \tabnodes added
+2023-10-31 \ignoreinspic, \keystroke, \colortab, \crx, \crtop, \crbot, \crmid added
+2023-10-23 \shadedframe, \roundframe added
+2023-10-21 \fcread, \fullcite added
+2023-10-20 \style m, \keepstyle, \easylist, \ttlineref added
+2023-10-19 \directoutput, \scaleto added
+2023-10-18 \algol, \cancel added
+2023-10-18 \createfile added
+2023-10-17 released
diff --git a/macros/optex/base/optex.ini b/macros/optex/base/optex.ini
index 5713354a69..b65832faf8 100644
--- a/macros/optex/base/optex.ini
+++ b/macros/optex/base/optex.ini
@@ -21,7 +21,7 @@
% OpTeX version
-\def\optexversion{1.12 May 2023}
+\def\optexversion{1.13 Nov 2023}
\def\fmtname{OpTeX}
\let\fmtversion=\optexversion
diff --git a/macros/optex/base/optex.lua b/macros/optex/base/optex.lua
index 40915fd6d4..c6ea56d794 100644
--- a/macros/optex/base/optex.lua
+++ b/macros/optex/base/optex.lua
@@ -675,9 +675,9 @@ local function set_node_color(n, color) -- "1 0 0 rg" or "0 g", etc.
attr = tex_getcount(color_count)
tex_setcount(color_count, attr + 1)
local strattr = tostring(attr)
- token_setmacro("_color::"..color, strattr)
- token_setmacro("_color:"..strattr, color)
- token_setmacro("_color-s:"..strattr, string.upper(color))
+ token_setmacro("_color::"..color, strattr, "global")
+ token_setmacro("_color:"..strattr, color, "global")
+ token_setmacro("_color-s:"..strattr, string.upper(color), "global")
end
setattribute(todirect(n), color_attribute, attr)
end
diff --git a/macros/optex/base/others.opm b/macros/optex/base/others.opm
index cde2f02fa1..9926c98fef 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 <2022-05-04>} % preloaded in format
+\_codedecl \uv {Miscenaleous <2023-10-17>} % preloaded in format
\_doc ----------------------------
\`\useOpTeX` and \`\useoptex` are declared as `\relax`.
@@ -125,6 +125,46 @@
\_let \lorem=\lipsum
\_doc -----------------------------
+ Selected macros from \ulink[https://petr.olsak.net/optex/optex-tricks.html]{\OpTeX/ tricks}
+ are registered using \`\_regtrick``<cs-name>`. The <cs-name> is defined
+ as \^`\loadtrick` `<cs-name> <cs-name>`. When a user runs such a registered
+ <cs-name> then \`\loadtrick` `<cs-name>` reads the appropriate code from the
+ file `optex-tricks.opm` and the <cs-name> is redefined. Finally, <cs-name> is run again.\nl
+ The `optex-tricks.opm` file includes blocks started by \^`\_trick` followed
+ by the declared <cs-names> followed by semicolon followed by the code
+ with declarations of <cs-names> itself. The next \`\_trick` does
+ `\endpinput` of the file. The file is read inside temporary `\vbox` with `\globaldefs=1`
+ because it can be read inside horizontal mode and/or inside a group.
+ The `optextrick` name space is used during reading the code from
+ the file. Only registered control sequences are re-defined directly
+ in user name space.\nl
+ You can load a code chunk by \^`\loadtrick` `<cs-name>`. This
+ command doesn't run the `<cs-name>`, only loads the appropriate code. It
+ should be usable if you want to load the code before the fisrt usage of
+ the `<cs-name>`.
+ \_cod -----------------------------
+
+\_def\_regtrick#1{\_ifx#1\_undefined\_def#1{\_loadtrick#1#1}\_else\_badtrick\_fi}
+\_def\_loadtrick#1{\_resetnamespace{optextrick}\_setctable\_optexcatcodes
+ \_savecatcodetable\_tmpcatcodes \_catcodetable\_tmpcatcodes
+ \_long\_def\_loadtrickA ##1\_trick##2#1##3;{##1}%
+ \_wlog{Loading trick macros for \_string#1}%
+ \_setbox0=\_vbox{\_globaldefs=1 \_ea\_loadtrickA \_input {optex-tricks.opm}}%
+ \_restorectable \_endnamespace
+}
+\_def\_trick #1;{\_endinput}
+\_public \loadtrick ;
+
+\_xargs \_regtrick \begfile \createfile \beglua \begLUA \logginglua
+ \sethours \setminutes \setseconds \setweekday \showpglists \runsystem
+ \directoutput \algol \scaleto \scaletof \ttlineref \easylist \keepstyle \fcread
+ \shadedframe \roundframe \cancel \ignoreinspic \keystroke
+ \colortab \crx \crtop \crbot \crmid \longtable \vcent \vbot \tnote \tabnodes \tablebefore
+ \framedblocks \twoblocks \pstart \settabs \import \incrpp \ispageodd
+ \iniseccc \seccc \makeLOF \makeLOT \captionF \captionT \correctvsize ;
+\_sdef{_item:m}{\_loadtrick{\style m}\_cs{_item:m}}
+
+ \_doc -----------------------------
Lua\TeX/ version 1.14 and newer provides `\partokenname` which allows to
specify something different than `\par` at empty lines. We set `\_par`
(see bellow) in \OpTeX/ version 1.04+ and newer. Some macros were rewritten
@@ -198,6 +238,7 @@
\_endcode
+2023-10-17 \_loadtrick introduced.
2022-05-04 \lipsum[<num>]. changed to \lipsum[<num>.] to keep macro expandable.
2022-04-21 syntax \lipsum[<num>]. introduced.
2022-02-16 declaration of @-names moved here from plain-at.opm.
diff --git a/macros/optex/base/parameters.opm b/macros/optex/base/parameters.opm
index c357a4ee8c..f831fa6a2d 100644
--- a/macros/optex/base/parameters.opm
+++ b/macros/optex/base/parameters.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \normalbaselineskip {Parameter settings <2021-04-13>} % preloaded in format
+\_codedecl \normalbaselineskip {Parameter settings <2023-09-19>} % preloaded in format
\_doc -----------------------------
\secc Primitive registers
@@ -57,6 +57,17 @@
\_splittopskip=10pt
\_doc -----------------------------
+ The following two registers were introduced to fix a couple of bugs
+ in the \LuaTeX/ engine. When `\matheqdirmode` is positive short
+ skip detection around display equations will work with right to left
+ typesetting. When `\breakafterdirmode` is set to 1 a glue after a dir
+ node will not be ignored.
+ \_cod -----------------------------
+
+\_matheqdirmode=1
+\_breakafterdirmode=1
+
+ \_doc -----------------------------
\secc Plain \TeX/ registers
Allocate registers that are used just like in plain \TeX/.\nl
\`\smallskipamount`, \`\medskipamount`, \`\bigskipamount`,
@@ -618,6 +629,7 @@ a register then \OpTeX/ macros still work without change.
\_endinput
History:
+2023-09-19 ... \matheqdirmode and \breakafterdirmode set (relevant when RTR typesetting)
2021-04-13 ... \bibpart added
2021-04-07 ... \biboptions added, bug from iso690 fixed
2020-04-04 ... \tabspaces added
diff --git a/macros/optex/base/references.opm b/macros/optex/base/references.opm
index ab5ee34163..cf43bb4049 100644
--- a/macros/optex/base/references.opm
+++ b/macros/optex/base/references.opm
@@ -1,6 +1,6 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \ref {References <2022-01-22>} % preloaded in format
+\_codedecl \ref {References <2023-07-03>} % preloaded in format
\_doc ----------------------------
\`\_Xpage` `{<gpageno>}{<pageno>}` saves the parameter pair into \`\_currpage`.
@@ -66,9 +66,9 @@
are read from `\_pgref:<label>` by \`\_pgrefB``{<gpageno>}{<pageno>}{<given-text>}`.
\nl
\`\_lastreflabel` keeps the value of the last label read by \^`\ref` or \^`\pgref`.
- You can use it for example by definig a macro `\pg` by `\def\pg{\pgref[\_lastreflabel]}`
+ You can use it for example by definig a macro \`\pgr` by `\def\pgr{\pgref[\_lastreflabel]}`
and then you need not repeat the same label in typical situations and you
- can write for instance: `see section \ref[lab] at page \pg.`
+ can write for instance: `see section \ref[lab] at page \pgr.`
\_cod ----------------------------
\_def\_ref[#1]{\_xdef\_lastreflabel{#1}\_isnextchar\_bgroup{\_refA}{\_refA{@}}}
@@ -102,12 +102,14 @@
Default \`\_printlabel` is empty macro (labels are not printed).
The \`\showlabels` redefines it as box with zero dimensions and
with left lapped `[<label>]` in blue 10pt `\tt` font shifted up by 1.7ex.
+ The color of labels is set by \`\_labelcolor` (default is RGB blue).
\_cod -----------------------------
\_def\_printlabel#1{}
+\_def\_labelcolor{\_setrgbcolor{0 0 1}}
\_def\_showlabels {%
- \_def\_printlabel##1{\_vbox to\_zo{\_vss\_llap{\_labelfont[##1]}\_kern1.7ex}}%
- \_fontdef\_labelfont{\_setfontsize{at10pt}\setfontcolor{blue}\_tt}
+ \_def\_printlabel##1{\_vbox to\_zo{\_vss\_llap{\_labelcolor\_labelfont[##1]}\_kern1.7ex}}%
+ \_fontdef\_labelfont{\_setfontsize{at10pt}\_tt}
}
\_public \showlabels ;
@@ -121,6 +123,7 @@ See section \ref[ref-file] for more information about `.ref` file concept.
\_endinput
+2023-07-03 ... obsolete \setfontcolor not used in \showlabels
2022-01-22 ... extended format for \ref, \pgref
2021-04-13 ... \_slideshook introduced (used by \slides)
2020-03-03 ... released
diff --git a/macros/optex/base/table.opm b/macros/optex/base/table.opm
index 562fe6515a..433ad41267 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 <2023-05-19>} % preloaded in format
+\_codedecl \table {Basic macros for OpTeX <2023-06-27>} % preloaded in format
\_doc -----------------------------
The result of the \`\table``{<declaration>}{<data>}` macro is inserted into
@@ -418,7 +418,7 @@
\_long\_def\_frame#1{%
\_hbox{\_vrule\_vtop{\_vbox{\_hrule\_kern\_vvkern
- \_hbox{\_kern\_hhkern\_relax#1\_kern\_hhkern}%
+ \_hbox{\_kern\_hhkern{#1}\_kern\_hhkern}%
}\_kern\_vvkern\_hrule}\_vrule}}
\_public \frame ;
@@ -591,6 +591,7 @@ after the second one.
\_endinput
+2023-06-27 \frame: argument in group
2023-05-19 \_tableparB,C: no strut when \tskip is processed (bug fixed).
2022-12-26 \tabdeclare: use {##} in order to allow a\over b in table items
2022-05-03 \_let\_tablereplstring\_relax removed and {...} encloses whole \_tableB body
diff --git a/macros/optex/base/unimath-macros.opm b/macros/optex/base/unimath-macros.opm
index d4cd9e5540..35842e674d 100644
--- a/macros/optex/base/unimath-macros.opm
+++ b/macros/optex/base/unimath-macros.opm
@@ -1,12 +1,13 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \loadmath {Unicode Math fonts <2023-01-17>} % preloaded in format
+\_codedecl \loadmath {Unicode Math fonts <2023-09-03>} % preloaded in format
\_doc -----------------------------
- \`\loadmath` `{<Unicode-math font>}` loads the given font. It does:
+ \`\loadmath` `<optional-factor> {<Unicode-math font>}` loads the given font. It does:
\begitems
* define \`\_unimathfont` as `<Unicode-math font>`,
* redefine `\normalmath` and `\boldmath` macros to their Unicode counterparts,
+ * save the `<optional-factor>` as scaling factor, see also \^`\_mfactor`,
* load the `\_unimathfont` by `\normalmath`,
* print information about the loaded font on the terminal,
* redefine all encoding dependent setting by `\input unimath-codes.opm`,
@@ -21,16 +22,17 @@
\_def\_noloadmath{\_mathloadingfalse}
\_def\_doloadmath{\_mathloadingtrue}
-\_def\_loadmath#1{%
+\_def\_loadmath#1#{\_loadmathA{#1}}
+\_def\_loadmathA#1#2{%
\_ifmathloading
\_initunifonts
- \_isfont{#1}\_iffalse
- \_opwarning{Math font "#1" not found, skipped...}%
+ \_isfont{#2}\_iffalse
+ \_opwarning{Math font "#2" not found, skipped...}%
\_else
- \_def\_unimathfont{#1}%
+ \_sdef{_mfactor:1}{#1}\_def\_unimathfont{#2}%
\_let\_normalmath = \_normalunimath \_let\_boldmath = \_boldunimath
\_normalmath
- \_wterm {MATH-FONT: "#1" -- unicode math prepared.}%
+ \_wterm {MATH-FONT: "#2" -- unicode math prepared.}%
\_ifx\_ncharrmA\_undefined \_opinput {unimath-codes.opm}\_fi
\_mathloadingfalse
\_fi\_fi}
@@ -133,9 +135,9 @@
\_def\_loadumathfamily{\_afterassignment\_loadumathfamilyA \_chardef\_mfam}
\_def\_loadumathfamilyA #1#2 {\_mfactor
- \_font\_mF \_umathname{#1}{\_textmff \_mparams #2} at\_sizemtext \_textfont \_mfam=\_mF
- \_font\_mF \_umathname{#1}{\_scriptmff \_mparams #2} at\_sizemtext \_scriptfont \_mfam=\_mF
- \_font\_mF \_umathname{#1}{\_sscriptmff\_mparams #2} at\_sizemtext \_scriptscriptfont\_mfam=\_mF
+ \_font\_mF \_umathname{#1}{\_textmff \_mparams #2} at\_sizemtext \_textfont \_mfam=\_mF
+ \_font\_mF \_umathname{#1}{\_scriptmff \_mparams #2} at\_sizemtext \_scriptfont \_mfam=\_mF
+ \_font\_mF \_umathname{#1}{\_sscriptmff\_mparams #2} at\_sizemtext \_scriptscriptfont \_mfam=\_mF
}
\_def\_textmff {ssty=0;mathsize=1;}
\_def\_scriptmff {ssty=1;mathsize=2;}
@@ -237,11 +239,15 @@
\_endcode
-The \^`\loadmath` `{<Unicode-math font>}` macro loads math fonts and
+The \^`\loadmath` `<optional-factor> {<Unicode-math font>}` macro loads the given math font and
redefines all default math-codes using `\input unimath-codes.opm`.
If Unicode-math font is loaded then \^`\_mathloadingfalse`
is set, so the new Unicode-math font isn't loaded until \^`\doloadmath` is used.
+The `<optional-factor>` is scaling factor of loaded font with respect to the
+size of the text font. It can be used if the used text font and loaded math font have
+incompatible ex height. If missing then the scaling factor is 1.
+
\^`\loadboldmath` `{<bold-font>} \to {<normal-font>}` loads bold variant only
if `<normal-font>` was sucessully loaded by the previous `\loadmath`. For example:
@@ -337,6 +343,9 @@ the section~\ref[math-macros].
\_endinput
+2023-09-03 mathsize does work (luaotfload v. 3.36 corrected the bug
+2023-08-28 mathsize doesn't work now
+2023-07-03 \loadmath: optional scaling factor introduced
2023-01-17 \mathchars: \int operators re-implemented
2023-01-15 \_def\_umathrange moved to unimath-codes.opm
2023.01-15 \themathcodeclass etc. introduced
diff --git a/macros/optex/base/usebib.opm b/macros/optex/base/usebib.opm
index ab2f106811..cb38eea7e8 100644
--- a/macros/optex/base/usebib.opm
+++ b/macros/optex/base/usebib.opm
@@ -1,139 +1,285 @@
%% This is part of the OpTeX project, see http://petr.olsak.net/optex
-\_codedecl \MakeReference {Reading bib databases <2022-02-04>} % loaded on demand by \usebib
+\_codedecl \readbibs {Reading bib databases <2023-06-25>} % loaded on demand by \usebib
\_doc -----------------------------
- Loading the `librarian.tex` macro package. See `texdoc librarian`
- for more information about it.
+ First, we implement the scanner of `.bib` files. Unfortunately, the format of
+ these files isn't \TeX/ friendly, so we must to do more work.
+ \`\readbibs` `{<bib-bases>}` reads <bib-bases> files
+ (i.e. the Bib\TeX/ format).
+ \_cod -----------------------------
+
+\_newcount\_aunum
+\_newcount\_NameCount
+\_def\_eaddto#1#2{\_ea\_addto\_ea#1\_ea{#2}}
+
+\_def\_readbibs #1{%
+ \_ifcsname _be:\_bibp*\_endcsname \_def\_citelist{}\_fi % \_citelist will be created
+ \_begingroup
+ \_everyeof{@{}}\_foreach#1,\_do##1,{\_ea\_nextat\_input{##1.bib}}%
+ \_endgroup
+}
+\_public \readbibs ;
- We want to ignore `\errmessage` and we want not to create `\jobname.lbr`
- file.
+ \_doc -----------------------------
+ The \`\_nextat` macro skips the text in the `.bib` file to the next `@`, and starts
+ the \`\_bibentry` macro which reads `@<entry type>{<data>}` from the `.bib` file.
+ Each reference entry is conveted to the \`\_entrydata`
+ macro and then `\_glet \_be:<bib-part>/<label> = \_entrydata` is done.
+ The \^`\_entrydata` includes key-value pairs, as described in the
+ section~\ref[readbibs].
\_cod -----------------------------
-\_def\errmessage#1{}
-\_def\newwrite#1{\_csname lb@restoreat\_endcsname \_endinput}
-\_def\_tmpb{\_catcode`\_=12 \_input librarian \_catcode`\_=11 }\_tmpb
-\_let\errmessage=\_errmessage
-\_let\newwrite=\_newwrite
+\_long\_def\_nextat#1@{\_bgroup\_catcode` =9 \_ea\_egroup\_bibentry}
+\_def\_bibentry #1#{\_ifx^#1^\_else \_afterfi{\_bibentryA{#1}}\_fi}
+\_def\_bibentryA #1#2{\_lowercase{\_def\_entrytype{#1}}%
+ \_ismacro\_entrytype{comment}\_iffalse % comment is ignored
+ \_ismacro\_entrytype{texcode}\_iftrue % TeX code is processed
+ \_endgroup #2\_begingroup \_everyeof{@{}}\_else
+ \_ismacro\_entrytype{string}\_iftrue % string is reported as unsupported
+ \_opwarning{\_string\usebib: @STRING entry isn't supported, try to use @TEXCODE}%
+ \_else
+ \_edef\_entrydata{[@]{\_entrytype}}%
+ {\_bibentryB #2\_fin}% % read a "normal" bib entry
+ \_fi\_fi\_fi
+ \_nextat
+}
+\_def\_bibentryB #1#2,#3\_fin{\_def\_citekey{#1#2}\_def\_bibentryC{\_nextfield #3,\_fin}%
+ \_ifcsname _be:\_bibp*\_endcsname
+ \_bibentryC
+ \_global\_addto\_citelist{\_citeI[#1#2]}
+ \_else
+ \_ea\_ifx \_begincsname _be:\_bibp#1#2\_endcsname \_empty
+ \_bibentryC
+ \_fi\_fi
+}
+\_def\_bibentryF {% finalize entry
+ \_preparebibsorting
+ \_global\_ea\_let \_csname _be:\_bibp\_citekey\_endcsname = \_entrydata
+}
-\_private \BibFile \ReadList \SortList \SortingOrder \NameCount \AbbreviateFirstname
- \CreateField \RetrieveFieldInFor \RetrieveFieldIn \RetrieveField ;
+ \_doc -----------------------------
+ \`\_nextfield` reads next field name and saves it to the \`\_fieldname`
+ and then reads field data and saves it to the \`\_fielddata`.
+ \_cod -----------------------------
+
+\_def\_nextfield #1{\_ifx,#1\_ea\_nextfield % skip commas from previous field
+ \_else \_ifx\_fin#1\_ea\_ea\_ea\_bibentryF % finalize bib entry
+ \_else \_def\_fieldname{#1}\_ea\_ea\_ea\_nextfieldA % first letter of fieldname found
+ \_fi\_fi
+}
+\_def\_nextfieldA #1{% next letters of field name until = is found
+ \_ifx=#1\_afterfi{\_nospacefuturelet\_next\_nextfieldB}%
+ \_else \_addto\_fieldname{#1}%
+ \_ea\_nextfieldA \_fi
+}
+\_def\_nextfieldB {% reading field data
+ \_casesof\_next
+ " {\_nextfieldC}% name = "data",
+ \_bgroup {\_nextfieldD}% name = {data},
+ \_finc {\_nextfieldE}% name = data,
+}
+\_def\_nextfieldC "#1"{\_nextfieldD{#1}}
+\_def\_nextfieldD #1{\_def\_fielddata{#1}\_nextfieldF}
+\_def\_nextfieldE #1,{\_nextfieldD{#1}}
+
+\_def\_nextfieldF{% finalize field
+ \_lowercase\_ea{\_ea\_def\_ea\_fieldname\_ea{\_fieldname}}% case insensitive field name
+ \_ifcsname _fia:\_fieldname\_endcsname \_edef\_fieldname{\_cs{_fia:\_fieldname}}\_fi
+ \_eaddto\_entrydata{\_ea[\_fieldname]}%
+ \_ismacro\_fieldname{author}\_iftrue \_ea\_auscan\_ea{\_fielddata}[author]\_else
+ \_ismacro\_fieldname{editor}\_iftrue \_ea\_auscan\_ea{\_fielddata}[editor]\_else
+ \_eaddto\_entrydata{\_ea{\_fielddata}}\_fi\_fi
+ \_sdef{_fd:\_fieldname\_ea}\_ea{\_fielddata}%
+ \_nextfield
+}
\_doc -----------------------------
- The `\usebib` command.
+ \`\_fieldalias``{<new-name>}{<given-name>}`
+ defines `\_fia:<new_name>` as <given-name>.
\_cod -----------------------------
-\_def\_usebib/#1 (#2) #3 {%
- \_let\_citeI=\_relax \_xdef\_citelist{\_trycs{_ctlst:\_bibp}{}\_trycs{_ctlstB:\_bibp}{}}%
- \_global \_ea\_let \_csname _ctlst:\_bibp\_endcsname =\_write
- \_ifx\_citelist\_empty
- \_opwarning{No cited items. \_noexpand\usebib ignored}%
- \_else
- \_bgroup \_par
- \_emergencystretch=.3\_hsize
- \_def\_optexbibstyle{#2}%
- \_setctable\_optexcatcodes
- \_input bib-#2.opm
- \_the \_bibtexhook
- \_ifcsname _mt:bib.and:\_cs{_lan:\_the\_language}\_endcsname \_else
- \_opwarning{\_string\usebib: No phrases for language
- "\_cs{_lan:\_the\_language}" (using "en")}%
- \_language=0 \_chardef\_documentlanguage=0
- \_fi
- \_def\_tmp##1[*]##2\_relax{\_def\_tmp{##2}}\_ea\_tmp\_citelist[*]\_relax
- \_ifx\_tmp\_empty\_else % there was \nocite[*] used.
- \_setbox0=\_vbox{\_hsize=\_maxdimen \_def\_citelist{}\_adef@{\_readbibentry}%
- \_input #3.bib
- \_ea}\_ea\_def\_ea\_citelist\_ea{\_citelist}%
- \_fi
- \_def\_citeI[##1]{\_csname lb@cite\_endcsname{##1}{\_bibp}{}{}}\_citelist
- \_BibFile{#3}%
- \_if s#1\_SortList{\_bibp}\_fi
- \_ReadList{\_bibp}%
- \_restorectable
- \_egroup
- \_fi
+\_def\_fieldalias#1#2{\_lowercase{\_sxdef{_fia:#1}{#2}}}
+
+ \_doc -----------------------------
+ The \`\_auscan``{<authors/editors-names>}[<field-name>]` reads the specific Bib\TeX/
+ format menitoned in section~\ref[readbibs] and converts them to
+ `{<Lastname>}{<Firstname>}{<Von>}{<Junior>}` for each author/editor. The result
+ includes $4k$ subfields (where $k$ is number of the authors/editors) and
+ it is saved to the `\_entrydata` and the
+ `[authornum]{`$k$`}` or `[editornum]{`$k$`}` is added.
+
+ The \`\_auscanA` macro does the loop over authors separated by `and`.
+ Each single author has its `\_tmpb` macro with `X` and `x`. Each letter
+ corresponds to single word of the name (`X`: begins with uppercase, `x`:
+ begins with lowercase). For example Leonardo Piero da Vinci has `\_tmpb`
+ macro `XXxX.`. If there are commas in after some words, then these commas
+ are in `\_tmpb` macro too, for example da Vinci, Piero Leonardo has its
+ `\_tmpb` macro `xX,XX.`. The number of commas is saved to `\_tmpnum`.
+ The \`\_auscanB` macro does a slight modifications of the `\_tmpb` macro as
+ mentioned in comments. Then the macro
+ \`\_auscanD``<tpmb-pattern>;{<WordA>}{<WordB>}{<WordC>}...` is executed.
+ It saves given words due to the `\_tmpb` pattern to the macros
+ `\_Lastname`, `\_Firstname`, `\_Von`, `\_Junior` in a loop. Finally, the contents of
+ these macros are saved to `\_fiedldata` and then to the `\_entrydata`.
+ \_cod -----------------------------
+
+\_def\_auscan#1[#2]{\_def\_auname{}\_def\_fielddata{}\_def\_tmpb{}\_aunum=0\_tmpnum=0
+ \_auscanA #1 and {}
+ \_eaddto\_entrydata{\_ea{\_fielddata}[#2num]}%
+ \_eaddto\_entrydata{\_ea{\_the\_aunum}}%
+}
+\_def\_auscanA #1 {%
+ \_ifx^#1^\_else
+ \_isequal{#1}{and}\_iftrue
+ \_incr\_aunum
+ \_addto\_tmpb{.}%
+ \_auscanB
+ \_ea\_auscanX \_auname
+ \_def\_auname{}\_def\_tmpb{}\_tmpnum=0
+ \_else
+ \_lowercase{\_isequal{#1}}{#1}\_iftrue \_addto\_tmpb{x}\_else \_addto\_tmpb{X}\_fi
+ \_def\_tmp{#1^}\_isinlist\_tmp{,^}%
+ \_iftrue
+ \_ea\_auscanC\_tmp \_addto\_tmpb{,}\_incr\_tmpnum
+ \_else
+ \_def\_tmp{#1}%
+ \_fi
+ \_eaddto\_auname{\_ea{\_tmp}}%
+ \_fi
+ \_ea\_auscanA
+ \_fi
+}
+\_def\_auscanB{%
+ \_ifcase\_tmpnum % 0 commas: XXX. -> XX:X. ; XxxXX. -> X:xxXX. ; xXX. -> :xXX. ; First:Last
+ \_isinlist\_tmpb{x}\_iffalse \_replstring\_tmpb{X.}{:X.}\_else
+ \_ea\_auscanT\_tmpb;\_iffalse \_replstring\_tmpb{Xx}{X:x}\_fi\_fi
+ \_or % 1 comma: XX,XXX -> XX,,XXX, Junior part is empty
+ \_replstring\_tmpb{,}{,,}\_tmpnum=2
+ \_fi % 2 commas: XX,XX,XXX no changes, generic format: Last, Junior, First
+ \_def\_Firstname{}\_def\_Lastname{}\_def\_Von{}\_def\_Junior{}%
}
-\_def\_readbibentry#1#{\_readbibentryA}
-\_def\_readbibentryA#1{\_readbibentryB#1,,\_relax!.}
-\_def\_readbibentryB#1#2,#3\_relax!.{\_addto\_citelist{\_citeI[#1#2]}}
+\_def\_auscanT #1#2;\_iffalse{\_ifx#1x\_def\_tmpb{:x#2}\_else} % xXX. -> :xXX.
+\_def\_auscanX {\_ea\_auscanD\_tmpb;}
+\_def\_auscanD #1#2;{%
+ \_def\_tmpb{#2}%
+ \_casesof #1
+ . {\_auscanF} % dot is last character, do final job
+ , {\_decr\_tmpnum \_auscanX} % Lastname->Junior or Junior->Firstname
+ : {\_tmpnum=2 \_auscanX} % Firstname->Lastname
+ X {\_auscanE\_Firstname\_Junior\_Lastname} % add data due to the \tmpnum value
+ x {\_auscanE\_Firstname\_Junior\_Von} % Von instead Lastname
+ \_finc {}%
+}
+\_def\_auscanE#1#2#3{\_ifcase\_tmpnum \_ea\_auscanS\_ea#1\_or \_ea\_auscanS\_ea#2\_else
+ \_ea\_auscanS\_ea#3\_fi}
+\_def\_auscanS#1#2{% #1=\Firstname or \Lastname or etc., #2=word to be inserted
+ \_ifx#1\_empty \_def#1{#2}\_else \_addto#1{ #2}\_fi
+ \_auscanX
+}
+\_def\_auscanF{% final work of \auscanX
+ \_eaddto\_fielddata{\_ea{\_Lastname}}\_eaddto\_fielddata{\_ea{\_Firstname}}%
+ \_eaddto\_fielddata{\_ea{\_Von}}\_eaddto\_fielddata{\_ea{\_Junior}}%
+}
+\_def\_auscanC #1,^{\_def\_tmp{#1}} % removing final comma: Word,^ -> Word
\_doc -----------------------------
- Corrections in librarian macros.
+ The \^`\_citelist` includes \`\_citeI``[<label>]`
+ commands. The \^`\usebib` macro runs this lists in order to print references.
+ Each \^`\_citeI``[<label>]` prints single bib entry given by the <label>.
+ It opens a group, sets macros `\_fd:<field-name>` to `<field-data>` and runs
+ \^`\_printentry`. Finally, it closes \TeX/ group,
+ so all macros `\_fd:<field-name>` have their initial (undefined) value.\nl
+ The \`\_getfield``[<field-name>]\macro` does `\def\macro{<field-data>}`.
+ If the field isn't declared then the `\macro` is empty.
\_cod -----------------------------
-\_tmpnum=\_catcode`\@ \_catcode`\@=11
-\_def\lb@checkmissingentries#1,{% we needn't \errmessage here, only \opmacwarning
- \_def\lb@temp{#1}%
- \_unless\_ifx\lb@temp\lb@eoe
- \lb@ifcs{#1}{fields}%
- {}%
- {\_opwarning{\_string\usebib: entry [#1] isn't found in .bib}}%
- \_ea\lb@checkmissingentries
- \_fi
+\_def\_citeI[#1]{%
+ \_begingroup
+ \_ea\_ifx \_begincsname _be:\_bibp#1\_endcsname \_empty
+ \_opwarning{\_string\usebib: entry [#1] isn't found in .bib}%
+ \_global\_slet{_bes:#1}{_relax}%
+ \_else
+ \_ea\_ea\_ea\_foreach \_csname _be:\_bibp#1\_endcsname \_do[##1]##2{\_sdef{_fd:##1}{##2}}%
+ \_def\_entrykey{#1}%
+ \_printentry
+ \_fi
+ \_endgroup
}
-\_def\lb@readentry#1#2#3,{% space before key have to be ingnored
- \_def\lb@temp{#2#3}% we need case sensitive keys
- \_def\lb@next{\_ea\lb@gotoat\lb@gobbletoeoe}%
- \lb@ifcs\lb@temp{requested}%
- {\_let\lb@entrykey\lb@temp
- \lb@ifcs\lb@entrykey{fields}{}%
- {\lb@defcs\lb@entrykey{fields}{}%
- \_lowercase{\lb@addfield{entrytype}{#1}}%
- \_let\lb@next\lb@analyzeentry}}{}%
- \lb@next
+\_def\_getfield[#1]#2{%
+ \_ifcsname _fd:#1\_endcsname
+ \_ea\_ea\_ea \_def \_ea\_ea\_ea #2\_ea\_ea\_ea {\_csname _fd:#1\_endcsname}%
+ \_else \_def#2{}%
+ \_fi
}
-\_let\lb@compareA=\lb@compare
-\_let\lb@preparesortA=\lb@preparesort
-\_def\lb@compare#1\lb@eoe#2\lb@eoe{% SpecialSort:
- \_ifx\lb@sorttype\lb@namestring
- \_ifx\_sortfield\_undefined \lb@compareA#1\lb@eoe#2\lb@eoe
- \_else
- \_ea\_RetrieveFieldInFor\_ea{\_sortfield}\lb@entrykey\lb@temp
- \_ifx\lb@temp\_empty \_toks1={#1\lb@eoe}\_else \_toks1=\_ea{\lb@temp\lb@eoe}\_fi
- \_ea\_RetrieveFieldInFor\_ea{\_sortfield}\lb@currententry\lb@temp
- \_ifx\lb@temp\_empty \_toks2={#2\lb@eoe}\_else \_toks2=\_ea{\lb@temp\lb@eoe}\_fi
- \_edef\lb@temp{\_noexpand\lb@compareA\_space\_the\_toks1 \_space\_the\_toks2}\lb@temp
- \_fi
- \_else \lb@compareA#1\lb@eoe#2\lb@eoe \_fi
+
+ \_doc -----------------------------
+ \`\_preparebibsorting` is called repeatedly for each bib entry when its reading from
+ `.bib` file is finished. Its main goal is to do
+ `\gdef\_bes:<citekey> {\;<sorting-rule>^^^<citekey>}`.
+ Note that the part of the control sequence name after `^^^` is ignored during sorting.
+ The default \^`\_preparebibsorting`
+ macro creates <sorting-rule> in the form: <Lastnames> <Firstnames> <Von>
+ <Junior> of the first author followed by <year> from `year` field.\nl
+ \`\_dobibsorting``\_citelist` sorts the \^`\_citelist` and runs it.
+ \_cod -----------------------------
+
+\_def\_preparebibsorting{%
+ \_getfield[sortedby]\_sortedby
+ \_ifx\_sortedby\_empty % explicitly given [sortedby] field has precedence
+ \_def\_sortedby{}%
+ \_getfield[author]\_tmp % sorting by author firstly
+ \_ifx\_tmp\_empty \_else \_ea\_preparebibsortingA\_tmp \_fin \_fi
+ \_getfield[year]\_tmp % soering by year secondly
+ \_ifx\_tmp\_empty \_else \_eaddto\_sortedby{\_tmp}\_fi
+ \_edef\_sortedby{\_sortedby}% we need to run macros aka \"e etc.
+ \_edef\_sortedby{\_ea\_removeoutbraces\_sortedby {\_fin}}% remove braces
+ \_fi
+ \_sxdef{_bes:\_citekey\_ea}\_ea{\_csname;\_detokenize\_ea{\_sortedby}^^^\_citekey\_endcsname}%
+}
+\_def\_preparebibsortingA#1#2#3#4#5\_fin {% names of the first author used by sorting:
+ \_def\_sortedby{#1 }% Lastname
+ \_ifx^#2^\_else \_addto\_sortedby{#2 }\_fi % Firstname
+ \_ifx^#3^\_else \_addto\_sortedby{#3 }\_fi % Von
+ \_ifx^#4^\_else \_addto\_sortedby{#4 }\_fi % Junior
+}
+\_def\_dobibsorting{%
+ {\_def\_citeI[##1]{\_ea\_citeIs\_csname _bes:##1\_endcsname{##1}}%
+ \_edef\_citelist{\_ea}\_citelist % converting \_citelist
+ \_dosorting\_citelist \_ea}%
}
-\_def\lb@preparesort#1#2\lb@eoe{%
- \_if#1-%
- \_def\lb@sorttype{#2}%
- \_else
- \_def\lb@sorttype{#1#2}%
- \_fi
- \lb@preparesortA#1#2\lb@eoe
+\_def\_citeIs#1#2{\_eaddto\_citelist{#1}%
+ \_ea\_gdef#1{\_citeI[#2]\_ea\_glet#1=\_undefined \_glet#1=\_undefined}%
}
-\_def\_SpecialSort#1{\_def\_sortfield{#1}}
-\_def\WriteImmediateInfo#1{} % the existence of .lbr file bocks new reading of .bib
-\_catcode`\@=\_tmpnum
\_doc -----------------------------
- Main action per each entry.
+ The \`\_printentry` macro prints bibliographic reference entry.
+ It prints <bibnum> or <bimark> (including hyperlinks) and they are
+ followed by printing the entry data. The format is given by the \^`\_printbib`
+ macro and by `\_print:<entrytype>` declared in the bib-style file.
\_cod -----------------------------
-\_def\MakeReference{\_par \_bibskip
- \_bibgl\_advance\_bibnum by1
+\_def\_printentry {\_par \_bibskip
+ \_bibgl\_incr\_bibnum
\_isdefined{_bim:\_bibp\_the\_bibnum}\_iftrue
\_edef\_tmpb{\_csname _bim:\_bibp\_the\_bibnum\_endcsname}%
\_bibmark=\_ea{\_tmpb}%
\_else \_bibmark={}\_fi
- \_edef\_tmpb{\EntryKey}%
- \_noindent \_dbib\EntryKey
+ \_edef\_tmpb{\_entrykey}%
+ \_noindent \_dbib\_entrykey
\_printbib
{%
- \_RetrieveFieldIn{entrytype}\_entrytype
+ \_getfield[@]\_entrytype
\_csname _print:BEGIN\_endcsname
\_isdefined{_print:\_entrytype}\_iftrue
\_csname _print:\_entrytype\_endcsname
\_else
\_ifx\_entrytype\_empty \_else
- \_opwarning{Entrytype @\_entrytype\_space from [\EntryKey] undefined}%
+ \_opwarning{Entrytype @\_entrytype\_space from [\_entrykey] undefined}%
\_csname _print:misc\_endcsname
\_fi\_fi
\_csname _print:END\_endcsname
- \_wbib \EntryKey {\_the\_bibnum}{\_the\_bibmark}%
+ \_wbib \_entrykey {\_the\_bibnum}{\_the\_bibmark}%
}\_par
}
@@ -147,13 +293,13 @@
\_def\_bibfieldname{#2#3}%
\_if!#2\_relax
\_def\_bibfieldname{#3}%
- \_RetrieveFieldIn{#3}\_bibfield
+ \_getfield[#3]\_bibfield
+ \_getfield[#3num]\_namecount % total persons in the author/editor fields
\_ifx\_bibfield\_empty\_else
- \_RetrieveFieldIn{#3number}\_namecount
- \_def\_bibfield{\_csname _Read#3\_ea\_endcsname \_csname _pp:#3\_endcsname}%
+ \_def\_bibfield{\_loopauthors{#3}}% read author/edior field in a loop
\_fi
\_else
- \_RetrieveFieldIn{#2#3}\_bibfield
+ \_getfield[#2#3]\_bibfield
\_fi
\_if^#1^%
\_ifx\_bibfield\_empty \_ea\_ea\_ea \_doemptyfield
@@ -163,36 +309,119 @@
}
\_def\_dofullfield#1#2{\_def\_dofield##1{#1}\_ea\_dofield\_ea{\_bibfield}}
\_def\_doemptyfield#1#2{\_def\_dofield##1{#2}\_ea\_dofield\_ea{\_bibfield}}
-\_let\_Readauthor=\ReadAuthor \_let\_Readeditor=\ReadEditor
-\_def\_bprintaA #1#2{\_ifx\_bibfield\_empty #2\_else\_bprintaB #1**\_eee\_fi}
-\_def\_bprintaB #1*#2*#3\_eee{\_if^#3^#1\_else\_ea\_bprintaC\_ea{\_bibfield}{#1}{#2}\_fi}
+\_def\_bprintaA #1#2{\_ifx\_bibfield\_empty #2\_else\_bprintaB #1**\_fin\_fi}
+\_def\_bprintaB #1*#2*#3\_fin{\_ifx^#3^#1\_else\_ea\_bprintaC\_ea{\_bibfield}{#1}{#2}\_fi}
\_def\_bprintaC #1#2#3{#2#1#3}
\_def\_bprintc#1#2{\_bprintcA#1#2**\_relax}
\_def\_bprintcA#1#2*#3*#4\_relax{\_ifx#1\_empty \_else \_if^#4^#2\_else#2#1#3\_fi\_fi}
\_def\_bprintv [#1]#2#3{\_def\_tmpa{#2}\_def\_tmpb{#3}\_bprintvA #1,,}
\_def\_bprintvA #1,{%
\_if^#1^\_tmpb\_else
- \_RetrieveFieldIn{#1}\_tmp
+ \_getfield[#1]\_tmp
\_ifx \_tmp\_empty
\_else \_tmpa \_def\_tmpb{}\_def\_tmpa{}%
\_fi
\_ea \_bprintvA
\_fi
}
-\_sdef{_pp:author}{\_letNames\_authorname}
-\_sdef{_pp:editor}{\_letNames\_editorname}
-\_def\_letNames{\_let\_Firstname=\Firstname \_let\_Lastname=\Lastname
- \_let\_Von=\Von \_let\_Junior=\Junior
-}
\_doc -----------------------------
- Various macros + multilingual. Note that \`\_nobibwarnlist` is used in
- \`\_bibwarning` and it is set by \^`\nobibwarning` macro.
+ \`\_loopauthors``{<field-name>}` does a loop over all authors/editors in
+ the `author` or `editor` field. The \`\_namecount`
+ (total nuber of authors/editors) was defined in
+ \^`\_bprintb`. Then for each author/edtor it do:
+ \begitems
+ * Set \`\_NameCount` to the position number of the currently processed author/editor.
+ * Define \`\_Lastname`, \`\_Firstname`, \`\_Junior`, \`\_Von`, \`\_After` macros.
+ * Run \^`\_authorname` or \^`\_editorname` macro (defined in the bib style file).
+ \enditems
+ \_cod -----------------------------
+
+\_def\_loopauthors #1{%
+ \_NameCount=0
+ \_ea\_ea\_ea\_foreach\_csname _fd:#1\_endcsname \_do ##1##2##3##4{%
+ \_advance\_NameCount by1
+ \_def\_Lastname{##1}\_def\_Firstname{##2}\_def\_Von{##3}\_def\_Junior{##4}%
+ \_csname _#1ini\_endcsname \_csname _#1name\_endcsname
+}}
+\_def\_authorini{} % ready for \_AbbreviateFirstname or similar...
+\_def\_editorini{}
+
+ \_doc -----------------------------
+ \`\_bibwarning` can be used if the manatory field is missing.
+ Note that \`\_nobibwarnlist` is used here, it is set by \^`\nobibwarning` macro.
\_cod -----------------------------
\_def\_bibwarning{%
- \_ea\_isinlist \_ea\_nobibwarnlist\_ea{\_ea,\EntryKey,}\_iffalse
- \_opwarning{Missing field "\_bibfieldname" in [\EntryKey]}\_fi}
+ \_ea\_isinlist \_ea\_nobibwarnlist\_ea{\_ea,\_entrykey,}\_iffalse
+ \_opwarning{Missing field "\_bibfieldname" in [\_entrykey]}\_fi}
+
+ \_doc -----------------------------
+ \`\_AbbreviateFirstname`, \`\_RetrieveFieldIn`, \`\_RetrieveField` are here only for
+ backward comaptibility with previous macros based on the librarian package.
+ The \`\_CreateField`, \`\_SortingOrder`, and \`\_SpecialSort` are dummy
+ macros because the sorting is implemented by a slightly different way
+ than in librarian package.
+ \_cod -----------------------------
+
+\_def\_AbbreviateFirstname{\_addto\_authorini{\_abbrevnames\_Firstname}}
+\_def\_abbrevnames#1{% Karolina Pondelickova-Maslova -> K. P.-M.
+ \_edef#1{\_ea\_foreach #1 \_do ##1##2 {##1.%
+ \_foreach ##2-{}\_do ####1-####2{\_ifx^####2^\_else-####2.\_fi} }^%
+ }\_replstring#1{ ^}{}%
+}
+\_def\_RetrieveFieldIn#1{\_getfield[#1]}
+\_def\_RetrieveField#1{\_trycs{_fd:#1}{}}
+\_def\_CreateField#1{}
+\_def\_SortingOrder#1#2{}
+\_def\_SpecialSort#1{}
+
+ \_doc -----------------------------
+ The \^`\usebib` command is defined as `\input{usebib.opm}\_usebib` in the
+ format. So, the command is re-defined here and it is run again with the new
+ meaning.\nl
+ The \^`\usebib` macro defined here reads `\_ctlst:<bibpart>/` and `\_ctlstB:<bibpart>/`
+ (they include a list of `\_citeI[<label>]`) and merges them to a single \`\_citelist`.
+ The `\_be:<bibpart>/<label>` is set to empty for each member of the `\_citelist`.
+ Then the style file is read in a group,
+ the \^`\readbibs` macro reads given `.bib` files and resulting `\_citelist`
+ is processed: i.e.\ the macros \^`\_citeI` print desired entries.
+ \_cod -----------------------------
+
+\_def\_usebib/#1 (#2) #3 {%
+ \_ifcsname _ctlst:\_bibp\_endcsname
+ \_slet{_citelist}{_ctlst:\_bibp}\_else \_def\_citelist{}\_fi
+ \_ea \_foreach\_citelist \_do ##1[##2]{\_sdef{_be:\_bibp##2}{}}%
+ \_ifcsname _ctlstB:\_bibp\_endcsname
+ \_ea\_ea\_ea\_foreach \_csname _ctlstB:\_bibp\_endcsname \_do ##1[##2]{%
+ \_ifcsname _be:\_bibp##2\_endcsname
+ \_else \_addto\_citelist{\_citeI[##2]}\_sdef{_be:\_bibp##2}{}%
+ \_fi
+ }%
+ \_fi
+ \_global \_ea\_let \_csname _ctlst:\_bibp\_endcsname =\_write
+ \_ifx\_citelist\_empty
+ \_opwarning{No cited items. \_noexpand\usebib ignored}%
+ \_else
+ \_bgroup
+ \_par
+ \_emergencystretch=.3\_hsize
+ \_def\_optexbibstyle{#2}%
+ \_setctable\_optexcatcodes
+ \_input bib-#2.opm
+ \_the \_bibtexhook
+ \_ifcsname _mt:bib.and:\_cs{_lan:\_the\_language}\_endcsname \_else
+ \_opwarning{\_string\usebib: No phrases for language
+ "\_cs{_lan:\_the\_language}" (using "en")}%
+ \_language=0 \_chardef\_documentlanguage=0
+ \_fi
+ \_ifx#1c\_def\_preparebibsorting{}\_def\_dobibsorting{}\_fi
+ \_readbibs {#3}%
+ \_dobibsorting\_citelist
+ \_restorectable
+ \_egroup
+ \_fi
+}
\_endcode
@@ -201,7 +430,7 @@
The file `usebib.opm` implements the command
\~`\usebib/<sorttype> (<style>) <bibfiles>`
where `<sorttype>` is one letter `c` (references ordered by citation order in
-the text) or `s` (references ordered by key in the style file),
+the text) or `s` (references sorted usually by authors and years),
`<style>` is the part of the name `bib-<style>.opm` of the style file
and `<bibfiles>` are one or more `.bib` file names without suffix separated by
comma without space. Example:
@@ -209,11 +438,10 @@ comma without space. Example:
\begtt
\usebib/s (simple) mybase,yourbase
\endtt
-
This command reads the `<bibfiles>` directly and creates the list of
bibliographic references (only those declared by \~`\cite[]` or
-\~`\nocite[]` in the text). The formatting of such references is defined in the style
-file.
+\~`\nocite[]` in the document). The formatting of such references is defined in
+the style~file.
The principle \"first entry wins" is used. Suppose `\usebib/s (simple) local,global`.
If an entry with the same label is declared in `local.bib` and in
@@ -231,6 +459,7 @@ Old `.bib` files may use the obscure notation for accents like `{\"o}`.
Recommendation: convert such old files to Unicode encoding. If you are
unable to do this then you can set \^`\bibtexhook={`\^`\oldaccents}`.
+
\secc Notes for bib-style writers
The `.bib` files include records in the format:
@@ -244,7 +473,10 @@ The `.bib` files include records in the format:
\endtt
%
see the file `demo/op-biblist.bib` for a real example. The <entry-types> and
-<field-names> are case insensitive.
+<field-names> are case insensitive. More field-names can behave equally if the
+\^`\_fieldalias``{<new-field-name>}{<given-field-name>}` is used in a style
+file. If a <new-field-name> is declared by this command and it is used in the `.bib`
+file then the effect is the same as if it was used the <given-field-name>.
Ancient Bib\TeX/ has read such files and has generated files appropriate for
reading by \LaTeX. It has worked with a set of <entry-types>, see the www
@@ -277,12 +509,12 @@ macros for a more comfortable setting of printing rules:
* The part <if not defined> can include
the \^`\_bibwarning` command if the <field-name> is mandatory.
* \^`\_bprintb` `[<field-name>] {<if defined>} {<if not defined>}`. The same as
- `\_bprinta`, but the `##1` parameter is used instead `*`. Differences: `##1`
+ \^`\_bprinta`, but the `##1` parameter is used instead `*`. Differences: `##1`
parameter can be used more than once and can be enclosed in nested
braces. The `*` parameter can be used at most once and cannot be enclosed
- in braces. Warning: if the `\_bprintb` commands are nested (`\_bprintb` in
- `\_bprintb`), then you need to write the `####1` parameter for internal `\_bprintb`.
- But if `\_bprinta` commands are nested then the parameter is not duplicated.
+ in braces. Warning: if the \^`\_bprintb` commands are nested (`\_bprintb` in
+ \^`\_bprintb`), then you need to write the `####1` parameter for internal `\_bprintb`.
+ But if \^`\_bprinta` commands are nested then the parameter is not duplicated.
* \^`\_bprintc` `\macro {<if non-empty>}`. The <if non-empty> part is executed if
`\macro` is non-empty. The `*` parameter can be used, it is replaced by
the `\macro`.
@@ -317,17 +549,17 @@ in order to declare the format of printing each individual name.
The following control sequences can be used in these macros:
\begitems
-* `\_NameCount`: the number of the currently processed author in the list
-* `\_namecont`: the total number of the authors in the list
-* `\_Lastname`, `\_Firstname`, `\_Von`, `\_Junior`: the parts of the name.
+* \^`\_NameCount`: the number of the currently processed author in the list
+* \^`\_namecount`: the total number of the authors in the list
+* \^`\_Lastname`, \^`\_Firstname`, \^`\_Von`, \^`\_Junior`: the parts of the name.
\enditems
-The whole style file is read in the group during the `\usebib` command is executed
+The whole style file is read in the group during the \^`\usebib` command is executed
before typesetting the reference list. Each definition or setting is local
here.
The auto-generated phrases (dependent on current language) can be used in
-bib-style files by `\_mtext{bib.<identifier>}`, where <ident> is an identifier of
+bib-style files by `\_mtext{bib.<identifier>}`, where <identifier> is an identifier of
the phrase and the phrase itself is defined by
`\_sdef{_mt:bib.<identifier>:<language>}{<phrase>}`. See section~\ref[langphrases]
for more detail. Phrases for <identifiers>:
@@ -335,24 +567,14 @@ and, etal, edition, citedate, volume, number, prepages, postpages, editor,
editors, available, availablealso, bachthesis, masthesis, phdthesis
are defined already, see the end of section~\ref[langphrases].
-If you are using non-standard field-names in .bib database and bib-style,
-you have to declare them by `\_CreateField {<fieldname>}`.
-
-You can declare `\_SortingOrder` in the manner documented by librarian package.
-
-User or author of the bib-style can create the hidden field which has a
-precedence while sorting names. Example:
-
-\begtt
-\CreateField {sortedby}
-\SpecialSort {sortedby}
-\endtt
+The `sortedby` field is declared by \~`\readbibs` as a special field where
+sorting phrase can be specified. If it is present then it has precedence
+before default sorting phrase generated by \~`\_preparebibsorting` from the
+lastname, firstnames of the first author and from the year.
Suppose that the .bib file includes:
\begtt
-...
author = "Jan Chadima",
sortedby = "Hzzadima Jan",
-...
\endtt
Now, this author is sorted between H and I, because the Ch digraph in this
name has to be sorted by this rule.
@@ -361,37 +583,91 @@ If you need (for example) to place the auto-citations before other citations,
then you can mark your entries in `.bib` file by `sortedby = "@"`, because this
character is sorted before `A`.
+If you want to declare a different sorting rule, you can re-define the
+\^`\_preparebibsorting` macro. The example is in the
+\ulink[http://petr.olsak.net/optex/optex-tricks.html\#reverseyear]{\OpTeX/ trick 0113}.
+
+\secc[readbibs] Direct reading of `.bib` files
+
+\^`\readbibs` `{<bib-bases>}` is internally used (by \^`\usebib`)
+for reading `.bib` databases in Bib\TeX/ format. The <bib-bases> is
+comma separated list of file names (without `.bib` extension, without
+spaces). These files are read and \^`\readbibs` defines macros
+`\_be:<bibpart>/<label>`, where <label> is the label of the reference record.
+These macros include key-value pairs `[<field name>]{<field data>}`.
+The first pair is `[@]{<entry type>}`.
+For example, if we have in the `.bib` file:
+\begtt
+@Book { tbn,
+ author = "Petr Olšák",
+ TITle = {\TeX{}book naruby},
+ publisher = "Konvoj",
+ year = 2001,
+}
+\endtt
+and the \^`\bibpart` is empty (default value)
+then the `\_be:/tbn` macro is defined with the content:
+\begtt
+[@]{BOOK}[author]{{Olšák}{Petr}{}{}}[authornum]{1}[title]{\TeX{}book naruby}%
+[publisher]{Konvoj}[year]{2001}
+\endtt
+If you do `\slet{tmp}{_be:/tbn}` then you can print the data (for example) by:
+\begtt
+\ea\foreach \tmp \do [#1]#2{\wterm{field-name: "#1", data: "#2"}}
+\endtt
+or you can do `\ea\foreach \tmp \do [#1]#2{\sdef{bib-field:#1}{#2}}` to enable
+direct acces to the scanned data.
+
+Note that entry type and field names are converted lower-case by the `\readbibs` macro.
+
+There are two special entry types: `@COMMENT{<ignored text>}` and
+`@TEXCODE{<processed text>}`. The <ignored text> is ignored, the
+<processed text> is executed by \TeX/. The definitions of macros used in other
+entries in data of fields can be here. If the `\usebib` is used then
+the <processed text> is executed inside a
+\TeX/ group, so the assignment is locally valid only during creating the
+reference list. The BiB\TeX/'s `@STRING{}` isn't supported. All others entry
+types are interpreted as a {\em reference entry} and they are interpreted as
+described above. An optional balanced text between entries in `.bib` files
+is ignored.
+
+If the macro `\_be:<bibpart>/*` is defined then the \^`\readbibs` macro reads
+all entries from `.bib` files and creates \~`\_citelist`. If the
+`\_be:<bibpart>/*` is undefined then
+the \^`\readbibs` macro reads only entries with <label> where
+`\_be:<bibpart>/<label>` is set to the empty macro. After reading, the
+macros `\_be:<bibpart>/<label>` are globally re-defined as described above.
+
+The \^`\readbibs` macro doesn't convert fields data, but there are two exceptions:
+author and editor fields. These fields have very specific format with
+various alternatives, see \url{https://nwalsh.com/tex/texhelp/bibtx-23.html}.
+Shortly speaking, more authors are divided by the `and` keyword and names of a single
+author must be separated to four subfields: <Lastnames>, <Firstnames>, <Von>,
+<Junior>. Only the <Lastnames> subfield must be nonempty. The input can look like
+\begtt
+Leonardo Piero da Vinci
+or
+da Vinci, Leonardo Piero
+\endtt
+and both these variants are converted to `{Vinci}{Leonardo Piero}{da}{}`.
+The <Von> part is rekognized as a word with only lowercase letters. In
+general, the name can be written without commas: <Firstnames> <Von>
+<Lastnames> or with single comma: <Von> <Lastnames>, <Firstnames> or with two
+commas: <Von> <Lastnames>, <Junior>, <Firstnames> and all these variants are
+converted to the quaternion `{<Lastnames>}{<Firstnames>}{<Von>}{<Junior>}`
+by the \^`\readbibs` macro.
+If there are more than single author, then each author is saved in four
+subfields side by side, so you have 4 or 8 or 12 etc.\ subfildeds in the
+author/editor data field. You can read them by
+`\foreach <author-data>\do #1#2#3#4{...}`.
+
\_endinput
History:
--------
-2022-02-04 reading tail of languages.opm removed
-2021-04-30 \RetrieveField declared as private, bug fixed.
-2021-04-13 \bibpart implemented
-2021-04-13 \_bibgl introduced (used by \slides)
-2021-03-12 \_citelistB added before first test.
-2021-02-15 \_expandafter -> \_ea
-Apr. 2014: released in OPmac
-Jan. 2016: "first entry wins" implemented
-Apr. 2016: \readentry -> \readbibentry, \usebib->\MakeReference
-Feb. 2018: \input librarian does not create \jobname.lbr
-
-% Source:
-
-% opmac-bib
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-% Petr Olsak, version Feb. 2018 (beta)
-
-% This is module for OPmac macros, see http://petr.olsak.net/opmac.html
-% The command:
-% \usebib/<sorttype> (<style>) (bibfiles>
-% for direct reading .bib files by OPmac macros (without bibTeX) is implemented here.
-% The implementation depends on librarian.tex package by Paul Isambert.
-% Use:
-% \input opmac \input opmac-bib
-% or simply:
-% \input opmac-bib
-% before using the command \usebib.
-
-%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end
-
+2023-06-25: \_fieldalias introduced
+2023-06-07: bug fix (\_namecount declaration)
+2023-06-06: \_slet{_bes:#1}{_relax}: bugfix when label not found and sorting
+2023-06-05: @TEXCODE introduced + more consistent doc
+2023-06-02: macros re-implemeted, librarian package no more needed.
+2018 - 2023-06-01 usebib.opm based on librarian package, like in OPmac.