%% OPmac -- Olsak's PlainTeX macros %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Tech-documentation, Petr Olsak, 2012 \input utf8off \clearmubyte % This file is encoded in ISO-8859-2 because % UTF-8 encTeX has a conflict with DocByTeX \def\projectversion{May 2014} \def\headtitle{OPmac} \widowpenalty=10000 \clubpenalty=10000 \emergencystretch=2em \hbadness=2200 \showboxbreadth=1500 \showboxdepth=2 \def\csplain{\CS plain} \def\CS{CS} \input docby.tex \setlinecomment{\percent} \noactive{\nb\percent} \noactive{\percent\cbrace} \noactive{\nb fontdimen} \title OPmac -- rozšiřující makra plain\TeX{}u \author Petr Olšák \centerline{\ulink[http://www.olsak.net/opmac.html]% {www.olsak.net/opmac.html}} \def\db{\dg\nb} \def\du#1{\api{\nb#1}} \let\quotehook=\langleactive \def\insdef#1 {\ifirst{docby.tex}{def\nb#1 }{^^B\cbrace}{++}} \def\inssdef#1 {\ifirst{docby.tex}{def\nb#1}{\empty}{+-}} \bgroup \catcode`\[=1 \catcode`]=2 \catcode`\{=12 \catcode`\}=12 \gdef\obrace[{] \gdef\cbrace[}] \egroup \def\indexhook{% Tučně je označena strana, kde je slovo dokumentováno, pak následuje seznam všech stran, na kterých se slovo vyskytuje. \medskip} \def\nn#1 {\noactive{\nb#1}} \nn insert \nn undefined \def\cnvbookmark#1{\lowercase{\lowercase{#1}}} \def\bookmarkshook{\lo ěe \lo šs \lo čc \lo řr \lo žz \lo ýy \lo áa \lo íi \lo ée \lo úu \lo ůu \lo óo \lo ňn } \def\lo #1#2{\lccode`#1=`#2} \dotoc \bookmarks \sec Úvod %%%%%%%%% OPmac je balík jednoduchých doplňujících maker k plain\TeX{}u umožňující uživatelům základní La\TeX{}ovou funkcionalitu: změny velikosti písma, automatickou tvorbu obsahu a rejstříku, práci s {\tt bib} databázemi, referencemi, možnost proložení referencí hyperlinkovými odkazy atd. \sec Uživatelská dokumentace %%%%%%%%%%%%%%%%%%%%%%%%%%%% Uživatelská dokumentace je zatím v souboru "opmac-u.tex" a "opmac-u.pdf". Do tohoto místa ji zahrnu později a prolinkuji ji s technickou dokumentací. \sec Technická dokumentace %%%%%%%%%%%%%%%%%%%%%%%%%% Tato část dokumentace je určena pro tvůrce maker, kteří se chtějí zde uvedenými makry inspirovat a případně je přizpůsobit svému požadavku. Předpokládá se znalost \TeX{}u, tj. například aspoň zběžná orientace v~\TeX{}booku naruby. Na tuto knihu je na mnoha místech odkazováno pod zkratkou TBN. \subsec Základní makra %%%%%%%%%%%%%%%%%%%%%% Na začátku souboru "opmac.tex" zjistíme, zda není soubor čtený podruhé. V takovém případě čtení odmítneme. Ptáme se na to, zda je definováno makro \db OPmacversion, které vzápětí definujeme. Je-li někdo překvapen, proč jsem nepoužil "\expandafter\endpinput\fi", může si prostudovat TBN, stranu~358, heslo "\endinput". \ifirst {opmac.tex}{OPmacversion}{\empty}{+-} Dva pracovní registry: \dgn \nb tmpnum \dgn \nb tmpdim \inext {newcount}{\empty}{+-} OPmac nebude nikdy hlásit chyby. Často ale bude psát pomocí \db opwarning na terminál varování. \inext {warning}{\empty}{+-} Makro \db addto "{}" přidá na konec "" dané "". \inext {addto}{\empty}{+-} V OPmac budeme pracovat se seznamem \db protectlist, který bude obsahovat makra, jež chceme mít tzv. robustní, tj. chceme, aby se při "\write" v output rutině neexpandovala. Každému makru v~seznamu předchází "\doprotect", takže seznam "\protectlist" vypadá takto: \def\begtthook{\langleactive} \begtt \doprotect \doprotect ... \endtt \def\begtthook{} Seznam budeme spouštět v output rutině s tím, že "\doprotect" tam bude mít význam makra, které zařídí, aby jeho parametr získal význam "\relax". Tím bude zabráněno jeho expanzi. Naprogramujeme \db addprotect "", které zařídí vložení "" do seznamu. \inext {protectlist}{\empty}{+-} Některá makra budou fungovat jen v pdf\TeX{}u při nastaveném "\pdfoutput=1". Připravíme si tedy test \db ifpdftex, který pak použijeme při čtení souboru "opmac.tex". Test nikdy nebudeme vkládat do maker, takže při čtení souboru "opmac.tex" už musí být jasné, zda bude výstup směrován do DVI nebo PDF. Pozdější změna "\pdfoutput" může způsobit potíže. Xe\TeX{} sice není pdf\TeX, ale po dobu čtení maker jej za pdf\TeX{} budeme považovat a na konci čtení maker (viz sekci~~\ilink[zaver]{\numref[zaver]}) to spravíme. \inext {ifpdftex}{\empty}{+-} Makra \db sdef a \db sxdef umožňují pohodlně definovat kontrolní sekvence ohraničené pomocí "\csname...\endcsname". \inext {sdef}{\empty}{+-} Makro \db adef umožní nastavit znak na aktivní a rovnou ho definovat, což normálně uvnitř maker není jednoduché (TBN str. 25 a 26). Využijeme toho, že "~" je aktivní znak a pomocí "\lccode" a "\lowercase" jej přepíšeme na požadovaný znak. Dostaneme tím aktivní token s požadovanou ASCII hodnotou a tento token definujeme. "\lccode" nastavíme ve skupině, takže po ukončení skupiny se vrací k výchozí hodnotě. \inext {adef}{\empty}{+-} Makrem \db isdefined "{}\iftrue" se ptáme, zda je definovaná "\csname\endcsname". To závěrečné připojené "\iftrue" makro sežere, ale uživatel ho píše zejména z toho důvodu, aby mu tato konstrukce fungovala uvnitř vnořených "\if..\fi" \inext {isdefined}{^^B\cbrace}{++} Makro \db isinlist "{}\iftrue" zjistí, zda "" jsou (jako string) obsaženy v~makru "". Přitom sežere "\iftrue" ze stejných důvodů, jak je uvedeno před chvílí. \inext {isinlist}{^^B\cbrace}{++} Makro \db isnextchar "{}{}" pracuje poněkud odlišně od předchozích maker. Zjistí, zda následující znak je "" a pokud ano, vykoná vnitřek první závorky, jinak vykoná vnitřek druhé závorky. Pomocí "\futurelet" uloží zkoumaný znak do "\next" a spustí \db isnextcharA. \inext {isnextchar}{\empty}{+-} Předefinujeme makro \db uv z \csplain{}u. Tam je toto makro navrženo tak, aby mohlo mít za svůj parametr verbatim text. Důsledkem toho nefunguje správně kerning. Považuji za lepší mít správně kerning a případné uvozování verbatim textů řešit třeba pomocí "\clqq...\crqq". \inext {def\nb uv}{}{+-} Knuth v souboru "plain.tex" zanechal řídicí sekvenci "\\" v provizorním stavu (cvičení: podívejte se v jakém). Domnívám se, že je lepší ji dát jednoznačný význam "\undefined". Některým uživatelům totiž může OPmac připomínat La\TeX{} a není tedy vyloučeno, že je napadne psát "\\". Měli by na to dostat jednoznačnou odpověď: {\tt undefined control sequence}. \inext {undefined}{}{+-} Do pracovního souboru určeného k novému načtení budeme chtít vložit komentáře za znakem procento. K tomu potřebujeme mít procento jako obyčejný znak kategorie 12. Na tento znak se v našem kódu překlopí otazník, Takže \db percent expanduje na znak procento s kategorií 12. \inext {percent}{}{+-} Podobně je naprogramováno makro \db bslash, které vytiskne obyčejné zpětné lomítko: \inext {bslash}{}{+-} Makro plain\TeX{}u "\," funguje jen v matematické sazbě. Uživatel bude chtít makro často použít například mezi číslem a jednotkou v textovém módu: "5\,mm", takže makro předefinujeme. \inext {muskip}{}{+-} Definovaná makra chceme při "\write" do souboru nechat v původním stavu: \inext {addprotect}{}{+-} Makro "\exfont" se vyskytuje v souboru "exchars.tex" z \CS{}plainu. Příkaz "\addprotect\exfont" zaprotektuje všechny znaky deklarované v toto souboru naráz. Podrobnosti lze nalézt v uvedeném souboru. \subsec Globální parametry %%%%%%%%%%%%%%%%%%%%%%%%%% Zakážeme vdovy a sirotky a dále nastavíme registry pro listingy tiskového materiálu na smysluplnější hodnoty, než jsou implicitní. \inext {widowpenalty}{\empty}{+-} Následující makra a registry ovlivní chování klíčových maker OPmac způsobem, jak je popsáno v~komentářích. Mnohé z těchto maker a registrů byly zmíněny v uživatelské dokumentaci. \dgn \nb iindent \dgn \nb ttindent \dgn \nb ttskip \dgn \nb ttpenalty \dgn \nb tthook \dgn \nb intthook \dgn \nb iiskip \dgn \nb bibskip \dgn \nb tabstrut \dgn \nb tabiteml \dgn \nb tabitemr \dgn \nb vvkern \dgn \nb hhkern \dgn \nb multiskip \dgn \nb colsep \dgn \nb mnoteindent \dgn \nb mnotesize \dgn \nb picdir \dgn \nb bibtexhook \dgn \nb chaphook \dgn \nb sechook \dgn \nb secchook \dgn \nb cnvhook \dgn \nb pghook \dgn \nb toclinehook \dgn \nb fnotehook \dgn \nb mnotehook \dgn \nb captionhook \inext {newdimen}{\count=7 \empty}{+-} \subsec Loga %%%%%%%%%%%% V logu \db OPmac je pomocí "\thefontscale" zvětšeno písmeno O. Logo \db CS je přepsáno beze změny z CS\TeX{}u. Tím snadno vytvoříme i logo \db csplain. \inext {def\nb OPmac}{\empty}{+-} Troufám si tvrdit, že logo \db LaTeX (ačkoli je plain\TeX{}isté asi moc nebudou potřebovat) je v~následujícím kódu daleko lépe řešeno, než v samotném La\TeX{}u. Počítá totiž ve spolupráci s makrem \db slantcorr i se sklonem písma při usazování zmenšeného A. \inext {LaTeX}{\empty}{+-} Loga se občas mohou vyskytnout v nadpisech. Zabezpečíme je tedy proti rozboření při zápisu do REF souboru. \inext {addprotect}{\empty}{+-} \subsec Velikosti fontů, řádkování %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \csplain{} od verze "" definuje makro \db resizefont "", které změní velikost fontu daného svým přepínačem a tento změněný font si ponechá stejný přepínač. Změna velikosti je dána obsahem makra \db sizespec. Tam může být například napsáno "at13pt" nebo "scaled800". Dále CSplain definuje makro \db resizeall, které změní velikost fontů s registrovanými přepínači. Registrování se provádí makrem \db regfont. Implicitně jsou registrovány přepínače "\tenrm", "\tenit", "\tenbf", "\tenbi", a "\tentt". Do nových velikostí tedy půjdeme se starými názvy přepínačů "\ten" a to slovo "ten" budeme chápat jen jako historický relikt, který nám ovšem napoví, že kontrolní sekvence je fontovým přepínačem. OPmac si zjistí, zda je definovaný "\regfont". Pokud ne, upozorní na starou verzi \csplain{}u na terminálu a potřebná makra si definuje. Je to kopie kódu ze souboru "csfontsm.tex" z balíčku \csplain{}. \inext {regfont}{\empty}{+-} Makra "\typosize", "\fontsizex", "\textfontsize", "\setbaselineskip" požadují zápis parametru bez jednotky. Jednotkou je \db ptunit, která je nastavena na 1pt. Uživatel může jednotku změnit (např. "\ptunit=1mm" při návrhu plakátu). Dále \db fontdim je registr, který udává aktuální velikost písma. \inext {ptunit}{\empty}{+-} Implicitně jsou zavedeny \CS{}fonty, takže k nim přidáme AMS fonty z "ams-math.tex", které vizuálně odpovídají. Později si může uživatel zavést jiné makro (např. "tx-math.tex") a zavede si třeba i jiné textové fonty. To nezmění vlastnosti maker v OPmac, pokud nové soubory maker správně předefinují makra "\setmathsizes[/