%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Module: Letterspacing Facility % % Synopsis: This module provides a fairly comprehensive letterspacing % facility for ZzTeX. % % Author: Paul C. Anagnostopoulos % Created: 10 July 1997 % % Copyright 1989--2020 by Paul C. Anagnostopoulos % under The MIT License (opensource.org/licenses/MIT) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Letterspacing Commands % ------------- -------- \defineskip{\zlspamount}{0pt} \defineskip{\zlspace}{0pt} \def \letterspace #1#2{% {amount[,space]}{text} {\zlspparse #1,,\zmark \zletterspace{#2}}} \def \eletterspace #1#2{% {amount[,space]}{text} \edef \znext {\noexpand\letterspace{#1}{#2}}% \znext} \def \zlspparse #1,#2,#3\zmark{% \zlspamount = #1\relax \if \emptyargp{#2}% \measurespacewidth{\zlspace}% \advance \zlspace by \zlspamount \else \zlspace = #2\relax \fi} % These commands can be used in letterspaced text, but must do nothing % when letterspacing is not in progress. \let \lsp = \relax \let \nolsp = \relax \def \lspspace {\space}% \def \zlspoff {\relax}% \def \lspoff {\zlspoff}% \def \zlspon {\relax}% \def \lspon {\zlspon}% % Letterspacing Engine % ------------- ------ \def \zletterspace #1{% {text} \def \lsp {\nobreak\hskip \zlspamount}% \def \lspspace {\hskip \zlspace}% \def \zzlspoff {\zlspoff}% \def \zzlspon {\zlspon}% \setflag \zlsping = \true \let \zlspprev = \relax \setflag \zlspprevchar = \false \let \zmark = \relax {\zlspa #1\zmark}} \def \zlspa {\futurelet\zlspcur \zlspb} \def \zlspb {% \let \znext = \zlspc \if \tokeqlp{\zlspcur}{\zmark}% \let \znext = \relax \else\if \cateqlp{\noexpand\zlspcur}{\zspacetoken}% \if \zlsping \aftergroup\lspspace \else \aftergroup\space \fi \else\if \cateqlp{\noexpand\zlspcur}{\bgroup}% \aftergroup{% \else\if \cateqlp{\noexpand\zlspcur}{\egroup}% \aftergroup}% \else\if \tokeqlp{\zlspcur}{\zzlspoff}% \setflag \zlsping = \false \else\if \tokeqlp{\zlspcur}{\zzlspon}% \setflag \zlsping = \true \else \let \znext = \zlspd \fi\fi\fi\fi\fi\fi \znext} \def \zlspc {% Discard current token. \let \zlspprev = \zlspcur \setflag \zlspprevchar = \false \afterassignment\zlspa \let\zlspcur = } \long\def \zlspd #1{% Process current token. \let \zlspprev = \zlspcur \if \cateqlp{\noexpand#1}{\relax}% \setflag \zlspprevchar = \false \aftergroup#1% \else\if \cateqlp{\noexpand#1}{\noexpand~}% \setflag \zlspprevchar = \false \if \zlsping \aftergroup\lspspace \else \aftergroup\space \fi \else\if \orp{\andp{\codeeqlp{\zlspprev}{-}}{\codeeqlp{\zlspcur}{-}}} {\orp{\andp{\codeeqlp{\zlspprev}{`}}{\codeeqlp{\zlspcur}{`}}} {\andp{\codeeqlp{\zlspprev}{'}}{\codeeqlp{\zlspcur}{'}}}}% \setflag \zlspprevchar = \true \aftergroup#1% \else \if \andp{\zlspprevchar}{\zlsping}\aftergroup\lsp \fi \setflag \zlspprevchar = \true \aftergroup#1% \fi\fi\fi \zlspa}