VERSION=1.1
ARCHIVE=ucwmac-$(VERSION).tar.gz
-all: test.pdf test-labels.pdf
+all: test.pdf test-labels.pdf test-ref.pdf
-%.dvi: %.tex
- csplain $<
+MACROS=$(wildcard ucw*.tex)
-%.ps: %.dvi
- dvips -D600 -o $@ -t a4 $<
+ifdef USE_LUATEX
-%.pdf: %.tex
- pdfcsplain $<
+LUATEX?=luatex
+export TEXINPUTS=.//:
+export LUAINPUTS=.//:
+
+%.pdf: %.tex $(MACROS) ucw-luacsplain.fmt
+ $(LUATEX) -file-line-error -fmt ucw-luacsplain $<
+ $(LUATEX) -file-line-error -fmt ucw-luacsplain $<
+
+%.fmt: %.ini
+ $(LUATEX) -file-line-error -jobname $* -ini $<
+
+.SECONDARY: ucw-luacsplain.fmt
+
+else ifdef USE_DVI
+
+%.dvi: %.tex $(MACROS)
+ csplain -file-line-error $<
+ csplain -file-line-error $<
+
+%.pdf: %.dvi
+ dvipdfm -r 600 -o $@ -p a4 $<
+
+else
+
+%.pdf: %.tex $(MACROS)
+ pdfcsplain -file-line-error $<
+ pdfcsplain -file-line-error $<
+
+endif
clean:
- rm -f *~ *.log *.dvi *.ps *.pdf *.aux
+ rm -f *~ *.log *.dvi *.ps *.pdf *.aux *.fmt
release:
git tag v$(VERSION)
-\input ucwmac.tex
-\input ucw-labels.tex
+\input ucwmac2.tex
+\ucwmodule{labels}
\setuplabels{3}{7}
\labelrulestrue
--- /dev/null
+\input ucwmac2.tex
+\ucwmodule{ofs}
+\ucwmodule{ref}
+\ucwmodule{pdfmeta}
+
+% \clickablefalse
+
+\pdfmetainfo{Author}{A. U. Thor}
+\pdfmetainfo{Title}{TeX Caput Regni}
+
+\newcount\chapcount
+\chapcount=0
+\optdef\chapter#1{
+ \vfill\eject
+ \advance\chapcount by 1
+ \addid{chap}{\the\chapcount}
+ \pdfmetaoutline{\the\chapcount}{\currentid}{#1}
+ \leftline{\the\chapcount. #1}
+ \medskip
+}
+
+\def\chapref{\ref{chap}}
+
+\pageid{pri}
+
+\chapter[pri]{Caput prima}
+
+\chapter[sec]{Caput secunda}
+
+\url{http://pruvodce.ucw.cz/errata%21.html}
+
+\linkurl{http://pruvodce.ucw.cz/}{See the web page.}
+
+\chapter[ter]{Caput tertia}
+
+See also chapter~\chapref{pri} at page \ref{page}{pri}.
+
+Hard link to \linkpage{1}{page~1}.
+
+\bye
-\input ucwmac.tex
-\input ucw-ofs.tex
-\input ucw-verb.tex
+\input ucwmac2.tex
+\ucwmodule{ofs}
+\ucwmodule{verb}
+\ucwmodule{algo}
\showfonts
\noindent An~itemized list:
+\list{(g)}
+\:primo
+\:secundo
+\:tertio
+\liststyle{(a)}
+\:quarto
+\liststyle{o}
+\:quinto
+\endlist
+
+\bigskip
+\noindent Backward-compatible lists:
+
\itemize\ibull
-\:It is an important and popular fact that things are not always what
+\:It is an {\I important and popular fact} that things are not always what
they seem. For instance, on the planet Earth, man had always assumed
that he was more intelligent than dolphins because he had achieved so
-much -- the wheel, New York, wars and so on -- whilst all the dolphins
+much -- the wheel, {\colorlocal\rgb{1 0 0}New York}, wars and so on -- whilst all the dolphins
had ever done was muck about in the water having a good time. But
-conversely, the dolphins had always believed that they were far more
+conversely, the \colorpush\rgb{0 0 1}dolphins\colorpop{} had always believed that they were far more
intelligent than man -- for precisely the same reasons.
\:Curiously enough, the dolphins had long known of the impending
destruction of the of the planet Earth and had made many attempts to
{\csc Caps And Small Caps}
-\loadmathfam \ttfam [/cmtt\fotenc]%
${\tt x}\in\fam\bbfam R$
The set{\settextsize{11}text}size macro does not strew spaces.
{\tt Typewriter {\it italic} {\sl slanted.}}
+\hd{Algorithms}
+
+\algo{Factorial}\algalias{calculate a~factorial}
+\algin A~non-negative integer~$n$
+\:If $n\ge 1$: \cmt{Test if something}
+\::Return $n$
+\:Else:
+\::Return $n \cdot \alg{Factorial}(n-1)$
+\algout The factorial of~$n$
+\endalgo
+
\bye
--- /dev/null
+% The UCW Macro Collection: Typesetting of algorithms
+% Written by Martin Mares <mj@ucw.cz> in 2018 and placed into public domain
+% -------------------------------------------------------------------------
+
+\ucwdefmodule{algo}
+
+% \algo{name of the algorithm}\algalias{a longer name}
+% \algin input description
+% \:step
+% \:step \cmt{comment}
+% \::[identifier]nested step
+% \:::yet more nested step
+% \algout output description
+% \endalgo
+
+% Localized strings
+\localedef{0}{alg:alg}{Algorithm}
+\localedef{0}{alg:proc}{Procedure}
+\localedef{0}{alg:in}{Input}
+\localedef{0}{alg:out}{Output}
+
+% Item indent
+\newdimen\algoindent
+\algoindent=2em
+
+% Extra indent for nested items
+\newdimen\algonestindent
+\algonestindent=2em
+
+% Width of item label
+\newdimen\algolabelwidth
+\algolabelwidth=0.5em
+
+% Set up spacing (customizable)
+\def\algospacing{
+ \itemnarrow=\itemindent
+ \interitemskip=1pt
+ \preitemizeskip=\bigskipamount
+ \postitemizeskip=\dimexpr \bigskipamount - \parskip \relax
+}
+
+% Set up paragraph mode for a single step of the algorithm (customizable)
+\def\algopar{
+ \par
+ \parindent=\algoindent
+ \hangindent=\algoindent
+ \advance\hangindent by \algolabelwidth
+ \hangafter=1
+ \leavevmode
+}
+
+% Typeset step label (customizable)
+\def\algostep#1{\hbox to \algolabelwidth{\hss #1~~}}
+
+\def\algoinit{
+ \begingroup
+ \algospacing
+ \inititemize
+ \let\:=\algoitem
+ \def\={\leftarrow}
+ \let\cmt=\algcmt
+ \itemcount=0
+}
+
+\def\typedalgo#1#2{\algoinit {\bo #1\/} \alg{#2}}
+\def\algo#1{\typedalgo{\localestr{alg:alg}}{#1}}
+\def\proc#1{\typedalgo{\localestr{alg:proc}}{#1}}
+\def\headlessalgo{\algoinit}
+
+\def\endalgo{\endlist\endgroup}
+\let\endproc=\endalgo
+
+\def\algoitem{%
+ \ifnum\itemcount=0\par\nobreak\smallskip\fi
+ \algopar\advance\itemcount by 1
+ \algostep{\the\itemcount.}%
+ \futurelet\next\algoitemh
+}
+
+\def\algoitemh{\ifx\next:\let\next=\algohang\else\let\next=\algoitemgo\fi\next}
+\def\algohang:{\advance\hangindent by \algonestindent \hskip \algonestindent\futurelet\next\algoitemh}
+\optdef\algoitemgo{\ifx\addid\undefined\else\addid{item}{\the\itemcount}\fi}
+
+\def\algin{\par\nobreak{\it \localestr{alg:in}:\/} }
+\def\algout{\par\nobreak\parindent=0pt{\it \localestr{alg:in}:\/} }
+\def\alginbreak{\hfil\break\hphantom{\it \localestr{alg:out}:\/} }
+\def\algalias#1{ (#1)}
+
+% Algorithm name in text or in a formula
+\protected\def\alg#1{\leavevmode\hbox{\csc #1}}
+
+% Comments
+\def\algcmt#1{\unskip~~\hfill\fullcmt{#1}\ignorespaces}
+\def\fullcmt#1{{$\triangleleft$\hskip0.5em\it #1}}
%% Macros for typesetting of labels
+\ucwdefmodule{labels}
+
% Default page parameters. You can change them before calling \setuplabels.
\setmargins{0pt}
\setuppage
--- /dev/null
+% The UCW Macro Collection: Czech localization
+% Written by Martin Mares <mj@ucw.cz> in 2018 and placed into public domain
+% -------------------------------------------------------------------------
+
+\ucwdefmodule{lang-cs}
+
+\localedef{\czech}{alg:alg}{Algoritmus}
+\localedef{\czech}{alg:proc}{Procedura}
+\localedef{\czech}{alg:in}{Vstup}
+\localedef{\czech}{alg:out}{Výstup}
--- /dev/null
+% The UCW Macro Collection: Destinations and links
+% Written by Martin Mares <mj@ucw.cz> in 2018 and placed into public domain
+% -------------------------------------------------------------------------
+
+\ucwdefmodule{link}
+
+% Should clickable links be produced?
+\newif\ifclickable
+\ifpdf
+ \clickabletrue
+\else
+ \clickablefalse
+\fi
+
+% Common style of all clickable links
+\pdflinkmargin=1pt
+\def\commonlinkargs{height \the\dimexpr\ht\strutbox-0.5pt\relax depth \the\dimexpr\dp\strutbox-0.5pt\relax attr {/C [0 0 0.5] /Border [0 0 2]}}
+
+% Define a PDF destination for the current position at the page
+\def\destpos#1{\ifclickable\pdfdest name {#1} xyz\relax\fi}
+
+% Define a PDF destination for the current page
+\def\destpage#1{\ifclickable\pdfdest name {#1} fit\relax\fi}
+
+% Typeset a clickable link to the given destination
+% \link{dest}{text}
+\def\link#1#2{%
+ \ifclickable
+ \pdfstartlink\commonlinkargs goto name {#1}\relax
+ #2%
+ \pdfendlink\relax
+ \else
+ #2%
+ \fi
+}
+
+% Typeset a clickable link to the given page number
+% (This does not use named destinations. We use it in tables of contents and indices,
+% where absolute page numbers are known from other sources.)
+% \linkpage{page}{text}
+\def\linkpage#1#2{\ifclickable\pdfstartlink\commonlinkargs goto page #1 {/Fit}\relax #2\pdfendlink\else #2\fi}
+
+% Typeset a clickable URL
+% \url{http://example.com/}
+\def\url{\begingroup\allowurlchars\urlaux}
+\def\urlaux#1{\linkurlaux{#1}{\displayurl #1^^X}}
+
+% Typeset a clickable link to the given URL
+% \linkurl{http://example.com/}{text}
+\def\linkurl{\begingroup\allowurlchars\linkurlaux}
+\def\linkurlaux#1#2{\endgroup
+ \leavevmode
+ \ifclickable
+ \pdfstartlink\commonlinkargs user {/Subtype/Link /A << /Type/Action /S/URI /URI(#1) >>}\relax
+ \fi
+ #2%
+ \ifclickable
+ \pdfendlink
+ \fi
+}
+
+% Catcode each special character valid in URL to 'other'
+\def\allowurlchars{\catcode`\#=12\catcode`\_=12\catcode`\%=12\catcode`\&=12\catcode`\$=12\catcode`\~=12\relax}
+
+% Style switches and the beginning/end of an URL
+\let\urlprefix\it
+\let\urlsuffix\/
+
+% Kern to place between "//" in an URL
+\newdimen\urlinterslashkern
+\urlinterslashkern=-0.1em
+
+% Internal macro for typesetting of URLs
+\def\displayurl#1:#2#3^^X{{\urlprefix #1:#2\ifx#2/\kern\urlinterslashkern\fi#3\urlsuffix}}
--- /dev/null
+%% Czech format for LuaTeX + ucwmac
+%%
+%% This is a cousin of Petr Olšák's csplain/luaplain living in LuaTeX land.
+%% It is based on ε-TeX.
+%%
+%% WARNING: This is experimental. We currently depend on internals of csplain
+%% and also on various packages related to LuaTeX, which tend to be rapidly
+%% changing.
+%%
+%% Written by Martin Mareš <mj@ucw.cz> in 2017 and placed into public domain
+
+\catcode`\{=1 \catcode`\}=2 \catcode`\#=6 \catcode9=10
+
+\input luatexiniconfig.tex % Enable LuaTeX primitives
+
+% We will skip font section of plain.tex, which sets up CM fonts.
+% Later, we will load Unicode LM fonts instead.
+% This hack is inspired by luaplain.ini.
+\let\orifont=\font
+\long\def\font#1\ttfam=\tentt{}
+\let\rm=\relax \let\tenex=\relax
+\def\mit{\fam1 } \def\cal{\fam2 }
+\def\it{\fam\itfam\tenit} \def\sl{\fam\slfam\tensl}
+\def\bf{\fam\bffam\tenbf} \def\tt{\fam\ttfam\tentt}
+\def\oldstyle{\fam1 \the\textfont1 }
+
+% Disarm \outer
+\let\outer=\relax
+
+\input etex.src % ε-TeX macros (includes plain.tex)
+
+% Bring \font back and allocate font families
+\let\font=\orifont
+\let\orifont=\undefined
+\newfam\itfam
+\newfam\slfam
+\newfam\bffam
+\newfam\ttfam
+
+\input luatex-unicode-letters.tex % Set properties of Unicode characters
+% \input ltluatex.tex % LuaTeX support for plain TeX
+\input luatex85.sty % Backward compatibility with pdfTeX
+\input pdftexconfig.tex % Initialize PDF output parameters
+\input pdftexmagfix.tex % Fix \magnification
+\input plaina4.tex % Set paper size to A4
+\input ucode.tex % \uv and similar macros for Czech typesetting
+% \input luaotfload.sty % OTF loader
+
+% Ask csplain to load LM fonts
+% (currently disabled, because it is broken in some versions; use ucw-luaofs.tex instead)
+% \def\fontfeatures{mode=base;script=latn;+tlig}
+% \let\luafonts=\relax % Avoid inclusion of csplain's luafonts.tex
+% \input lmfonts.tex
+% \let\fontfeatures=\undefined
+
+\everyjob={%
+ \message{Loaded ucw-luacsplain 2018-06}%
+ % These packages do not survive dumping, defer loading to \everyjob
+ \input ltluatex.tex
+ \input ucwmac2.tex
+ \input ucw-luaofs.tex
+}
+
+\dump
--- /dev/null
+\ucwdefmodule{luaofs}
+\ucwdefmodule{ofs}
+
+\input luaotfload.sty
+\input ofs.tex
+\nofontmessages
+
+\ofsputfamlist{^^JLatinModern:}
+
+\def\LMfeat#1{:mode=base;script=latn;+tlig}
+
+%%% LMRoman %%%
+
+\ofsdeclarefamily [LMRoman] {%
+ \loadtextfam lmr;%
+ lmbx;%
+ lmti;%
+ lmbxti;;%
+ \newvariant 8 \sl (Slanted) lmsl;;%
+ \newvariant 9 \bxsl (BoldSlanted) lmbxsl;;%
+ \newvariant a \bo (BoldNormal) lmb;;%
+ \newvariant b \bosl (BoldNormalSlanted) lmbsl;;%
+ \newvariant c \csc (CapsAndSmallCaps) lmcsc;;%
+}
+
+\registertfm lmr - LMRoman10-Regular\LMfeat{}
+\registertfm lmr 0pt-6pt LMRoman5-Regular\LMfeat{}
+\registertfm lmr 6pt-7pt LMRoman6-Regular\LMfeat{}
+\registertfm lmr 7pt-8pt LMRoman7-Regular\LMfeat{}
+\registertfm lmr 8pt-9pt LMRoman8-Regular\LMfeat{}
+\registertfm lmr 9pt-10pt LMRoman9-Regular\LMfeat{}
+\registertfm lmr 10pt-12pt LMRoman10-Regular\LMfeat{}
+\registertfm lmr 12pt-17pt LMRoman12-Regular\LMfeat{}
+\registertfm lmr 17pt-* LMRoman17-Regular\LMfeat{}
+
+\registertfm lmbx - LMRoman10-Bold\LMfeat{}
+\registertfm lmbx 0pt-6pt LMRoman5-Bold\LMfeat{}
+\registertfm lmbx 6pt-7pt LMRoman6-Bold\LMfeat{}
+\registertfm lmbx 7pt-8pt LMRoman7-Bold\LMfeat{}
+\registertfm lmbx 8pt-9pt LMRoman8-Bold\LMfeat{}
+\registertfm lmbx 9pt-10pt LMRoman9-Bold\LMfeat{}
+\registertfm lmbx 10pt-12pt LMRoman10-Bold\LMfeat{}
+\registertfm lmbx 12pt-* LMRoman12-Bold\LMfeat{}
+
+\registertfm lmti - LMRoman10-Italic\LMfeat{}
+\registertfm lmti 0pt-8pt LMRoman7-Italic\LMfeat{}
+\registertfm lmti 8pt-9pt LMRoman8-Italic\LMfeat{}
+\registertfm lmti 9pt-10pt LMRoman9-Italic\LMfeat{}
+\registertfm lmti 10pt-12pt LMRoman10-Italic\LMfeat{}
+\registertfm lmti 12pt-* LMRoman12-Italic\LMfeat{}
+
+\registertfm lmbxti - LMRoman10-BoldItalic\LMfeat{}
+
+\registertfm lmsl - LMRomanSlant10-Regular\LMfeat{}
+\registertfm lmsl 0pt-9pt LMRomanSlant8-Regular\LMfeat{}
+\registertfm lmsl 9pt-10pt LMRomanSlant9-Regular\LMfeat{}
+\registertfm lmsl 10pt-12pt LMRomanSlant10-Regular\LMfeat{}
+\registertfm lmsl 12pt-17pt LMRomanSlant12-Regular\LMfeat{}
+\registertfm lmsl 17pt-* LMRomanSlant17-Regular\LMfeat{}
+
+\registertfm lmbxsl - LMRomanSlant10-Bold\LMfeat{}
+
+\registertfm lmb - LMRomanDemi10-Regular\LMfeat{}
+
+\registertfm lmbsl - LMRomanDemi10-Oblique\LMfeat{}
+
+\registertfm lmcsc - LMRomanCaps10-Regular\LMfeat{}
+
+\setfonts[LMRoman/]
+
+%%% LMSans %%%
+
+\ofsdeclarefamily [LMSans] {%
+ \loadtextfam lmss;%
+ lmssbx;%
+ lmsso;%
+ lmssbo;;%
+}
+
+\registertfm lmss - LMSans10-Regular\LMfeat{}
+\registertfm lmss 0pt-9pt LMSans8-Regular\LMfeat{}
+\registertfm lmss 9pt-10pt LMSans9-Regular\LMfeat{}
+\registertfm lmss 10pt-12pt LMSans10-Regular\LMfeat{}
+\registertfm lmss 12pt-17pt LMSans12-Regular\LMfeat{}
+\registertfm lmss 17pt-* LMSans17-Regular\LMfeat{}
+
+\registertfm lmssbx - LMSans10-Bold\LMfeat{}
+
+\registertfm lmsso - LMSans10-Oblique\LMfeat{}
+\registertfm lmsso 0pt-9pt LMSans8-Oblique\LMfeat{}
+\registertfm lmsso 9pt-10pt LMSans9-Oblique\LMfeat{}
+\registertfm lmsso 10pt-12pt LMSans10-Oblique\LMfeat{}
+\registertfm lmsso 12pt-17pt LMSans12-Oblique\LMfeat{}
+\registertfm lmsso 17pt-* LMSans17-Oblique\LMfeat{}
+
+\registertfm lmssbo - LMSans10-BoldOblique\LMfeat{}
+
+%%% LMSansDC %%%
+
+\ofsdeclarefamily [LMSansDC] {%
+ \loadtextfam lmssdc;%
+ ;%
+ lmssdo;%
+ ;;%
+}
+
+\registertfm lmssdc - LMSansDemiCond10-Regular\LMfeat{}
+
+\registertfm lmssdo - LMSansDemiCond10-Oblique\LMfeat{}
+
+%%% LMMono %%%
+
+\ofsdeclarefamily [LMMono] {%
+ \loadtextfam lmtt;%
+ lmtk;%
+ lmtti;%
+ ;;%
+ \newvariant 8 \sl (Slanted) lmtto;;%
+ \newvariant 9 \bxsl (BoldSlanted) lmtko;;%
+ \newvariant c \csc (CapsAndSmallCaps) lmtcsc;;%
+}
+
+\registertfm lmtt - LMMono10-Regular\LMfeat{}
+\registertfm lmtt 0pt-9pt LMMono8-Regular\LMfeat{}
+\registertfm lmtt 9pt-10pt LMMono9-Regular\LMfeat{}
+\registertfm lmtt 10pt-12pt LMMono10-Regular\LMfeat{}
+\registertfm lmtt 12pt-* LMMono12-Regular\LMfeat{}
+
+\registertfm lmtk - LMMonoLt10-Bold\LMfeat{}
+
+\registertfm lmtti - LMMono10-Italic\LMfeat{}
+
+\registertfm lmtto - LMMonoSlant10-Regular\LMfeat{}
+
+\registertfm lmtko - LMMonoLt10-BoldOblique\LMfeat{}
+
+\registertfm lmtcsc - LMMonoCaps10-Regular\LMfeat{}
+
+\newfam\ttfam
+\loadmathfam\ttfam[/LMMono10-Regular\LMfeat{}]
+
+%%% LMMonoCondensed %%%
+
+\ofsdeclarefamily [LMMonoCondensed] {%
+ \loadtextfam lmtlc;%
+ ;%
+ lmtlco;%
+ ;;%
+}
+
+\registertfm lmtlc - LMMonoLtCond10-Regular\LMfeat{}
+
+\registertfm lmtlco - LMMonoLtCond10-Oblique\LMfeat{}
+
+%%% UCW extensions %%%
+
+\ofsputfamlist{^^JUCW:}
+
+\ofsdeclarefamily [BlackboardBold] {%
+ \loadtextfam bbm;%
+ ;%
+ ;%
+ ;\defaultextraenc;%
+}
+
+\registertfm bbm - bbm10
+\registertfm bbm 0pt-6pt bbm5
+\registertfm bbm 6pt-7pt bbm6
+\registertfm bbm 7pt-8pt bbm7
+\registertfm bbm 8pt-9pt bbm8
+\registertfm bbm 9pt-10pt bbm9
+\registertfm bbm 10pt-12pt bbm10
+\registertfm bbm 12pt-17pt bbm12
+\registertfm bbm 17pt-* bbm17
+
+% \bb - blackboard bold math font
+
+\newfam\bbfam
+\def\bb{\fam\bbfam}
+
+\def\loadbbm{%
+ \loadmathfam\bbfam[/bbm]%
+}
+\loadbbm
+
+%%% Font size switches %%%
+
+% Recalculate line spacing for a given point size of the font (assuming CM-like metrics).
+% Also sets \strut and \topskip.
+\def\setbaselines#1{%
+ \dimen0=1pt
+ \dimen0=#1\dimen0
+ \normalbaselineskip=1.2\dimen0
+ \normallineskip=0.1\dimen0
+ \setbox\strutbox=\hbox{\vrule height 0.85\dimen0 depth 0.35\dimen0 width 0pt}%
+ \topskip=1\dimen0
+ \normalbaselines
+}
+
+% Switch to a specified font size (including math, line spacing etc.)
+\def\settextsize#1{%
+ \def\fomenc{CM}%
+ \setfonts[/#1]%
+ \setmath[//]%
+ \setbaselines{#1}%
+ \loadbbm
+}
+\def\twelvepoint{\settextsize{12}}
+
+%%% Various hacks %%%
+
+% Re-define \tt, so that it works in both text and math mode
+\def\tt{\ifmmode\fam\ttfam\else\setfonts[LMMono/]\fi}
+
+% Re-define ucwmac's \fontfont
+\let\footfont=\tenrm
% Written by Martin Mares <mj@ucw.cz> in 2010 and placed into public domain
% -------------------------------------------------------------------------
+\ucwdefmodule{ofs}
+
\ifx\OFSversion\undefined
\input ofs.tex
% \detailfontmessages
\def\twelvepoint{\settextsize{12}}
% Re-define \tt, so that it works in both text and math mode
+\loadmathfam\ttfam[/cmtt\fotenc]
\def\tt{\ifmmode\fam\ttfam\else\setfonts[CMTypewriter/]\fi}
%% ISO 216 paper sizes [ABC]{0..10}
+\ucwdefmodule{paper}
+
\defpaper{a0}{840truemm}{1189truemm}
\defpaper{a1}{594truemm}{840truemm}
\defpaper{a2}{420truemm}{594truemm}
--- /dev/null
+-- A library for writing PDF metadata
+
+luatexbase.provides_module {
+ name = 'pdfmeta',
+ version = '0.0',
+ author = 'Martin Mareš',
+}
+
+pdfmeta = { }
+
+-- Debugging function for dumping a table
+
+local function do_dump_table(t, key, depth)
+ local tmp = string.rep(" ", depth)
+ if key then
+ tmp = tmp .. key .. ": "
+ end
+ if type(t) == "table" then
+ texio.write(tmp .. "{\n")
+ for k, v in pairs(t) do
+ do_dump_table(v, k, depth+1)
+ end
+ tmp = string.rep(" ", depth) .. "}"
+ elseif type(t) == "number" then
+ tmp = tmp .. tostring(t)
+ elseif type(t) == "string" then
+ tmp = tmp .. string.format("%q", t)
+ else
+ tmp = tmp .. "???"
+ end
+ texio.write(tmp .. "\n")
+end
+
+local function dump_table(t)
+ do_dump_table(t, nil, 0)
+end
+
+-- PDF metadata can be encoded either in an ancient PDFEncoding, which covers
+-- only a small subset of Unicode characters, or in UTF-16-BE. We use the latter
+-- for anything outside basic ASCII. It is tempting to use "lualibs-unicode"
+-- for the conversion, but alas, it is too broken.
+
+local function pdf_string(s)
+ local u16 = {}
+ local str = {}
+ local strok = true
+ table.insert(u16, "<feff")
+ for x in string.utfvalues(s) do
+ if x >= 0x20 and x < 0x7f and x ~= 0x28 and x ~= 0x29 and x ~= 0x5c then
+ if x == 0x28 or x == 0x29 or x == 0x5c then
+ table.insert(str, "\\" .. string.char(x))
+ else
+ table.insert(str, string.char(x))
+ end
+ else
+ strok = false
+ end
+ if x < 0x10000 then
+ table.insert(u16, string.format("%04x", x))
+ else
+ local y = x - 0x10000
+ local h = y/1024 + 0xd800
+ local l = y%1024 + 0xdc00
+ table.insert(u16, string.format("%04x%04x", h, l))
+ end
+ end
+
+ if strok then
+ return "(" .. table.concat(str) .. ")"
+ else
+ table.insert(u16, ">")
+ return table.concat(u16)
+ end
+end
+
+local function pdf_encode_dict_body(d)
+ local t = {}
+ for k, v in pairs(d) do
+ table.insert(t, "/" .. k .. " " .. v)
+ end
+ return table.concat(t, "\n")
+end
+
+local function pdf_encode_dict(d)
+ return '<< ' .. pdf_encode_dict_body(d) .. ' >>'
+end
+
+-- Metadata dictionary
+
+pdfmeta.info = { }
+pdfmeta.catalog = { }
+
+function pdfmeta.set_info(key, val)
+ pdfmeta.info[key] = pdf_string(val)
+end
+
+local function write_metas()
+ pdfmeta.make_outline()
+ pdf.setinfo(pdf_encode_dict_body(pdfmeta.info))
+ pdf.setcatalog(pdf_encode_dict_body(pdfmeta.catalog))
+end
+
+luatexbase.add_to_callback('finish_pdffile', write_metas, 'Write all PDF metadata')
+
+-- Document outline
+
+pdfmeta.outline = { children = {} }
+pdfmeta.outline_stack = { pdfmeta.outline }
+
+function pdfmeta.add_outline(key, dest, text)
+ local stk = pdfmeta.outline_stack
+ local level = 1
+ local p, r
+
+ for k in string.gmatch(key, '%.*(%d+)') do
+ level = level+1
+ end
+ while #stk >= level do
+ table.remove(stk)
+ end
+ while #stk < level do
+ p = stk[#stk]
+ r = { children = {} }
+ table.insert(p.children, r)
+ table.insert(stk, r)
+ end
+ r.dest = dest
+ text = string.gsub(text, '~', unicode.utf8.char(160))
+ text = string.gsub(text, '%-%-%-', unicode.utf8.char(8212))
+ text = string.gsub(text, '%-%-', unicode.utf8.char(8211))
+ r.text = text;
+end
+
+local function reserve_objects(r)
+ r.obj = pdf.reserveobj()
+ r.num_descendants = 0
+ for i, child in pairs(r.children) do
+ reserve_objects(child)
+ r.num_descendants = r.num_descendants + child.num_descendants + 1
+ end
+end
+
+local function outline_ref(r)
+ if r then
+ return r.obj .. ' 0 R'
+ else
+ tex.error('Asked to format null reference')
+ return 'nil'
+ end
+end
+
+local function gen_outline(r, parent)
+ d = {}
+ r.dict = d
+
+ if not parent then
+ d.Type = '/Outlines'
+ d.Count = r.num_descendants
+ else
+ d.Parent = outline_ref(parent)
+ d.Count = r.num_descendants
+ end
+
+ if r.text then
+ d.Title = pdf_string(r.text)
+ d.A = '<< /D (' .. r.dest .. ') /S /GoTo >>'
+ end
+
+ if r.children[1] then
+ d.First = outline_ref(r.children[1])
+ d.Last = outline_ref(r.children[#r.children])
+ for i, child in pairs(r.children) do
+ gen_outline(child, r)
+ if i>1 then
+ child.dict.Prev = outline_ref(r.children[i-1])
+ end
+ if i<#r.children then
+ child.dict.Next = outline_ref(r.children[i+1])
+ end
+ end
+ end
+end
+
+local function write_outline(r)
+ pdf.obj {
+ type = 'raw',
+ immediate = true,
+ objnum = r.obj,
+ string = pdf_encode_dict(r.dict),
+ }
+ for i, child in pairs(r.children) do
+ write_outline(child)
+ end
+end
+
+function pdfmeta.make_outline()
+ local o = pdfmeta.outline
+ reserve_objects(o)
+ gen_outline(o, nil)
+ -- dump_table(o)
+ write_outline(o)
+ pdfmeta.catalog.Outlines = outline_ref(o)
+end
--- /dev/null
+% The UCW Macro Collection: PDF meta-data (requires LuaTeX)
+% Written by Martin Mares <mj@ucw.cz> in 2018 and placed into public domain
+% -------------------------------------------------------------------------
+
+\ucwdefmodule{pdfmeta}
+
+\ifx\directlua\undefined
+ \def\pdfmetainfo#1#2{}%
+ \def\pdfmetaoutline#1#2#3{}%
+\endinput\fi
+
+\directlua{require('ucw-pdfmeta.lua')}
+
+% Set entry in Info dictionary (usual keys are Author and Title)
+% \pdfmetainfo{key}{value}
+\def\pdfmetainfo#1#2{\directlua{pdfmeta.set_info('\luaescapestring{#1}', '\luaescapestring{#2}')}}
+
+% Add entry to the document outline
+% \pdfmetaoutline{chapter.section.subsec.etc}{link-destination}{text}
+\def\pdfmetaoutline#1#2#3{%
+ \directlua{pdfmeta.add_outline('\luaescapestring{#1}', '\luaescapestring{#2}', '\luaescapestring{#3}')}%
+}
--- /dev/null
+% The UCW Macro Collection: References
+% Written by Martin Mares <mj@ucw.cz> in 2018 and placed into public domain
+% -------------------------------------------------------------------------
+
+\ucwdefmodule{ref}
+\ucwmodule{link}
+
+% We maintain a collection of objects. Each object has:
+% - type (namespace -- e.g., chapter)
+% - identifier (alphanumeric string used to refer to the object in TeX source)
+% - label (to be typeset in clickable links -- e.g., chapter number)
+% - location (it is tied to a specific place in the output document)
+
+% Some output formats (e.g., EPUB) have output split to multiple files.
+% We need to keep track of the file name for every object.
+% When producing a PDF, it is always empty.
+\def\refcurrentfile{}
+
+% An auxiliary file to which we write definitions of all identifiers
+\newwrite\ids
+\def\writeid#1#2{\immediate\write\ids{\string\iddef{#1}{#2}{\refcurrentfile}}}
+\def\delayedwriteid#1#2{\write\ids{\string\iddef{#1}{#2}{\refcurrentfile}}}
+
+% Used in auxiliary files
+\def\iddef#1#2#3{\ifcsname id:#1\endcsname\ucwwarn{Identifier #1 re-defined}\else
+\expandafter\def\csname id:#1\endcsname{#2}%
+\expandafter\def\csname ff:#1\endcsname{#3}%
+\fi}
+
+% Read the auxiliary file from the previous run of TeX, create a new one
+\immediate\openin\ids=\jobname.ids.aux
+\ifeof\ids
+\else
+\input \jobname.ids.aux
+\fi
+\immediate\closein\ids
+\immediate\openout\ids=\jobname.ids.aux
+
+% Define an object. It is called from macros with optional arguments
+% as \addid{type}{label}. It defines a new object whose identifier is the
+% optional argument.
+% It sets \currentid to either ID prefixed by its type, or to \relax.
+\def\addid#1#2{%
+ \ifx\optarg\relax
+ \let\currentid\relax
+ \else
+ \edef\currentid{#1\optarg}%
+ \writeid{\currentid}{#2}%
+ \destpos{\currentid}%
+ \fi
+}
+
+% A low-level interface for typesetting references: produces a clickable link
+% to the identifier #2 of type #1 with a label translated by macro #3 (use \relax
+% for no translation).
+\def\reflink#1#2#3{\expandafter\ifx\csname id:#1#2\endcsname\relax
+ {\ifx\bo\undefined\bf\else\bo\fi ??}%
+ \immediate\write16{*** Warning: Reference #1 undefined ***}%
+\else
+ \link{#1#2}{#3{\csname id:#1#2\endcsname}}%
+\fi
+}
+
+% Typeset a link to identifier #2 of type #1
+\def\ref#1#2{\reflink{#1}{#2}\relax}
+
+% Define an identifier of type page pointing to the current page
+\def\pageid#1{\delayedwriteid{page#1}{\the\count0}\destpage{page#1}}
+\def\pageref{\ref{page}}
% Written by Martin Mares <mj@ucw.cz> in 2010 and placed into public domain
% -------------------------------------------------------------------------
+\ucwdefmodule{verb}
+
% We'll use internal macros of plain TeX
\catcode`@=11
-% The UCW Macro Collection (a successor of mjmac.tex)
-% Written by Martin Mares <mj@ucw.cz> in 2010--2013 and placed into public domain
-% -------------------------------------------------------------------------------
+% Emulate behavior of historic ucwmac
-%%% Prolog %%%
+\input ucwmac2.tex
-% We'll use internal macros of plain TeX
-\catcode`@=11
-
-%%% PDF output detection %%%
-
-\newif\ifpdf
-\pdffalse
-
-\ifx\pdfoutput\undefined
-\else\ifnum\pdfoutput>0
- \pdftrue
- \pdfpkresolution=600 % Provide a reasonable default
-\fi\fi
-
-%%% Page size and margins %%%
-
-% If you modify these registers, call \setuppage afterwards
-\newdimen\pagewidth
-\newdimen\pageheight
-\newdimen\leftmargin
-\newdimen\rightmargin
-\newdimen\topmargin
-\newdimen\bottommargin
-\newdimen\evenpageshift
-
-\def\setuppage{%
- \hsize=\pagewidth
- \advance\hsize by -\leftmargin
- \advance\hsize by -\rightmargin
- \vsize=\pageheight
- \advance\vsize by -\topmargin
- \advance\vsize by -\bottommargin
- \hoffset=\leftmargin
- \advance\hoffset by -1truein
- \voffset=\topmargin
- \advance\voffset by -1truein
- \ifpdf
- \pdfhorigin=1truein
- \pdfvorigin=1truein
- \pdfpagewidth=\pagewidth
- \pdfpageheight=\pageheight
- \fi
-}
-
-% Set multiple margins to the same value
-\def\sethmargins#1{\leftmargin=#1\relax\rightmargin=#1\relax\evenpageshift=0pt\relax}
-\def\setvmargins#1{\topmargin=#1\relax\bottommargin=#1\relax}
-\def\setmargins#1{\sethmargins{#1}\setvmargins{#1}}
-
-% Define inner/outer margin instead of left/right
-\def\setinneroutermargin#1#2{\leftmargin#1\relax\rightmargin#2\relax\evenpageshift=\rightmargin\advance\evenpageshift by -\leftmargin}
-
-% Use a predefined paper format, calls \setuppage automagically
-\def\setpaper#1{%
- \expandafter\let\expandafter\currentpaper\csname paper-#1\endcsname
- \ifx\currentpaper\relax
- \errmessage{Undefined paper format #1}
- \fi
- \currentpaper
-}
-
-% Switch to landscape orientation, calls \setuppage automagically
-\def\landscape{%
- \dimen0=\pageheight
- \pageheight=\pagewidth
- \pagewidth=\dimen0
- \setuppage
-}
-
-% Common paper sizes
-\def\defpaper#1#2#3{\expandafter\def\csname paper-#1\endcsname{\pagewidth=#2\pageheight=#3\setuppage}}
-\defpaper{a3}{297truemm}{420truemm}
-\defpaper{a4}{210truemm}{297truemm}
-\defpaper{a5}{148truemm}{210truemm}
-\defpaper{letter}{8.5truein}{11truein}
-\defpaper{legal}{8.5truein}{14truein}
-
-% Default page parameters
-\setmargins{1truein}
-\setpaper{a4}
-
-%%% Placing material at specified coordinates %%%
-
-% Set all dimensions of a given box register to zero
-\def\smashbox#1{\ht#1=0pt \dp#1=0pt \wd#1=0pt}
-\long\def\smashedhbox#1{{\setbox0=\hbox{#1}\smashbox0\box0}}
-\long\def\smashedvbox#1{{\setbox0=\vbox{#1}\smashbox0\box0}}
-
-% Variants of \llap and \rlap working equally on both sides and/or vertically
-\def\hlap#1{\hbox to 0pt{\hss #1\hss}}
-\def\vlap#1{\vbox to 0pt{\vss #1\vss}}
-\def\clap#1{\vlap{\hlap{#1}}}
-
-% \placeat{right}{down}{hmaterial} places <hmaterial>, so that its
-% reference point lies at the given position wrt. the current ref point
-\long\def\placeat#1#2#3{\smashedhbox{\hskip #1\lower #2\hbox{#3}}}
-
-% Like \vbox, but with reference point in the upper left corner
-\long\def\vhang#1{\vtop{\hrule height 0pt\relax #1}}
-
-% Like \vhang, but respecting interline skips
-\long\def\vhanglines#1{\vtop{\hbox to 0pt{}#1}}
-
-% Crosshair with reference point in its center
-\def\crosshair#1{\clap{\vrule height 0.2pt width #1}\clap{\vrule height #1 width 0.2pt}}
-
-%%% Output routine %%%
-
-\newbox\pageunderlays
-\newbox\pageoverlays
-\newbox\commonunderlays
-\newbox\commonoverlays
-
-% In addition to the normal page contents, you can define page overlays
-% and underlays, which are zero-size vboxes positioned absolutely in the
-% front / in the back of the normal material. Also, there are global
-% versions of both which are not reset after every page.
-\def\addlay#1#2{\setbox#1=\vbox{\ifvbox#1\box#1\fi\nointerlineskip\smashedvbox{#2}}}
-\def\pageunderlay{\addlay\pageunderlays}
-\def\pageoverlay{\addlay\pageoverlays}
-\def\commonunderlay{\addlay\commonoverlays}
-\def\commonoverlay{\addlay\commonoverlays}
-
-% Our variation on \plainoutput, which manages inner/outer margins and overlays
-\output{\ucwoutput}
-\newdimen\pagebodydepth
-\def\ucwoutput{\wigglepage\shipout\vbox{%
- \makeheadline
- \ifvbox\commonunderlays\copy\commonunderlays\nointerlineskip\fi
- \ifvbox\pageunderlays\box\pageunderlays\nointerlineskip\fi
- \pagebody
- \pagebodydepth=\prevdepth
- \nointerlineskip
- \ifvbox\commonoverlays\vbox to 0pt{\vskip -\vsize\copy\commonoverlays\vss}\nointerlineskip\fi
- \ifvbox\pageoverlays\vbox to 0pt{\vskip -\vsize\box\pageoverlays\vss}\nointerlineskip\fi
- \prevdepth=\pagebodydepth
- \makefootline
-}\advancepageno
-\ifnum\outputpenalty>-\@MM \else\dosupereject\fi}
-
-\def\wigglepage{\ifodd\pageno\else\advance\hoffset by \evenpageshift\fi}
-
-% Make it easier to redefine footline font (also, fix it so that OFS won't change it unless asked)
-\let\footfont=\tenrm
-\footline={\hss\footfont\folio\hss}
-
-%%% Itemization %%%
-
-% Default dimensions of itemized lists
-\newdimen\itemindent \itemindent=0.5in
-\newdimen\itemnarrow \itemnarrow=0.5in % make lines narrower by this amount
-\newskip\itemmarkerskip \itemmarkerskip=0.4em % between marker and the item
-\newskip\preitemizeskip \preitemizeskip=3pt plus 2pt minus 1pt % before the list
-\newskip\postitemizeskip \postitemizeskip=3pt plus 2pt minus 1pt % after the list
-\newskip\interitemskip \interitemskip=2pt plus 1pt minus 0.5pt % between two items
-
-% Analogues for nested lists
-\newdimen\nesteditemindent \nesteditemindent=0.25in
-\newdimen\nesteditemnarrow \nesteditemnarrow=0.25in
-\newskip\prenesteditemizeskip \prenesteditemizeskip=0pt
-\newskip\postnesteditemizeskip \postnesteditemizeskip=0pt
-
-\newif\ifitems\itemsfalse
-\newbox\itembox
-\newcount\itemcount
-
-\def\preitemize{
- \ifitems
- \vskip\prenesteditemizeskip
- \advance\leftskip by \nesteditemindent
- \advance\rightskip by \nesteditemnarrow
- \else
- \vskip\preitemizeskip
- \advance\leftskip by \itemindent
- \advance\rightskip by \itemnarrow
- \fi
- \parskip=\interitemskip
-}
-
-\def\postitemize{
- \ifitems
- \vskip\postnesteditemizeskip
- \else
- \vskip\postitemizeskip
- \fi
-}
-
-\def\inititemize{\begingroup\preitemize\itemstrue\parindent=0pt}
-
-\def\itemize#1{\inititemize\setbox\itembox\llap{#1\hskip\itemmarkerskip}%
-\let\:=\singleitem}
-
-\def\singleitem{\par\leavevmode\copy\itembox\ignorespaces}
-
-\def\endlist{\par\endgroup\postitemize}
-
-\def\ibull{\raise0.2ex\hbox{$\bullet$}} % Signs frequently used for \itemize
-\def\idot{\raise0.2ex\hbox{$\cdot$}}
-\def\istar{\raise0.2ex\hbox{$\ast$}}
-
-\def\numlist#1{\inititemize\itemcount=0\let\:=\numbereditem
-\let\itemnumbering=#1}
-
-\def\numbereditem{\par\leavevmode\advance\itemcount by 1
-\llap{\itemnumbering\hskip\itemmarkerskip}\ignorespaces}
-
-\def\nnorm{\the\itemcount}
-\def\ndotted{\nnorm.}
-\def\nparen{\nnorm)}
-\def\nroman{\romannumeral\itemcount}
-\def\nromanp{\nroman)}
-\def\nalpha{\count@=96\advance\count@ by\itemcount\char\count@)}
-\def\nAlpha{\count@=64\advance\count@ by\itemcount\char\count@)}
-\def\ngreek{$\ifcase\itemcount\or\alpha\or\beta\or\gamma\or\delta\or\epsilon\or
-\zeta\or\eta\or\theta\or\iota\or\kappa\or\lambda\or\mu\or\nu\or\xi\or\pi\or\rho
-\or\sigma\or\tau\or\upsilon\or\phi\or\chi\or\psi\or\omega\fi$)}
-
-%%% Miscellanea %%%
-
-% {\I italic} with automatic italic correction
-\def\I{\it\aftergroup\/}
-
-% A breakable dash, to be repeated on the next line
-\def\={\discretionary{-}{-}{-}}
-
-% Non-breakable identifiers
-\def\<#1>{\leavevmode\hbox{\I #1}}
-
-% A handy shortcut
-\let\>=\noindent
-
-% Variants of \centerline, \leftline and \rightline, which are compatible with
-% verbatim environments and other catcode hacks
-\def\cline{\bgroup\def\linet@mp{\aftergroup\box\aftergroup0\aftergroup\egroup\hss\bgroup\aftergroup\hss\aftergroup\egroup}\afterassignment\linet@mp\setbox0\hbox to \hsize}
-\def\lline{\bgroup\def\linet@mp{\aftergroup\box\aftergroup0\aftergroup\egroup\bgroup\aftergroup\hss\aftergroup\egroup}\afterassignment\linet@mp\setbox0\hbox to \hsize}
-\def\rline{\bgroup\def\linet@mp{\aftergroup\box\aftergroup0\aftergroup\egroup\hss\bgroup\aftergroup\egroup}\afterassignment\linet@mp\setbox0\hbox to \hsize}
-
-%%% Epilog %%%
-
-% Let's hide all internal macros
-\catcode`@=12
+\preitemizepenalty=0
+\postitemizepenalty=0
--- /dev/null
+% The UCW Macro Collection (a successor of mjmac.tex)
+% Written by Martin Mares <mj@ucw.cz> in 2010--2018 and placed into public domain
+% -------------------------------------------------------------------------------
+
+\ifx\ucwmodule\undefined\else\endinput\fi
+
+%%% Prolog %%%
+
+% We'll use internal macros of plain TeX
+\catcode`@=11
+
+\ifx\eTeXversion\undefined
+\errmessage{ucwmac requires the e-TeX engine or its successor}
+\fi
+
+%%% PDF output detection %%%
+
+\newif\ifpdf
+\pdffalse
+
+\ifx\pdfoutput\undefined
+\else\ifnum\pdfoutput>0
+ \pdftrue
+ \pdfpkresolution=600 % Provide a reasonable default
+\fi\fi
+
+\ifx\directlua\undefined\else
+ % In LuaTeX \pdfpkresolution is not enough
+ \directlua{kpse.init_prog("luatex", 600, "ljfour")}
+\fi
+
+%%% Temporary registers %%%
+
+\newcount\tmpcount
+\newdimen\tmpdimen
+
+%%% Auxiliary macros %%%
+
+% Prepend/append #2 to the definition of #1
+\long\def\prependef#1#2{\expandafter\def\expandafter#1\expandafter{#2#1}}
+\long\def\appendef#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
+
+% Variants of \def and \let, where the control sequence name is given as a string
+\def\sdef#1{\expandafter\def\csname#1\endcsname}
+\def\slet#1#2{\expandafter\let\csname#1\expandafter\endcsname\csname#2\endcsname}
+
+% Assign a control sequence given as a string, complain if it is not defined.
+\def\sget#1#2{\ifcsname#2\endcsname
+ \expandafter\let\expandafter#1\csname#2\endcsname
+ \else
+ \errmessage{Undefined control sequence #2}%
+ \let#1\relax
+ \fi
+}
+
+% Add \protected to an existing macro
+\def\addprotected#1{\protected\edef#1{\expandafter\unexpanded\expandafter{#1}}}
+
+% Protect ~
+\addprotected~
+
+\def\ucwwarn#1{\immediate\write16{*** UCWmac warning: #1 ***}}
+
+%%% Page size and margins %%%
+
+% If you modify these registers, call \setuppage afterwards
+\ifx\luatexversion\undefined
+ % In LuaTeX, \pagewidth and \pageheight are primitive
+ \newdimen\pagewidth
+ \newdimen\pageheight
+\fi
+\newdimen\leftmargin
+\newdimen\rightmargin
+\newdimen\topmargin
+\newdimen\bottommargin
+\newdimen\evenpageshift
+
+\def\setuppage{%
+ \hsize=\pagewidth
+ \advance\hsize by -\leftmargin
+ \advance\hsize by -\rightmargin
+ \vsize=\pageheight
+ \advance\vsize by -\topmargin
+ \advance\vsize by -\bottommargin
+ \hoffset=\leftmargin
+ \advance\hoffset by -1truein
+ \voffset=\topmargin
+ \advance\voffset by -1truein
+ \ifpdf
+ \pdfhorigin=1truein
+ \pdfvorigin=1truein
+ \ifx\luatexversion\undefined
+ \pdfpagewidth=\pagewidth
+ \pdfpageheight=\pageheight
+ \fi
+ \fi
+}
+
+% Set multiple margins to the same value
+\def\sethmargins#1{\leftmargin=#1\relax\rightmargin=#1\relax\evenpageshift=0pt\relax}
+\def\setvmargins#1{\topmargin=#1\relax\bottommargin=#1\relax}
+\def\setmargins#1{\sethmargins{#1}\setvmargins{#1}}
+
+% Define inner/outer margin instead of left/right
+\def\setinneroutermargin#1#2{\leftmargin#1\relax\rightmargin#2\relax\evenpageshift=\rightmargin\advance\evenpageshift by -\leftmargin}
+
+% Use a predefined paper format, calls \setuppage automagically
+\def\setpaper#1{%
+ \expandafter\let\expandafter\currentpaper\csname paper-#1\endcsname
+ \ifx\currentpaper\relax
+ \errmessage{Undefined paper format #1}
+ \fi
+ \currentpaper
+}
+
+% Switch to landscape orientation, calls \setuppage automagically
+\def\landscape{%
+ \dimen0=\pageheight
+ \pageheight=\pagewidth
+ \pagewidth=\dimen0
+ \setuppage
+}
+
+% Common paper sizes
+\def\defpaper#1#2#3{\expandafter\def\csname paper-#1\endcsname{\pagewidth=#2\pageheight=#3\setuppage}}
+\defpaper{a3}{297truemm}{420truemm}
+\defpaper{a4}{210truemm}{297truemm}
+\defpaper{a5}{148truemm}{210truemm}
+\defpaper{letter}{8.5truein}{11truein}
+\defpaper{legal}{8.5truein}{14truein}
+
+% Default page parameters
+\setmargins{1truein}
+\setpaper{a4}
+
+%%% Macros with optional arguments %%%
+
+% After \def\a{\withoptarg\b}, the macro \a behaves in this way:
+% \a[arg] does \def\optarg{arg} and then it expands \b
+% \a does \let\optarg=\relax and then it expands \b
+\def\withoptarg#1{\let\xoptcall=#1\futurelet\next\xopt}
+\def\xopt{\ifx\next[\expandafter\xoptwith\else\let\optarg=\relax\expandafter\xoptcall\fi}
+\def\xoptwith[#1]{\def\optarg{#1}\xoptcall}
+
+% A shortcut for defining macros with optional arguments:
+% \optdef\macro behaves as \def\domacro, while \macro itself is defined
+% as a wrapper calling \domacro using \withoptarg.
+\def\optdef#1{%
+ \edef\xoptname{\expandafter\eatbackslash\string#1}%
+ \edef#1{\noexpand\withoptarg\csname do\xoptname\endcsname}%
+ \expandafter\def\csname do\xoptname\endcsname
+}
+
+% Trick: \eatbackslash eats the next backslash of category 12
+\begingroup\lccode`\+=`\\
+\lowercase{\endgroup\def\eatbackslash+{}}
+
+% Expand to the optional argument if it exists
+\def\optargorempty{\ifx\optarg\relax\else\optarg\fi}
+
+%%% Placing material at specified coordinates %%%
+
+% Set all dimensions of a given box register to zero
+\def\smashbox#1{\ht#1=0pt \dp#1=0pt \wd#1=0pt}
+\long\def\smashedhbox#1{{\setbox0=\hbox{#1}\smashbox0\box0}}
+\long\def\smashedvbox#1{{\setbox0=\vbox{#1}\smashbox0\box0}}
+
+% Variants of \llap and \rlap working equally on both sides and/or vertically
+\def\hlap#1{\hbox to 0pt{\hss #1\hss}}
+\def\vlap#1{\vbox to 0pt{\vss #1\vss}}
+\def\clap#1{\vlap{\hlap{#1}}}
+
+% \placeat{right}{down}{hmaterial} places <hmaterial>, so that its
+% reference point lies at the given position wrt. the current ref point
+\long\def\placeat#1#2#3{\smashedhbox{\hskip #1\lower #2\hbox{#3}}}
+
+% Like \vbox, but with reference point in the upper left corner
+\long\def\vhang#1{\vtop{\hrule height 0pt\relax #1}}
+
+% Like \vhang, but respecting interline skips
+\long\def\vhanglines#1{\vtop{\hbox to 0pt{}#1}}
+
+% Crosshair with reference point in its center
+\def\crosshair#1{\clap{\vrule height 0.2pt width #1}\clap{\vrule height #1 width 0.2pt}}
+
+%%% Output routine %%%
+
+\newbox\pageunderlays
+\newbox\pageoverlays
+\newbox\commonunderlays
+\newbox\commonoverlays
+
+% In addition to the normal page contents, you can define page overlays
+% and underlays, which are zero-size vboxes positioned absolutely in the
+% front / in the back of the normal material. Also, there are global
+% versions of both which are not reset after every page.
+\def\addlay#1#2{\setbox#1=\vbox{\ifvbox#1\box#1\fi\nointerlineskip\smashedvbox{#2}}}
+\def\pageunderlay{\addlay\pageunderlays}
+\def\pageoverlay{\addlay\pageoverlays}
+\def\commonunderlay{\addlay\commonoverlays}
+\def\commonoverlay{\addlay\commonoverlays}
+
+% Our variation on \plainoutput, which manages inner/outer margins and overlays
+\output{\ucwoutput}
+\newdimen\pagebodydepth
+\def\ucwoutput{\wigglepage\shipout\vbox{%
+ \makeheadline
+ \ifvbox\commonunderlays\copy\commonunderlays\nointerlineskip\fi
+ \ifvbox\pageunderlays\box\pageunderlays\nointerlineskip\fi
+ \pagebody
+ \pagebodydepth=\prevdepth
+ \nointerlineskip
+ \ifvbox\commonoverlays\vbox to 0pt{\vskip -\vsize\copy\commonoverlays\vss}\nointerlineskip\fi
+ \ifvbox\pageoverlays\vbox to 0pt{\vskip -\vsize\box\pageoverlays\vss}\nointerlineskip\fi
+ \prevdepth=\pagebodydepth
+ \makefootline
+}\advancepageno
+\ifnum\outputpenalty>-\@MM \else\dosupereject\fi}
+
+\def\wigglepage{\ifodd\pageno\else\advance\hoffset by \evenpageshift\fi}
+
+% Make it easier to redefine footline font (also, fix it so that OFS won't change it unless asked)
+\let\footfont=\tenrm
+\footline={\hss\footfont\folio\hss}
+
+%%% Itemization %%%
+
+% Usage:
+%
+% \list{style}
+% \:first item
+% \:second item
+% \endlist
+%
+% Available styles (others can be defined by \sdef{item:<style>}{<marker>})
+%
+% o % bullet
+% O % empty circle
+% * % asterisk
+% - % en-dash
+% . % dot
+% n % 1, 2, 3
+% i % i, ii, iii
+% I % I, II, III
+% a % a, b, c
+% A % A, B, C
+% g % α, β, γ
+%
+% Meta-styles (can be used to modify an arbitrary style, currently hard-wired)
+%
+% #. % with a dot behind
+% #) % with a parenthesis behind
+% (#) % enclosed in parentheses
+%
+% Historic usage:
+%
+% \itemize\ibull % or other marker
+% \:first item
+% \:second item
+% \endlist
+%
+% \numlist\ndotted % or other numbering style
+% \:first
+% \:second
+% \endlist
+
+% Default dimensions of itemized lists
+\newdimen\itemindent \itemindent=0.5in
+\newdimen\itemnarrow \itemnarrow=0.5in % make lines narrower by this amount
+\newskip\itemmarkerskip \itemmarkerskip=0.4em % between marker and the item
+\newskip\preitemizeskip \preitemizeskip=3pt plus 2pt minus 1pt % before the list
+\newskip\postitemizeskip \postitemizeskip=3pt plus 2pt minus 1pt % after the list
+\newskip\interitemskip \interitemskip=2pt plus 1pt minus 0.5pt % between two items
+
+% Analogues for nested lists
+\newdimen\nesteditemindent \nesteditemindent=0.25in
+\newdimen\nesteditemnarrow \nesteditemnarrow=0.25in
+\newskip\prenesteditemizeskip \prenesteditemizeskip=0pt
+\newskip\postnesteditemizeskip \postnesteditemizeskip=0pt
+
+\newif\ifitems\itemsfalse
+\newbox\itembox
+\newcount\itemcount
+
+% Penalties
+\newcount\preitemizepenalty \preitemizepenalty=-500
+\newcount\postitemizepenalty \postitemizepenalty=-500
+
+\def\preitemize{
+ \ifitems
+ \vskip\prenesteditemizeskip
+ \advance\leftskip by \nesteditemindent
+ \advance\rightskip by \nesteditemnarrow
+ \else
+ \ifnum\preitemizepenalty=0\else\penalty\preitemizepenalty\fi
+ \vskip\preitemizeskip
+ \advance\leftskip by \itemindent
+ \advance\rightskip by \itemnarrow
+ \fi
+ \parskip=\interitemskip
+}
+
+\def\postitemize{
+ \ifitems
+ \vskip\postnesteditemizeskip
+ \else
+ \ifnum\postitemizepenalty=0\else\penalty\postitemizepenalty\fi
+ \vskip\postitemizeskip
+ \fi
+}
+
+\def\inititemize{\begingroup\preitemize\itemstrue\parindent=0pt}
+
+\def\list#1{\inititemize\itemcount=0\liststyle{#1}\let\:=\listitem}
+\def\listitem{\par\leavevmode\advance\itemcount by 1
+ \llap{\listmarker\hskip\itemmarkerskip}\ignorespaces}
+
+\def\liststyle#1{%
+ \edef\markertmp{#1}
+ \ifcsname item:\markertmp\endcsname
+ \sget\listmarker{item:\markertmp}%
+ \else
+ \sget\listmarker{metaitem:\markertometa#1^^X}%
+ \sget\markerinner{item:\markertoinner#1^^X}%
+ \fi
+}
+
+\def\markertometa#1{%
+ \ifx#1^^X%
+ \else
+ \ifx#1((%
+ \else\ifx#1))%
+ \else\ifx#1..%
+ \else=%
+ \fi\fi\fi
+ \expandafter\markertometa
+ \fi
+}
+
+\def\markertoinner#1{%
+ \ifx#1^^X%
+ \else
+ \ifx#1(%
+ \else\ifx#1)%
+ \else\ifx#1.%
+ \else#1%
+ \fi\fi\fi
+ \expandafter\markertoinner
+ \fi
+}
+
+\def\endlist{\par\endgroup\postitemize}
+
+% List styles
+\sdef{item:o}{\raise0.2ex\hbox{$\bullet$}}
+\sdef{item:O}{\raise0.2ex\hbox{$\circ$}}
+\sdef{item:*}{\raise0.2ex\hbox{$\ast$}}
+\sdef{item:-}{--}
+\sdef{item:.}{\raise0.2ex\hbox{$\cdot$}}
+\sdef{item:n}{\the\itemcount}
+\sdef{item:i}{\romannumeral\itemcount}
+\sdef{item:I}{\uppercase\expandafter{\romannumeral\itemcount}}
+\sdef{item:a}{\char\numexpr 96+\itemcount\relax}
+\sdef{item:A}{\char\numexpr 64+\itemcount\relax}
+\sdef{item:g}{$\ifcase\itemcount\or\alpha\or\beta\or\gamma\or\delta\or\epsilon\or
+\zeta\or\eta\or\theta\or\iota\or\kappa\or\lambda\or\mu\or\nu\or\xi\or\pi\or\rho
+\or\sigma\or\tau\or\upsilon\or\phi\or\chi\or\psi\or\omega\fi$}
+
+% List meta-styles
+\sdef{metaitem:=.}{\markerinner.}
+\sdef{metaitem:=)}{\markerinner)}
+\sdef{metaitem:(=)}{(\markerinner)}
+
+% Old-style lists
+
+\def\itemize#1{\inititemize\setbox\itembox\llap{#1\hskip\itemmarkerskip}%
+\let\:=\singleitem}
+
+\def\singleitem{\par\leavevmode\copy\itembox\ignorespaces}
+
+\def\numlist#1{\inititemize\itemcount=0\let\:=\numbereditem
+\let\itemnumbering=#1}
+
+\def\numbereditem{\par\leavevmode\advance\itemcount by 1
+\llap{\itemnumbering\hskip\itemmarkerskip}\ignorespaces}
+
+% Old-style markers
+
+\def\ibull{\raise0.2ex\hbox{$\bullet$}}
+\def\idot{\raise0.2ex\hbox{$\cdot$}}
+\def\istar{\raise0.2ex\hbox{$\ast$}}
+
+\def\nnorm{\the\itemcount}
+\def\ndotted{\nnorm.}
+\def\nparen{\nnorm)}
+\def\nparenp{(\nnorm)}
+\def\nroman{\romannumeral\itemcount}
+\def\nromanp{\nroman)}
+\def\nalpha{\count@=96\advance\count@ by\itemcount\char\count@)}
+\def\nAlpha{\count@=64\advance\count@ by\itemcount\char\count@)}
+\def\ngreek{$\ifcase\itemcount\or\alpha\or\beta\or\gamma\or\delta\or\epsilon\or
+\zeta\or\eta\or\theta\or\iota\or\kappa\or\lambda\or\mu\or\nu\or\xi\or\pi\or\rho
+\or\sigma\or\tau\or\upsilon\or\phi\or\chi\or\psi\or\omega\fi$)}
+
+%%% Miscellanea %%%
+
+% {\I italic} with automatic italic correction
+\def\I{\it\aftergroup\/}
+
+% A breakable dash, to be repeated on the next line
+\def\={\discretionary{-}{-}{-}}
+
+% Non-breakable identifiers
+\def\<#1>{\leavevmode\hbox{\I #1}}
+
+% Handy shortcuts
+\let\>=\noindent
+\def\\{\hfil\break}
+
+% Variants of \centerline, \leftline and \rightline, which are compatible with
+% verbatim environments and other catcode hacks
+\def\cline{\bgroup\def\linet@mp{\aftergroup\box\aftergroup0\aftergroup\egroup\hss\bgroup\aftergroup\hss\aftergroup\egroup}\afterassignment\linet@mp\setbox0\hbox to \hsize}
+\def\lline{\bgroup\def\linet@mp{\aftergroup\box\aftergroup0\aftergroup\egroup\bgroup\aftergroup\hss\aftergroup\egroup}\afterassignment\linet@mp\setbox0\hbox to \hsize}
+\def\rline{\bgroup\def\linet@mp{\aftergroup\box\aftergroup0\aftergroup\egroup\hss\bgroup\aftergroup\egroup}\afterassignment\linet@mp\setbox0\hbox to \hsize}
+
+% Insert a PDF picture
+% \putimage{width specification}{file}
+\def\putimage#1#2{\hbox{\pdfximage #1{#2}\pdfrefximage\pdflastximage}}
+
+%%% Colors %%%
+
+% Use of pdfTeX color stack:
+% \colorpush\rgb{1 0 0} puts a new color on the stack
+% \colorset\rgb{1 0 0} replaces the top color on the stack
+% \colorpop pops the top color
+% \colorlocal\rgb{1 0 0} set a color locally until the end of the current group
+\chardef\colorstk=\pdfcolorstackinit page direct{0 g 0 G}
+\def\colorset#1{\pdfcolorstack\colorstk set #1}
+\def\colorpush#1{\pdfcolorstack\colorstk push #1}
+\def\colorpop{\pdfcolorstack\colorstk pop}
+\def\colorlocal{\aftergroup\colorpop\colorpush}
+
+% Different ways of describing colors: \rgb{R G B}, \gray{G}, \cmyk{C M Y K}
+% (all components are real numbers between 0 and 1)
+\def\rgb#1{{#1 rg #1 RG}}
+\def\gray#1{{#1 g #1 G}}
+\def\cmyk#1{{#1 k #1 K}}
+
+%%% Localization %%%
+
+% Define a new localized string: \localedef{language}{identifier}{message}
+% (we use \language codes to identify languages)
+\def\localedef#1#2{\tmpcount=#1\expandafter\def\csname loc:\the\tmpcount:#2\endcsname}
+
+% Expand a localized string in the current language: \localemsg{identifier}
+\def\localestr#1{%
+ \ifcsname loc:\the\language:#1\endcsname
+ \csname loc:\the\language:#1\endcsname
+ \else
+ \ucwwarn{Localized string #1 not defined in language \the\language}%
+ ???%
+ \fi
+}
+
+%%% Modules %%%
+
+% Require a module: load it if it is not already loaded
+\def\ucwmodule#1{
+ \ifcsname ucwmod:#1\endcsname
+ \else
+ \input ucw-#1.tex
+ \fi
+}
+
+% Definition of a new module (to be placed at the beginning of its file)
+% (Also guards against repeated loading if somebody uses \input instead of \ucwmodule.)
+\def\ucwdefmodule#1{
+ \ifcsname ucwmod:#1\endcsname\endinput\fi
+ \expandafter\let\csname ucwmod:#1\endcsname=\relax
+}
+
+%%% Epilog %%%
+
+% Let's hide all internal macros
+\catcode`@=12