% \iffalse %<*copyright> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% aeb_mlink.sty package, %% %% Copyright (C) 2006--2020 D. P. Story %% %% dpstory@acrotex.net %% %% %% %% This program can redistributed and/or modified under %% %% the terms of the LaTeX Project Public License %% %% Distributed from CTAN archives in directory %% %% macros/latex/base/lppl.txt; either version 1.2 of %% %% the License, or (at your option) any later version. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % %\NeedsTeXFormat{LaTeX2e} %\ProvidesPackage{aeb_mlink} % [2020/07/12 v2.3.6 AeB MLink (dps)] %<*driver> \documentclass{ltxdoc} \usepackage{xcolor} \usepackage[colorlinks,hyperindex=false,pdfpagemode=UseNone]{hyperref} \let\bWebCustomize\endinput \usepackage{aeb_mlink} \pdfstringdefDisableCommands{\let\\\textbackslash}% \OnlyDescription % comment out for implementation details \EnableCrossrefs \CodelineIndex \RecordChanges \InputIfFileExists{aebdocfmt.def}{\PackageInfo{web}{Inputting aebdocfmt.def}} {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax \PackageInfo{web}{aebdocfmt.def cannot be found}} \begin{document} \def\CMD#1{\textbackslash#1} \let\pkg\textsf \let\env\texttt \let\opt\texttt \let\app\textsf \def\visispace{\symbol{32}} \def\ameta#1{\ensuremath{\langle\textit{\texttt{#1}}\rangle}} \def\meta#1{\textsl{\texttt{#1}}} \def\SUB#1{\ensuremath{{}_{\mbox{\scriptsize\ttfamily#1}}}} \def\darg#1{\texttt{\char123\relax#1\char125\relax}} \addtolength{\marginparwidth}{3pt} \GetFileInfo{aeb_mlink.sty} \title{The \textsf{aeb\_mlink} Package\texorpdfstring{\\}{: } A member of the AeB Pro family} \author{D. P. Story\\ Email: \texttt{dpstory@uakron.edu}} \date{processed \today} \maketitle \tableofcontents \DocInput{aeb_mlink.dtx} \IfFileExists{\jobname.ind}{\newpage\setupFullwidth\par\PrintIndex} {\paragraph*{Index} The index goes here. Execute \[\texttt{makeindex -s gind.ist -o aeb\_mlink.ind aeb\_mlink.idx}\] on the command line and recompile \texttt{web.dtx}.} \IfFileExists{\jobname.gls}{\PrintChanges} {\paragraph*{Change History} The list of changes goes here. Execute \[\texttt{makeindex -s gglo.ist -o aeb\_mlink.gls aeb\_mlink.glo}\] on the command line and recompile \texttt{aeb\_mlink.dtx}.} \end{document} % % \fi % \MakeShortVerb{|} % \InputIfFileExists{aebdonotindex.def}{\PackageInfo{web}{Inputting aebdonotindex.def}} % {\PackageInfo{aeb_mlink}{cannot find aebdonotindex.def}} % % \section{Introduction} % This package creates \underbar{m}ultiline-\underbar{links}. % The package \textsf{hyperref} does create links, but generally % these links cannot be broken across lines, unless \textsf{pdflatex} % is used to create a PDF. % % This package uses the \texttt{QuadPoints} entry in the link annotation to create % a bounding region; consequently, this package requires \textbf{Acrobat Distiller} % to create a PDF. \texttt{QuadPoints} is a PDF 1.6 feature, so these multiline links % will work in Adobe Reader 7.0 or later. If viewed in a version of Adobe Reader previous % to 7.0, the viewer will use the underlying bounding box. % % LaTeX package requirements are the \textsf{eForms} and \textsf{hyperref}. Only the use % of \textsf{dvips} and \textsf{dvipsone} is supported. % %The key to creating a multi-line is contained in Table~8.24 of the %PDF Reference. The description of \texttt{QuadPoints} in the PDF Reference %is as follows: % %\begin{quote}\small %(Optional; PDF 1.6) An array of $8 \times n$ numbers specifying the %coordinates of $n$ quadrilaterals in default user space that comprise %the region in which the link should be activated. The coordinates %for each quadrilateral are given in the order %$$ % x_1\ y_1\ x_2\ y_2\ x_3\ y_3\ x_4\ y_4 %$$ %specifying the four vertices of the quadrilateral in %counterclockwise order. For orientation purposes, such as when %applying an underline border style, the bottom of a quadrilateral is %the line formed by $(x_1 , y_1)$ and $(x_2 , y_2)$. If this entry is not %present or the viewer application does not recognize it, the region %specified by the \texttt{Rect} entry should be used. \texttt{QuadPoints} should be %ignored if any coordinate in the array lies outside the region %specified by \texttt{Rect}. %\end{quote} % \begin{macrocode} % \end{macrocode} % \section{The \texorpdfstring{\protect\pkg{aeb-mlink}}{aeb-mlink} Package} % The \pkg{aeb\_mlink} package is listed on CTAN as \pkg{aeb-mlink}; there was, in % fact, no \pkg{aeb-mlink}. Here, we provide a `dummy' package by that name which % passes everything on to \pkg{aeb\_mlink}. % \begin{macrocode} % Begin Alt pkg %<*altpkgname> \NeedsTeXFormat{LaTeX2e} \RequirePackage{xkeyval} \ProvidesPackage{aeb-mlink} [2018/04/26 v1.0 AeB MLink Alt-name (dps)] \DeclareOptionX*{\PassOptionsToPackage{\CurrentOption}{aeb_mlink}} \ProcessOptionsX \RequirePackage{aeb_mlink}[2018/08/18] % % \end{macrocode} % \section{Package Requirements and Options} % After having established the alternate of this package, we now work on the package itself. % \changes{v2.3}{2018/04/26}{Added \string\pkg{aeb-mlink} as an alternate name for this package} % \changes{v2.3.6}{2020/07/12}{Added some safeguards against using a driver other than dvips} % \begin{macrocode} % Begin Package %<*package> \RequirePackage{xkeyval} \RequirePackage{ifpdf}[2006/02/20] \RequirePackage{ifxetex}[2006/08/21] % \end{macrocode} % (2020/07/12) We test for non-pdfmark drivers, if present, we make minimal % package definitions, define all relevant commands to display their \ameta{text} % argument. In this way, \app{pdflatex}, \app{lualatex}, and \app{xelatex} can be used % to preview the document, perhaps viewing the results in \app{SumatraPDF}. % \begin{macrocode} \ifpdf \let\ML@action\endinput \else \ifxetex \let\ML@action\endinput \else \let\ML@action\relax \fi \fi \ifx\ML@action\endinput % \end{macrocode} % \paragraph*{Begin the minimal version of the package.} Designed for when % a non-pdfmark driver is used: \texttt{latex\,->\,dvips\,->\ameta{\upshape{distiller\string|ps2pdf}}} % \begin{macrocode} \RequirePackage{hyperref} %\RequirePackage{refcount} \RequirePackage{eforms}[2018/08/16] % \end{macrocode} % Make all commands of this package to do nothing other % then to reproduce their \ameta{text} argument. % \begin{macrocode} \@ifundefined{mlhypertext}{\newcommand}{\renewcommand}% \mlhypertext[2][]{#2} \newcommand\mlhyperlink[3][]{#3} \newcommand\mlhyperref[3][]{#3} \newcommand\mlNameref[2][]{#2} \newcommand\mlnameref[2][]{#2} \newcommand\mlhref[3][]{#3} \newcommand\mlurl[2][]{\expandafter\Hurl\expandafter{#2}} \let\mlMarksOn\relax \let\mlMarksOff\relax \let\turnSyllbCntOn\relax \let\turnSyllbCntOff\relax \def\mlcs#1{\texttt{\@backslashchar#1}} \def\mlMaxNSylls{30} \PackageWarningNoLine{aeb_mlink} {PDF creation requires Adobe Distiller.\MessageBreak Workflow is latex > dvips > distiller; otherwise,\MessageBreak this package does nothing} \fi \ML@action % \endinput or \relax % \end{macrocode} % \paragraph*{Begin the pdfmark version of the package}\leavevmode\\[6pt] % Set the driver for \texttt{dvips} % \begin{macrocode} \newif\if@ml@dvips \@ml@dvipstrue \def\mlcsarg#1#2{\expandafter#1\csname#2\endcsname} % \end{macrocode} % \leavevmode\IndexOpt{dvipsone}^^A % Set the driver for \texttt{dvipsone} % \begin{macrocode} \DeclareOptionX{dvipsone}{\def\eq@drivernum{0}\@ml@dvipsfalse \PassOptionsToPackage{dvipsone}{eforms} \PassOptionsToPackage{dvipsone}{hyperref} } % \end{macrocode} % \leavevmode\IndexOpt{dvips}^^A % Set the driver for \texttt{dvips}% % \begin{macrocode} \DeclareOptionX{dvips}{\def\eq@drivernum{0}\@ml@dvipstrue \PassOptionsToPackage{dvips}{eforms} \PassOptionsToPackage{dvips}{hyperref} } % \end{macrocode} % \leavevmode\IndexOpt{urlOpts}^^A % The options of the \pkg{url} package may be passed through the value of this key; % for example, |urlOpts={hyphens}|. % \changes{v2.3.5}{2020/01/06}{Added \string\opt{urlOpts}} % \begin{macrocode} \define@key{aeb_mlink.sty}{urlOpts}[]{\def\url@Opts{[#1]}} \let\url@Opts\@empty % \end{macrocode} % Undefined options are passed to \pkg{eforms}. % \begin{macrocode} \DeclareOptionX*{\PassOptionsToPackage{\CurrentOption}{eforms}} % \end{macrocode} % \leavevmode\IndexOpt{dblevel}^^A % Sets the debug level. % \begin{macrocode} \@ifundefined{mldblevel}{\newcount\mldblevel\mldblevel=0 }{} \define@key{aeb_mlink.sty}{dblevel}[0]{\mldblevel=#1 } % \end{macrocode} % Package error message when not dvips (or dvispone) % \begin{macrocode} \def\ml@err@msg{This package requires the driver dvips and\MessageBreak Adobe Distiller as the PDF creator} % \end{macrocode} % (2020/01/06) Conform to the new \texttt{web.cfg} format. % \changes{v2.3.5}{2020/01/06}{Conform to the new \string\texttt{web.cfg} format} % \begin{macrocode} \let\bWebCustomize\endinput \let\eWebCustomize\relax \ifpdf\PackageError{aeb_mlink}{\ml@err@msg}\else \ifxetex\PackageError{aeb_mlink}{\ml@err@msg}\else \let\ExecuteOptions@SAVE\ExecuteOptions \let\ExecuteOptions\ExecuteOptionsX \InputIfFileExists{web.cfg}{} {\@ifundefined{l@tex@@@@driver}{\ExecuteOptionsX{dvips}} {\ExecuteOptionsX{dvipsone}}}% \let\ExecuteOptions\ExecuteOptions@SAVE \fi\fi % \end{macrocode} % (2020/01/06) Now require \pkg{url} package and pass % options to \pkg{url} through \opt{urlOpts}. % \changes{v2.3.5}{2020/01/06}{Now require \string\pkg{url} package and pass % options to \string\pkg{url} through \string\opt{urlOpts}} % \begin{macrocode} \ProcessOptionsX \expandafter\RequirePackage\url@Opts{url} % \end{macrocode} % We require hyperref, eforms and soul. For eforms, a recent version is needed, % \texttt{2008/03/14} or later. % \begin{macrocode} \RequirePackage{hyperref} \RequirePackage{refcount} % \end{macrocode} % Beginning with the version of \pkg{eforms} dated 2018/03/22 or later, there are several % link options that are defined. These are \cs{mlfix}, \cs{mlstrut}, \cs{mlcrackat} and % \cs{mlhyph}. % \begin{macrocode} \RequirePackage{eforms}[2018/08/16] \RequirePackage{soul} % \end{macrocode} % % \section{Driver Dependent Code} % % Driver dependent definitions for dvipsone and dvips. % \begin{macrocode} \def\ps@mark{[\space} \ifnum\mldblevel>0 \def\mlpgMsg{(\string\n Beginning of page: ) pf PhysicalPage 20 string cvs pf(\string\n)pf}\else \def\mlpgMsg{}\fi \def\pgmonitoring{\if@ml@dvips dup /PhysicalPage exch 1 add def /PhysicalPage PhysicalPage def^^J\fi \mlpgMsg } % \end{macrocode} % Redefining \cs{mllnkcontainer}, defined in \pkg{eforms} % dated 2018/03/14 or later. If \cs{ifoldstylequads} is true, % we do not set \texttt{/Rect} to the minimal rectangle, rather % it is set to the region defining the whole page. This was % the default rectangle in the past. % \begin{macrocode} \def\smallRectTF{\ifoldstylequads false\else \iffixmlinks true\else false\fi\fi\space \ifSmallRect true\else false\fi\space and} \def\ml@@nnotName{mLink} % dps \def\mllnkcontainer#1{bCreateLink { xoMsgB { \smallRectTF\space mlRectFix^^J% #1}if}{(\ml@@nnotName\the\aeb@mLinkCnt) mlIsBldMsg}ifelse} % \end{macrocode} % \cs{pboxRect} is defined in \pkg{eforms} % \begin{macrocode} \def\pboxRect{mlRect } \if@ml@dvips % \end{macrocode} % \textsf{\textbf{dvips} driver:} Code for the \textsf{dvips} driver % This next \cs{special} defines some standard conversion % formulas, {\TeX} to PDF and PDF to {\TeX} for \textsf{dvips}. % \begin{macrocode} \def\mlDict{SDict} \special{!userdict begin /TeXtoPDF {65536 div DVImag mul} def % sp to pts /PDFtoDvips {72.27 div Resolution mul} def % points to dots /PDFtoVDvips {72.27 div VResolution mul} def % points to dots /DvipstoPDF {72.27 mul Resolution div} def % dots to points /HTeXtoDvips {TeXtoPDF PDFtoDvips} def % sp to dots /VTeXtoDvips {TeXtoPDF PDFtoVDvips} def^^J% % sp to dots /PhysicalPage 0 def^^J% /PageHeight {vsize} def^^J% /PDFtoTeX {PDFtoDvips} def^^J% /pf{print flush}def^^J% /bop-hook{ \pgmonitoring\space } def end} % \end{macrocode} % This command calculates the \cs{QuadPoints} array % when we are using the \textsf{dvips} driver. % \begin{macrocode} \def\setQuadBox{% currentpoint DvipstoPDF \aeb@bbox@dp\space TeXtoPDF add neg vsize add 72 sub % y1 exch DvipstoPDF 72 add exch % x1 2 copy exch \aeb@bbox@wd\space TeXtoPDF add exch % x2 2 copy \aeb@bbox@ht\space TeXtoPDF add % y3 2 copy exch \aeb@bbox@wd\space TeXtoPDF sub exch % x4 } % \end{macrocode} % For the bounding rectangle, we just enclose the entire page. This % simplifies things greatly. % \begin{macrocode} \def\par@@Rect {% 72 neg PDFtoDvips vsize 72 sub PDFtoVDvips hsize 72 sub PDFtoDvips 72 neg PDFtoVDvips } % \end{macrocode} % \textsf{\textbf{dvipsone} driver:} Code for the \textsf{dvipsone} driver % This next \cs{special} defines some standard conversion % formulas, {\TeX} to PDF and PDF to {\TeX} in the \textsf{YandY {\TeX} System}. % \begin{macrocode} \else \def\mlDict{dvidict} \special{!/TeXtoPDF {65536 div mag 1000 div mul} def /PDFtoTeX {65536 mul mag 1000 div div} def^^J% /pf{print flush}def^^J% /bphook{ \pgmonitoring\space } def^^J% } % \end{macrocode} % This command calculates the \cs{QuadPoints} array % when we are using the \textsf{dvipsone} driver. % \begin{macrocode} \def\setQuadBox{% currentpoint \aeb@bbox@dp\space add TeXtoPDF neg PageHeight add 72 sub % y1 exch TeXtoPDF 72 add exch % x1 2 copy exch \aeb@bbox@wd\space TeXtoPDF add exch % x2 2 copy \aeb@bbox@ht\space TeXtoPDF add % y3 2 copy exch \aeb@bbox@wd\space TeXtoPDF sub exch % x4 } % \end{macrocode} % For the bounding rectangle, we just enclose the entire page. This % simplifies things greatly. % \begin{macrocode} \def\par@@Rect {% 72 neg PDFtoTeX PageHeight 72 sub PDFtoTeX PageWidth 72 sub PDFtoTeX 72 neg PDFtoTeX } \fi % \end{macrocode} % % \section{The Multi-line Linking Commands} % % We use a box, and two counters for this package. % \begin{macrocode} \newbox\aeb@bbox \newcount\aeb@arrayIndx \aeb@arrayIndx=0 \newcount\aeb@mLinkCnt \aeb@mLinkCnt=0 \newcount\syllableCnt \syllableCnt=0 \newif\ifmllinktotalchanged\mllinktotalchangedfalse % \end{macrocode} % When \cs{ifSmallRect} is true (the default), the smallest possible \texttt{Rect} % is constructed to enclose the text; obeyed only when \cs{iffixmlinks} (defined in \pkg{eforms} % is true. % \begin{macrocode} \newif\ifSmallRect \SmallRecttrue \AtEndDocument{\wrtmlinktot@l\ckchngmlinktot@l\wrt@linksnotformed} \def\wrt@linksnotformed{\iflinknotformed \PackageWarningNoLine{aeb_mlink}{Some link calculations are not complete.\MessageBreak DO NOT CONVERT TO PDF at this time. Compile at \MessageBreak least twice more}\fi} \def\wrtmlinktot@l{\immediate\write\@auxout{\string\gdef \string\mlinkstotal{\the\aeb@mLinkCnt}}} \def\ckchngmlinktot@l{\@ifundefined{mlinkstotal}{} {\ml@mlinktot@l@changed}} \def\ml@mlinktot@l@changed{% \ifnum\mlinkstotal=\the\aeb@mLinkCnt\relax\else \PackageWarningNoLine{aeb_mlink}{The number of links has changed. Compile again\MessageBreak until this message does not appear}\immediate \write\@auxout{\string\mllinktotalchangedtrue}\fi } \def\ml@mllinktotalchanged{\ifmllinktotalchanged \PackageWarningNoLine{aeb_mlink} {The number of links has changed, continue\MessageBreak to compile}\fi} \AtBeginDocument{\ml@mllinktotalchanged} \def\CurrentBorderColor{\@linkbordercolor} \def\ml@nocolorHighlight{I} \def\ml@nocolorLineStyle{S} \def\ml@nocolorLineWidth{1} \def\ml@setnocolorDefaults{% \def\ml@nocolor@defaults{\H{\ml@nocolorHighlight}% \S{\ml@nocolorLineStyle}\W{\ml@nocolorLineWidth}% \Color{\CurrentBorderColor}}% } \ifHy@colorlinks \let\ml@nocolor@defaults\@empty \else \ml@setnocolorDefaults \fi \def\ml@earlyExecProps#1{% \eq@setWidgetProps\relax{#1}% } % \end{macrocode} % The new scheme of fixing up the quad points write information % to the AUX file, which then requires multiple compilations to bring % that information up to date in the document. When working on document % development, you can declare \cs{OldStyleBoxesOn} in the preamble to revert % to the old style boxes that do not require AUX info. %\changes{v2.1.3}{2018/03/10}{Reinstate old style link} % \begin{macrocode} \newif\ifoldstylequads \oldstylequadsfalse \def\OldStyleBoxesOn{\mlfixOff\oldstylequadstrue} \def\OldStyleBoxesOff{\oldstylequadsfalse} \@onlypreamble\OldStyleBoxesOn \@onlypreamble\OldStyleBoxesOff \let\mlh@preambleCmdInsert\relax \def\mlcs#1{\texttt{\@backslashchar#1}} \bgroup\@makeother\% \gdef\CMT#1{ %\space #1}\egroup \def\mldbModeOn{\def\mldb##1##2{##2}} \def\mldbModeOff{\def\mldb##1##2{}} \def\mldb#1#2{\ifnum#1<\mldblevel#2\fi} \def\ml@adj@x{2}\def\ml@adj@y{2} \def\mlMaxNSylls{30} % usage \mlcrackinsat{\removelastspace} \def\removelastspace{\hskip-\fontdimen2\font} \AtBeginDvi{\special{!% % \end{macrocode} % \paragraph*{Begin Postscript code} This code is executed as the PDF is created % by either \app{Adobe Distiller} (preferred) or \app{ps2pdf}. Information is % written to the \app{distiller} (\app{ps2pdf}) log.\medskip\par % % {\noindent}A switch to determine if the link should be created or now; it may not be % fully formed. % \begin{macrocode} /bCreateLink true def % \end{macrocode} % The length of the arrays we deal with are multiples of eight (8), we use a value % of 17 as a way of testing whether an array size has been updated. All arrays % are set to 17 in length initially. % \begin{macrocode} /mlIsBld 17 def^^J% /mlIsBldMsg {^^J% /sName exch def^^J% (\string\n!! )pf sName 20 string cvs pf ( is not completely formed, compile again!!\string\n)pf^^J% } def^^J% /xoMsgB true def^^J% /xoMsg {^^J% /Indx exch def^^J% /sName exch def^^J% /nSyllable Indx 8 div def^^J% dpsa08 (!!------------------------------------------------------------------% \string\n Warning:\string\n The text of )pf sName 20 string cvs pf ( has crossed a page boundary from page )pf PhysicalPage 1 sub 10 string cvs pf ( to ) pf PhysicalPage 10 string cvs pf sName 0 1 getinterval (m) eq { (.\string\n Cross page links are not supported by the PDF Specification)pf (.\string\n This link is not constructed, please fix it.\string\n)pf (Break point is after syllable number )pf nSyllable cvi 20 string cvs pf (.\string\n)pf (Use the \string\\mlcrackat{)pf nSyllable cvi 20 string cvs pf (} option with this link.\string\n)pf }{ (.\string\n Cross page annotations are not supported by the PDF Specification)pf (.\string\n This annotation is not constructed, please fix it.\string\n)pf (Break point is after syllable number )pf nSyllable cvi 20 string cvs pf (.\string\n)pf (Use the mlcrackat=)pf nSyllable cvi 20 string cvs pf ( option with this annotation.\string\n)pf } ifelse (!!------------------------------------------------------------------% \string\n)pf^^J% } def^^J% % \end{macrocode} % quadpointsfixup is the major procedure for combining all `rectangles' that are on % the same line. % \begin{macrocode} /quadpointsfixup {^^J% /ary exch def^^J% /quadL exch def^^J% /sName exch def^^J% \mldb0{(Processing )pf sName pf (: OK\string\n)pf^^J}% %\mldb0{lnkCnt 20 string cvs pf (: OK\string\n) pf^^J}% quadL 0 eq { (Problems with this link, length=0, will skip the creation of this link)pf^^J% }{ % \end{macrocode} % Begin by defining some variables needed for this operation. % \begin{macrocode} /gOffset 0 def^^J% % \end{macrocode} % \texttt{gY} holds the y-coordinate of the lower-left corner of the first entry % of a quad. We use it and others like it to determine at which syllable the line % is broken. % \begin{macrocode} /gY ary\space 1 gOffset add get def^^J% \mldb1{(gY is ) pf gY 20 string cvs print^^J}% \mldb1{flush (\string\n) pf^^J}% /gN 0 def^^J% % \end{macrocode} % \texttt{gMrk} is an array that will load the offsets into \texttt{mLinkFxup\ameta{num}}. Each % offset is the beginning of a line. We initially set the length of the array to 10, though % this may not be correct. That is, we assume the hypertext will not exceed 10 lines in length. % \begin{macrocode} /gMrk 10 array def^^J% limitation % \end{macrocode} % The first entry is always 0, because marks the location of the quad corresponding to the % beginning of the first syllable. % \begin{macrocode} gMrk 0 0 put^^J% % \end{macrocode} % \texttt{gMrkL} is the length of the array, we set it to 1, as we've already inserted % the first entry into \texttt{gMrkL}. % \begin{macrocode} /gMrkL 1 gOffset add def^^J% \mldb2{(Begin first for\string\n) pf^^J}% % \end{macrocode} % Begin a for loop\marginpar{\raggedleft for loop}. The purpose of this loop is to search % through the quad points of \texttt{mLinkFxup\ameta{num}} and find the offsets into the % structure where the line breaks occur. % \begin{macrocode} 0 8 quadL 8 sub {^^J% % \end{macrocode} % \texttt{gIndx} is the loop counter, which we use below. Since we are dealing % with quads, we increment by 8 each time. % \begin{macrocode} /gIndx exch def^^J% \mldb2{(Outside gt if with gIndx=) pf^^J}% \mldb2{gIndx 20 string cvs pf^^J}% \mldb2{(\string\n) pf^^J}% % \end{macrocode} % \texttt{getEntry} is the y-coordinate of the lower-left corner of the % quad we are currently examining. We will compare its value to that % of \cs{gY}. % \begin{macrocode} /getEntry ary\space 1 gOffset add get def^^J% \mldb2{(getEntry=) pf getEntry 20 string cvs pf^^J}% \mldb2{(\string\n) pf^^J}% % \end{macrocode} % Here's where we compare \texttt{gY} with \texttt{getEntry}. If they differ % by more than 2 points then the line has changed. (We do it this way since these % are decimal numbers and they may have been rounded in unpredictable ways.\marginpar{\raggedleft if comparison} % \begin{macrocode} gY getEntry sub abs 2 gt {^^J% \mldb2{(Inside gt if\string\n) pf^^J}% % \end{macrocode} % The two entries differ, so a line break must have occurred. We inert value % of \texttt{gIndx} into \texttt{gMrk}. \texttt{gIndx} is essentially the offset % into \texttt{mLinkFxup\ameta{num}} where the line break occurs. % \begin{macrocode} gMrk gMrkL gIndx put^^J% % \end{macrocode} % Increment \texttt{gMrkL} accordingly. % \begin{macrocode} /gMrkL gMrkL 1 add def^^J% % \end{macrocode} % Place the new y-value in \texttt{gY} before we look back % and look for another line break. % \begin{macrocode} /gY getEntry def^^J% \mldb2{(Updating gY to )pf gY 20 string cvs pf^^J}% \mldb2{(\string\n) pf^^J}% \mldb2{(gMrkL=)pf gMrkL 20 string cvs pf^^J}% \mldb2{(\string\n) pf^^J}% % \end{macrocode} % End of the if\marginpar{\raggedleft end if} % \begin{macrocode} } if^^J% /gOffset gOffset 8 add def^^J% % \end{macrocode} % End of the for loop\marginpar{\raggedleft end for} % \begin{macrocode} } for^^J% \mldb2{(end first for\string\n) pf^^J}% % \end{macrocode} % We finished searching for line breaks and are now going to work on combining % contiguous quads. Contiguous quads are the ones between the offsets recorded % in the \texttt{gMrk} array. Now, if there are now line breaks, the length % of \texttt{gMrk} is one. % % \texttt{gAry} is a temporary array that holds all the quads \emph{corresponding to % one line}. Each syllable generates an quad of length 8. Here, we assume any given % line has at most \cs{mlMaxNSylls} syllables, (currently set to \cs{mlMaxNSylls}, % but may be revised). The array \texttt{gAry} is declared % inside the next loop, so it is redeclared at each iteration of the loop. If \app{Distiller} of \app{ps2pdf} % fails, it may be due to \cs{mlMaxNSylls} being too small for some of your sentences; in this case, redefine % \cs{mlMaxNSylls} to a larger value. % \changes{v2.3.2}{2018/08/09}{\string\cs{mlMaxNSylls} now sets the array size of gAryL} % \begin{macrocode} /gAryL 8 \mlMaxNSylls\space mul def^^J% limitation \mldb2{(gAryL=) pf gAryL 20 string cvs pf^^J}% \mldb2{(\string\n)pf^^J}% % \end{macrocode} % \texttt{gFixup} is an array that will hold the final combined quad points, this array % is the one that will be referenced by the \texttt{QuadPoints} entry of the link annotation. % It's length is set to 8 times the number of lines over which the hypertext is broken (\texttt{gMrkL}) % One quad for each line, rather than many quads, one for each syllable. % \begin{macrocode} /gFixup 8 gMrkL mul array def^^J% links /aFixup 8 gMrkL mul array def^^J% text markup annotations /gOffset 0 def^^J% \mldb2{(for loop: gMrkL=)pf gMrkL 20 string cvs pf^^J}% \mldb2{(\string\n) pf^^J}% % \end{macrocode} % The last loop. In this loop, for each line of hypertext, % we build its contiguous quad and load it into \texttt{gFixup}.\marginpar{\raggedleft begin for} % \begin{macrocode} 0 1 gMrkL 1 sub {^^J% \mldb2{(After gAry\string\n) pf^^J}% \mldb2{(Top of for loop\string\n) pf^^J}% /gIndx exch def^^J% \mldb2{(gIndx=)pf gIndx 20 string cvs pf^^J}% \mldb2{(\string\n)pf^^J}% \mldb2{(gMrk=)pf gMrk gIndx get 20 string cvs pf^^J}% \mldb2{(\string\n) pf^^J}% \mldb2{(mLinkFxup length = )^^J}% \mldb2{pf ary\space length 20 string cvs^^J}% \mldb2{pf (\string\n) pf^^J}% % \end{macrocode} % We need to determine if we are examining the quads for the last line, or not. % The calculation of \texttt{gCount} is dependent on this. % \begin{macrocode} gIndx 1 add gMrkL eq {^^J% /gCount ary\space length gMrk gIndx get sub def^^J% }{^^J% /gCount gMrk gIndx 1 add get gMrk gIndx get sub def^^J% } ifelse^^J% % \end{macrocode} % Declare the \texttt{gAry} array % \begin{macrocode} /gAry gAryL array def^^J% \mldb2{(gCount=)pf gCount 20 string cvs pf^^J}% \mldb2{(\string\n)pf^^J}% % \end{macrocode} % We want to copy a slice of \texttt{mLinkFxup\ameta{num}}, we declare the next % array of length \texttt{gCount} just computed. % \begin{macrocode} /sliceOfLinkfxup gCount array def^^J% % \end{macrocode} % Populate this array with a slice of \texttt{mLinkFxup\ameta{num}} beginning at % \texttt{gMrk[gIndx]} and including the subsequent \texttt{gCount} entries. % array of length \texttt{gCount} just computed. % \begin{macrocode} sliceOfLinkfxup 0 ary gMrk gIndx get^^J% gCount getinterval putinterval^^J% gAry 0 sliceOfLinkfxup putinterval^^J% \mldb1{(Listing elements of gFixup\string\n) pf^^J}% \mldb1{gAry 0 get 20 string cvs pf (\string\n)pf^^J}% \mldb1{gAry 1 get 20 string cvs pf (\string\n)pf^^J}% \mldb1{gAry gCount 1 sub 5 sub get 20 string cvs pf (\string\n)pf^^J}% \mldb1{gAry gCount 1 sub 4 sub get 20 string cvs pf (\string\n)pf^^J}% \mldb1{gAry gCount 1 sub 3 sub get 20 string cvs pf (\string\n)pf^^J}% \mldb1{gAry gCount 1 sub 2 sub get 20 string cvs pf (\string\n)pf^^J}% \mldb1{gAry 6 get 20 string cvs pf (\string\n)pf^^J}% \mldb1{gAry 7 get 20 string cvs pf (\string\n)pf^^J}% gFixup gOffset [^^J% gAry 0 get ^^J% x1 ll 1 gAry 1 get^^J% y1 ll 1 gAry gCount 1 sub 5 sub get^^J% x2 lr 2 gAry gCount 1 sub 4 sub get^^J% y2 lr 2 gAry gCount 1 sub 3 sub get^^J% x3 ur 3 gAry gCount 1 sub 2 sub get^^J% y3 ur 3 gAry 6 get^^J% x4 ul 4 gAry 7 get^^J% y4 ul 4 ] putinterval^^J% % \end{macrocode} % When forming quad points for text markup annotations, the PDF reference is not followed. We have % to reorder the array \texttt{gFixup} to conform to how Acrobat/Reader expect it. Entries 0 and 4 % are increased by the same amount that was subtracted out earlier in % \changes{v2.3.2}{2018/08/09}{Form the array \string\texttt{aFixup} for \string\pkg{aeb\_mlink}} % \begin{macrocode} aFixup gOffset [^^J% gAry 6 get gOffset 0 eq {\ml@adj@x\space add}if^^J% x4 ul 4 gAry 7 get^^J% y4 ul 4 gAry gCount 1 sub 3 sub get^^J% x3 ur 3 gAry gCount 1 sub 2 sub get^^J% y3 ur 3 gAry 0 get gOffset 0 eq {\ml@adj@x\space add}if^^J% x1 ll 1 gAry 1 get 1 sub^^J% y1 ll 1 gAry gCount 1 sub 5 sub get^^J% x2 lr 2 gAry gCount 1 sub 4 sub get 1 sub^^J% y2 lr 2 ] putinterval^^J% /gOffset gOffset 8 add def^^J% } for^^J% \mldb2{(End of second for\string\n) pf^^J}% } ifelse } def^^J% % \end{macrocode} % \texttt{smallquadpointsfixup} fixes up the bounding boxes. Raises their heights % by \cs{ml@adj@y} (removed), and moves the left boundary \cs{ml@adj@x} to the left. % \changes{v2.1.2}{2018/03/09}{Added PS proc \string\texttt{smallquadpointsfixup}} % \begin{macrocode} /smallquadpointsfixup {^^J% /gIndx exch def^^J% /ary exch def^^J% /lnkCnt exch def^^J% /quadL exch def^^J% /gSFup 8 array def^^J% gSFup 0 ary 0 gIndx add get gIndx 0 eq {\ml@adj@x\space sub} if put^^J% x1 gSFup 1 ary 1 gIndx add get put^^J% y1 gSFup 2 ary 2 gIndx add get put^^J% x2 gSFup 3 ary 3 gIndx add get put^^J% y2 gSFup 4 ary 4 gIndx add get put^^J% x3 gSFup 5 ary 5 gIndx add get put^^J% gSFup 6 ary 6 gIndx add get gIndx 0 eq {\ml@adj@x\space sub} if put^^J% x4 gSFup 7 ary 7 gIndx add get put^^J% ary gIndx gSFup putinterval^^J% } def^^J% % \end{macrocode} % The \texttt{mlRectFix} procedure creates the minimum sized rectangle % that encloses the text, and we use this as the dimensions of \texttt{/Rect} % \changes{v2.1.10}{2018/03/25}{Set \string\texttt{/Rect} to minimal rectangle containing text} % \begin{macrocode} /mlRectFix {^^J% /ifRectFix exch def^^J% ifRectFix { /nL gFixup length 8 sub def^^J% number of lines /xMin gFixup 0 get def^^J% 0 8 nL {^^J% /Indx exch def^^J% gFixup Indx get xMin lt {/xMin gFixup Indx get def}if } for^^J% /xMin xMin 2 sub def^^J% /xMax gFixup 2 get def^^J% 2 8 nL 2 add {^^J% /Indx exch def^^J% gFixup Indx get xMax gt {/xMax gFixup Indx get def}if } for^^J% /xMax xMax 2 add def^^J% /yMin gFixup 1 get def^^J% 1 8 nL 1 add {^^J% /Indx exch def^^J% gFixup Indx get yMin lt {/yMin gFixup Indx get def}if } for^^J% /yMin yMin 4 sub def^^J% /yMax gFixup 5 get def^^J% 5 8 nL 5 add{^^J% /Indx exch def^^J% gFixup Indx get yMax gt {/yMax gFixup Indx get def}if } for^^J% /yMax yMax 2 add def^^J% /mlRect {/Rect [^^J% xMin 72 sub PDFtoTeX^^J% PageHeight 72 sub yMax sub PDFtoTeX^^J% xMax 72 sub PDFtoTeX^^J% PageHeight yMin sub 72 sub PDFtoTeX ]^^J% }def^^J% }{^^J% /mlRect{/Rect [ \par@@Rect ] }def^^J% }ifelse^^J% ifRectFix { \mldb1{(/Rect [)pf^^J% xMin 20 string cvs pf( )pf^^J% yMax 20 string cvs pf( )pf^^J% xMax 20 string cvs pf( )pf^^J% yMin 20 string cvs pf(]\string\n)pf^^J}% } if^^J% } def }} % \end{macrocode} % \DescribeMacro{\mlMarksOn} % Added tracking marks. Turn them on with \cs{mlMarksOn} and off again % with \DescribeMacro{\mlMarksOff}\cs{mlMarksOff}. % \changes{v2.1.8}{2018/03/19}{Added tracking marks} % \begin{macrocode} \newif\ifmlmarks\mlmarksfalse \def\mlMarksOn{\mlmarkstrue} \def\mlMarksOff{\mlmarksfalse} % \end{macrocode} % \leavevmode\DescribeMacro{\ml@MrkLnk}\hskip-\marginparsep\darg{\ameta{num}} % The internal command \cs{ml@MrkLnk} typesets the tracking mark; it may be redefined. % When the link is within a \env{tabular} environment (and perhaps others), in this case, % \cs{baselineskip=0pt}. We raise instead the height of the capital letter `T', % plus a little. % \changes{v2.1.9}{2018/03/22}{Changed the definition of \cs{ml@MrkLnk}} % \begin{macrocode} \def\MrkLnkLtr{L} \def\ml@MrkLnk#1{\ifmlmarks\bgroup\ifdim\baselineskip=0pt \setbox\z@\hbox{T}\gdef\ml@raiseamt{\ht\z@+.4pt}\else \gdef\ml@raiseamt{.6\baselineskip}\fi\smash{\rlap{\normalfont \normalcolor\bfseries \raisebox{\ml@raiseamt}{\tiny\strut{\MrkLnkLtr#1}}}}\egroup\fi} \newif\iflinknotformed \linknotformedfalse \newif\ifcr@ckit \cr@ckitfalse \def\ml@underlinded{U} % \end{macrocode} % \begin{macro}{\mlhypertext} % \leavevmode\hskip-\marginparsep\texttt{[\ameta{opts}]\darg{\ameta{text}}} % This is a general purpose hypertext link. Not only is it % a fine stand-alone linking command, but it also serves % as a building block to some convenience commends that follow. % % The commands takes two arguments, the first an optional one the second % one requires. % \begin{enumerate} % \item[\texttt{\ameta{opts}}] (Optional) A standard optional argument for \pkg{eforms} to change % the appearance of the link and/or to include actions. % \item[\texttt{\ameta{text}}] The text to be enclosed by the link. % \end{enumerate} % The most recently, \pkg{eforms} defines \cs{mlhypertext} to a warning % message. So if \cs{mlhypertext} is already defined, we \cs{renewcommand} % else we \cs{newcommand}. % \changes{v2.1.17}{2018/04/19}{added conditional command definition for \string\cs{mlhypertext}} % \changes{v2.3.1}{2018/07/18}{added \string\cs{hglue0pt} to add some hard glue just before % the beginning of \string\cs{mlhypertext}} % \begin{macrocode} \@ifundefined{mlhypertext}{\newcommand}{\renewcommand}% {\mlhypertext}[2][]{\hglue0pt\begingroup \global\ml@displaytrue \toks@=\expandafter{#2}% \edef\ml@HytextArg{{\the\toks@}}% \global\aeb@arrayIndx=\z@ \def\ml@setlink##1{\setLinkPbox{% \QuadPoints{mLink##1}#1}}% \expandafter\processAppArgs\set@LinkPboxDefaults \presets{\ml@nocolor@defaults}\S{S}\W{0}#1\end\@nil \ifx\eq@S@value\ml@underlinded \let\itsunderline\ef@YES\else\let\itsunderline\ef@NO\fi % \end{macrocode} % Now we test whether \cs{eq@mlcrackat} is empty or not. If not-empty % we break this link to two parts. % \begin{macrocode} \ifx\eq@mlignore\ef@YES \global\advance\aeb@mLinkCnt\@ne\relax \def\ml@next{\mlhypertext@i{#1}}\else \ifx\eq@mlcrackat\@empty % \end{macrocode} % A `normal' link, continue % \begin{macrocode} \global\advance\aeb@mLinkCnt\@ne\relax \def\ml@next{\mlhypertext@i{#1}}% \else % \eq@mlcrackat not \@empty % \end{macrocode} % \textbf{Crack it up.} We define \cs{ml@next} to call \cs{mlhypertext} consecutively; % the first time we specify |\mlignore{0}| to indicate this link % is the first part, and then |mlignore{1}| to indicate the second part. % For the first part, we proceed as usual until we get the the syllable % number specified by \cs{mlcrackAt}, then we continue with the next % \cs{mlhypertext} command, we remove all content up to the syllable number % \cs{mlcrackAt}, and typeset the rest; for example, %\begin{quote} %This is a test sentence that \textcolor{gray}{we want to break across pages.} (1)\\ %\textcolor{gray}{This is a test sentence that} we want to break across pages. (2) %\end{quote} %The first link produces the typeset material in (1), where grayed-out text are removed; while %the second link produces line (2), again, with the grayed-out material removed. % \begin{macrocode} \def\ml@next{\global\ml@displaytrue\let\ml@space\space \mlhypertext[#1\mlignore{0}]{#2}\eq@mlcrackinsat \penalty-100 \cr@ckittrue \global\ml@displayfalse\let\ml@space\space \mlhypertext[#1\mlignore{1}]{#2}\aftergroup \normalcolor\endgroup}% \fi \fi \ml@next } \def\mlhypertext@i#1{% \@ifundefined{mLinkLngth\the\aeb@mLinkCnt}{\global \linknotformedtrue\def\ml@lngth{17}} {\edef\ml@lngth{\@nameuse{mLinkLngth\the\aeb@mLinkCnt}}}% \ml@start@link{\the\aeb@mLinkCnt}{\ml@lngth}% Step 1 \def\mlh@preambleCmdInsert{% \ml@MrkLnk{\the\aeb@mLinkCnt}\ml@earlyExecProps{#1}}% \def\mlh@postambleCmd{\endgroup}% % \end{macrocode} % Start \pkg{soul} on \cs{mlhypertext} (\cs{aeb@mlh}) % \begin{macrocode} \expandafter\aeb@mlh\ml@HytextArg \ml@finish@link{\the\aeb@mLinkCnt}{\ml@lngth}% \ml@setlink{\the\aeb@mLinkCnt}% \ifoldstylequads\else \iffixmlinks\literalps@out{restore}\fi\fi \@ifundefined{mLinkLngth\the\aeb@mLinkCnt}{% \immediate\write\@auxout{\string\mlcsarg \string\gdef{mLinkLngth\the\aeb@mLinkCnt}{17}}% }{\immediate\write\@auxout{\string\mlcsarg \string\gdef{mLinkLngth\the\aeb@mLinkCnt}% {\the\aeb@arrayIndx}}}\endgroup } \def\mlh@setQuadSyllable#1#2#3#4{% % #1 = current array Index % #2 = quad total % #3 = link cnt % #4 = content \setbox\aeb@bbox=\hbox{\ml@strut#4}% {% \setbox\@tempboxa\hbox{\ml@strut}% \ifx\itsunderline\ef@YES\@tempdima1bp\relax\else \@tempdima\dp\@tempboxa \ifdim\@tempdima>2bp \advance\@tempdima-2bp\fi \fi \ifx\isstrikeout\ef@YES\advance\@tempdima-2bp\fi \dp\aeb@bbox\@tempdima \@tempdima\ht\@tempboxa \advance\@tempdima\dp\aeb@bbox \advance\@tempdima1bp \ht\aeb@bbox\@tempdima\def\x{\the\count\z@}% \count\z@=\ht\aeb@bbox\xdef\aeb@bbox@ht{\x}% \count\z@=\wd\aeb@bbox\xdef\aeb@bbox@wd{\x}% \count\z@=\dp\aeb@bbox\xdef\aeb@bbox@dp{\x}% }% \ifoldstylequads \literalps@out{% bCreateLink {^^J% \mlDict\space/mLinkFxup#3\space known {^^J% \ps@mark{mLink#3} \the\aeb@arrayIndx\space [\setQuadBox] \space /PUTINTERVAL pdfmark}{^^J% xoMsgB { /xoMsgB false def (\ml@@nnotName\the\aeb@arrayIndx) #3\space xoMsg % dpsa08 } if^^J% xoMsgB } ifelse } if }% \else \literalps@out{% bCreateLink {^^J% \mlDict\space/mLinkFxup#3\space known {^^J% mLinkFxup#3\space #1\space[\setQuadBox] putinterval^^J% % \end{macrocode} % Initiate fix up of little rectangles % \begin{macrocode} #2\space % #3\space mLinkFxup#3\space #1\space smallquadpointsfixup }{^^J% xoMsgB { /xoMsgB false def (\ml@@nnotName#3) #1\space xoMsg % dpsa08 } if^^J% xoMsgB } ifelse } if }% \fi \global\advance\aeb@arrayIndx8\relax } % \end{macrocode} % \end{macro} % The next four commands are used internally, though \cs{aebnameref}, % \cs{labelRef} and \cs{atPage} are public, and can be used. % \begin{macrocode} \def\aeb@exiii{\expandafter\expandafter\expandafter} \def\aebnameref#1{\@ifundefined{r@#1}{??} {\aeb@exiii\@thirdoffive\csname r@#1\endcsname}} \def\labelRef#1{\@ifundefined{r@#1}{Doc-Start} {\aeb@exiii\@fourthoffive\csname r@#1\endcsname}} \def\atPage#1{\getrefbykeydefault{#1}{page}{??}} % \end{macrocode} % \begin{macro}{\mlhyperlink} % \begin{macro}{\mlhyperref} % \begin{macro}{\mlnameref} % \begin{macro}{\mlNameref} % These four commands mimic the \pkg{hyperref} commands of the same root name. % The commands \cs{mlhyperlink} and \cs{mlhyperref} take three % parameters (the first one optional). The optional parameter % modifies the appearance of the link, the second is the % target/destination of the link, the third is the text the link is % wrapped around. In the case of \cs{mlhyperlink} that target is a % defined by \cs{hypertarget}; for \cs{mlhyperref} the target is a % latex label. % % The commands \cs{mlnameref} and \cs{mlNameref} take two parameters % (the first is optional). As before, the first modifies the % appearance of the link, the second is the target, a latex label. %\begin{flushleft} % Syntax: \ttfamily\string\mlhyperlink[\ameta{opts}]\darg{\ameta{named-dest}}\darg{\ameta{text}} %\end{flushleft} % \begin{macrocode} \newcommand\mlhyperlink[3][]{% \mlhypertext[#1\A{/S/GoTo/D (#2)}]{#3}} % \end{macrocode} %\begin{flushleft} % Syntax: \ttfamily\string\mlhyperref[\ameta{opts}]\darg{\ameta{label}}\darg{\ameta{text}} %\end{flushleft} % \begin{macrocode} \newcommand\mlhyperref[3][]{% \mlhypertext[#1\A{/S/GoTo/D (\labelRef{#2})}]{#3}} % \end{macrocode} %\begin{flushleft} % Syntax: \ttfamily\string\mlnameref[\ameta{opts}]\darg{\ameta{label}} %\end{flushleft} % \begin{macrocode} \newcommand\mlnameref[2][]{\protected@edef\ml@temp{\aebnameref{#2}}% \def\ml@tempi{\mlhypertext[#1\A{/S/GoTo/D (\labelRef{#2})}]}% \expandafter\ml@tempi\expandafter{\ml@temp}} % \end{macrocode} % We use a work around to a |\relax| problem encountered in the % |\mlNameRef| command. {\LaTeX} inserts a |relax| at the end of label % titles, which stops soul. We insert |\let\SOUL@stop\ml@SOUL@stop|, % this seems to work, no guarantees. %\begin{flushleft} % Syntax: \ttfamily\string\mlNameref[\ameta{opts}]\darg{\ameta{label}} %\end{flushleft} % \begin{macrocode} \newcommand\mlNameref[2][]{\let\SOUL@stop\ml@SOUL@stop \protected@edef\ml@temp{`\aebnameref{#2}' on page~\atPage{#2}}% \def\ml@tempi{\mlhypertext[#1\A{/S/GoTo/D (\labelRef{#2})}]}% \expandafter\ml@tempi\expandafter{\ml@temp}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % The next three commands are modifications some low \pkg{hyperref} commands % found in the \texttt{pdfmark.def} file. Depending on the parsing, \cs{href} % calls one of these three; we intercept them, and insert % our own command \cs{mlhypertext} so the link string gets wrapped around % if needed. These are in preparation for the definition of \cs{mlhref}. % \begin{macrocode} \def\ml@hyper@linkurl#1#2{\hyper@chars \let\ef@thislinkcolor\@urlcolor \let\CurrentBorderColor\@urlbordercolor \mlhypertext[\presets{\mlhref@args}\A{/S/URI/URI(#2)}]{#1}% \endgroup } \def\ml@hyper@linkfile#1#2#3{% \let\ef@thislinkcolor\@filecolor \let\CurrentBorderColor\@filebordercolor \ifx\@pdfstartview\@empty \def\theView{[0 /Fit]}\else \def\theView{[0 \@pdfstartview]}\fi \@ifundefined{ifHy@pdfnewwindow} {\ifHy@newwindow}{\ifHy@pdfnewwindow}% \def\isWindow{/NewWindow true}\else \let\isWindow\@empty\fi \mlhypertext[\presets{\mlhref@args}\A{/S/GoToR \isWindow /F (#2) /D \ifx\\#3\\\theView\else(#3)\fi}]{#1}% \endgroup } \def\ml@hyper@launch run:#1\\#2#3{% \let\ef@thislinkcolor\@filecolor \let\CurrentBorderColor\@runbordercolor \@ifundefined{ifHy@pdfnewwindow} {\ifHy@newwindow}{\ifHy@pdfnewwindow}% \def\isWindow{/NewWindow true}\else \let\isWindow\@empty\fi \mlhypertext[\presets{\mlhref@args}\A{/S/Launch\isWindow /F (#1) \ifx\\#3\\\else /Win << /P (#3) /F (#1) >> \fi}]{#2}% \endgroup } % \end{macrocode} % Below is the code for \cs{mlhref}. We first let the old commands found in \texttt{pdfmark.def} % equal to the new versions, then we call \cs{href} to do all the parsing. Things % eventually comes back to the above three commands. % \begin{macrocode} \let\aeb@saved@href\href % \end{macrocode} % \begin{macro}{\mlhref} % This command is similar to \cs{href}. This command also takes % three arguments, one optional. The first is usual optional argument % that allow one to modify the appearance of the link, the second one % is the URL that we are linking to, the third is the text that we are % wrapping this link around. %\begin{flushleft} % Syntax: \ttfamily\string\mlhref[\ameta{opts}]\darg{\ameta{url}}\darg{\ameta{text}} %\end{flushleft} % \begin{macrocode} \newcommand{\mlhref}[1][]{% \begingroup \def\mlhref@args{#1}% \let\hyper@linkurl\ml@hyper@linkurl \let\hyper@linkfile\ml@hyper@linkfile \let\@hyper@launch\ml@hyper@launch \aeb@saved@href } % \end{macrocode} % \end{macro} % \begin{macro}{\mlurl} % The multi-line version of Donald Arseneau's url package. There % are problems with this one, will continue to work on it. % \changes{v2.0}{2016/02/16}{Added support for the \cs{url} command.} % % The problem is not as ``easy'' as the previous cases. Arseneau places the URL in math mode % and it does not reconstruct (\texttt{soul} terminology) as it should. Our solution is to % hijack three commands of \texttt{soul}, these are \cs{SOUL@doword}, \cs{SOUL@analyze}, and \cs{SOUL@dosyllable}, % and modify them to do the work on an URL. % \begin{macrocode} \newbox\ml@urlbuildi \newbox\ml@urlbuildii % \end{macrocode} % We modify \cs{SOUL@doword} and name it \cs{ml@SOUL@doword}. % \begin{macrocode} \def\ml@SOUL@doword{% \global\setbox\ml@urlbuildi\hbox{}% \global\setbox\ml@urlbuildii\hbox{}% \edef\x{\the\SOUL@word}% \ifx\x\empty \else \SOUL@buffer={}% \setbox\z@\vbox{% \SOUL@tt \hyphenchar\font`\- \hfuzz\maxdimen \hbadness\@M \pretolerance\m@ne \tolerance\@M \leftskip\z@ \rightskip\z@ \hsize1sp \everypar{}% \parfillskip\z@\@plus1fil \hyphenpenalty-\@M \noindent \hskip\z@ \relax \the\SOUL@word}% % \end{macrocode} % We don't do the reconstruction, so no need for the message. % \begin{macrocode} \let\SOUL@errmsg\relax % \let\SOUL@errmsg\SOUL@error \let\-\relax \count@\m@ne % \end{macrocode} % Here is the first major change, rather than splitting off to \cs{SOUL@analyze}, we go % to our modified version, \cs{ml@SOUL@analyze}. % \begin{macrocode} \ml@SOUL@analyze \SOUL@word={}% \fi } % \end{macrocode} % We modify \cs{SOUL@analyze} and name it \cs{ml@SOUL@analyze}. % \begin{macrocode} \def\ml@SOUL@analyze{{% \setbox\z@\vbox{% \unvcopy\z@ \unskip \unpenalty \global\setbox\@ne=\lastbox}% \ifvoid\@ne \else % \end{macrocode} % We encapsulate our changes at this point in \cs{ml@interface@analyze} % \begin{macrocode} \ml@interface@analyze \SOUL@syllgoal=\wd\@ne \advance\count@\@ne % \end{macrocode} % We get the tokens recursively, but we jump back to \cs{ml@SOUL@analyze} not % \cs{SOUL@analyze}. % \begin{macrocode} \ml@SOUL@analyze \SOUL@syllwidth\z@ \SOUL@syllable={}% \ifnum\count@>\z@ \advance\SOUL@syllgoal-\SOUL@ttwidth % \end{macrocode} % At this point, we jump to \cs{ml@SOUL@dosyllable} rather than % \cs{SOUL@dosyllable}. % \begin{macrocode} \ml@SOUL@dosyllable \SOUL@getkern{\the\SOUL@lasttoken}{\SOUL@hyphkern}% {\SOUL@sethyphenchar}% \SOUL@everyhyphen \else % \end{macrocode} % Use \cs{ml@SOUL@dosyllable} not \cs{SOUL@dosyllable}. % \begin{macrocode} \ml@SOUL@dosyllable \fi \fi }} % \end{macrocode} % % \begin{macrocode} \newif\ifml@display \ml@displaytrue % \end{macrocode} % We modify \cs{SOUL@dosyllable} and name it \cs{ml@SOUL@dosyllable}. % \begin{macrocode} \def\ml@SOUL@dosyllable{% \SOUL@gettoken \SOUL@eventuallyexhyphen{\the\SOUL@token}% \edef\x{\the\SOUL@token}% \ifx\x\SOUL@hyphenhintM \let\SOUL@n\ml@SOUL@dosyllable \else\ifx\x\SOUL@lowerthanM \SOUL@gettoken \SOUL@getkern{\the\SOUL@lasttoken}{\SOUL@charkern} {\the\SOUL@token}% \SOUL@everylowerthan \SOUL@puttoken \let\SOUL@n\ml@SOUL@dosyllable \else\ifdim\SOUL@syllwidth=\SOUL@syllgoal \SOUL@everysyllable \SOUL@puttoken \let\SOUL@n\relax \else \ifx\x\SOUL@stopM \SOUL@errmsg \global\let\SOUL@errmsg\relax \let\SOUL@n\relax \else \setbox\tw@\hbox{\SOUL@tt\the\SOUL@token}% \advance\SOUL@syllwidth\wd\tw@ \global\SOUL@lasttoken=\SOUL@token \SOUL@gettoken \SOUL@getkern{\the\SOUL@lasttoken}{\SOUL@charkern} {\the\SOUL@token}% \SOUL@puttoken \global\SOUL@token=\SOUL@lasttoken \SOUL@everytoken \edef\x{\SOUL@syllable={\the\SOUL@syllable\the\SOUL@token}}\x % \end{macrocode} % Here is the only change, we direct flow back to \cs{ml@SOUL@dosyllable} % \begin{macrocode} \let\SOUL@n\ml@SOUL@dosyllable \fi\fi\fi\fi \SOUL@n } % \end{macrocode} % We put most of our changes to \cs{ml@SOUL@analyze} in % \DescribeMacro{\ml@interface@analyze}\cs{ml@interface@analyze} % \begin{macrocode} \def\ml@interface@analyze{% \global\advance\syllableCnt\@ne % dpsa11 \setbox\@ne\hbox{\unhbox\@ne}% % \end{macrocode} % If we say \verb!\mlurl{http://www.math.uakron.edu/~dpstory}!, then the \cs{box\cs{z@}} above contains % the following tokens, listed at their breakpoints:\goodbreak % \begin{flushleft} % \texttt{http:}\\ % \texttt{\string\\}\\ % \texttt{www.}\\ % \texttt{math.}\\ % \texttt{uakron.}\\ % \texttt{edu/}\\ % \texttt{\string~dpstory} % \end{flushleft} % The idea is to get each of these using \verb~\global\setbox\@ne=\lastbox~ (bottom to top) % and to build the URL with the quad points calculated. Each new token is added in front % of the URL as we build it. Results are held in \cs{ml@urlbuild}. We insert \cs{penalty0} to % promote a break point between components, as each component is enclosed in an \cs{hbox} now. % \begin{macrocode} % \end{macrocode} % We'll try cracking the url here, if requested. % \begin{macrocode} \ifx\eq@mlcrackat\@empty % \end{macrocode} % Ordinary link, we don't crack it apart, continue with the old code. % \begin{macrocode} \ml@bld@quadchunks{\the\aeb@mLinkCnt} {\ml@qlngthchunki}{\ml@urlbuildi}% \else \ifnum\syllableCnt=\revCrackAt\relax % \end{macrocode} % Everything is in reverse order, this is the last syllable of the first chunk % \begin{macrocode} \aeb@arrayIndx=\z@ % \end{macrocode} % start first link % \begin{macrocode} \ml@start@link{\the\aeb@mLinkCnt}{\ml@qlngthchunki}% \ml@bld@quadchunks{\the\aeb@mLinkCnt} {\ml@qlngthchunki}{\ml@urlbuildi}% \else % \end{macrocode} % Continue with first link % \begin{macrocode} \ifnum\syllableCnt>\revCrackAt\relax \ml@bld@quadchunks{\the\aeb@mLinkCnt} {\ml@qlngthchunki}{\ml@urlbuildi}% \else \ifnum\syllableCnt=\@ne % \end{macrocode} % start second link % \begin{macrocode} \aeb@arrayIndx=\z@ % \end{macrocode} % Everything is in reverse order, this is the last syllable of the second chunk % \begin{macrocode} \ml@start@link{\aeb@mLinkCnt@}{\ml@qlngthchunkii}% \ml@bld@quadchunks{\aeb@mLinkCnt@} {\ml@qlngthchunkii}{\ml@urlbuildii}% \else % \end{macrocode} % continue with second link % \begin{macrocode} \ml@bld@quadchunks{\aeb@mLinkCnt@} {\ml@qlngthchunkii}{\ml@urlbuildii}% \fi \fi \fi \fi } \def\ml@bld@quadchunks#1#2#3{{% % #1 = link cnt % #2 = chunk size % #3 = \ml@urlbuild to i or ii \@ifundefined{mLinkLngth\the\aeb@mLinkCnt} {\edef\@indx{\the\aeb@arrayIndx}} {\@tempcnta#2\relax \advance\@tempcnta-8\relax \advance\@tempcnta-\aeb@arrayIndx \def\@indx{\the\@tempcnta}% }% \@tempcntb=\@indx \divide\@tempcntb by 8 \advance\@tempcntb by 1 \ifx#3\ml@urlbuildii \advance\@tempcntb by \eq@mlcrackat\relax\fi \global\setbox#3=\hbox{% \mlh@setQuadSyllable{\@indx}{#2}{#1}{\unhcopy\@ne}% \hbox{\unhcopy\@ne}\relax \ml@typeset@@syl{\@tempcntb}\penalty0\unhcopy#3}%hbox }} % \end{macrocode} % After the above preliminaries, we finally define \DescribeMacro{\mlurl}\cmd{\mlurl}. %\begin{flushleft} % Syntax: \ttfamily\string\mlurl[\ameta{opts}]\darg{\ameta{url}} %\end{flushleft} % \begin{macrocode} \newcommand{\mlurl}{\begingroup\@makeother\~\relax% \def~{\string~}% \ef@sanitize@toks\mlurl@} % \end{macrocode} % After sanitizing, we save the URL (\texttt{\#2}) an a macro % \cs{ml@url} using the \cs{urldef} command, defined in the \textsf{url} package. % \begin{macrocode} \newcommand{\mlurl@}[2][]{\@ifundefined{ef@thislinkcolor} {\let\ef@thislinkcolor\normalcolor}{}\expandafter \def\expandafter\ef@thislinkcolor@SAVE \expandafter{\ef@thislinkcolor}% \def\ml@setlink##1{\setLinkPbox{\A{\URI{#2}}% \QuadPoints{mLink##1}#1}}% % \end{macrocode} % We get the link options early to determine if this link is to % be underlined. % \begin{macrocode} \expandafter\processAppArgs\set@LinkPboxDefaults \presets{\ml@nocolor@defaults}\S{S}\W{0}#1\end\@nil \ifx\eq@S@value\ml@underlinded \let\itsunderline\ef@YES\else\let\itsunderline\ef@NO\fi % \end{macrocode} % \cs{ml@url} is the specified url to create a link around % \begin{macrocode} \global\aeb@arrayIndx=0\relax \global\syllableCnt=0\relax \global\advance\aeb@mLinkCnt\@ne\relax % \end{macrocode} % \begin{macrocode} \@ifundefined{mLinkLngth\the\aeb@mLinkCnt}{% \global\linknotformedtrue\def\ml@lngth{17}% \def\ml@qlngthchunki{17}} {\@tempcnta\@nameuse{mLinkLngth\the\aeb@mLinkCnt}\relax \edef\ml@lngth{\the\@tempcnta}%\multiply\@tempcnta8\relax \edef\ml@qlngthchunki{\the\@tempcnta}}% % \end{macrocode} % We make some calculations in preparation to a link that will be % cracked apart. % \cs{mlM@XCNT} is the number of syllables of the un-cracked URL. % \begin{macrocode} \@ifundefined{mLinkSyCnt\the\aeb@mLinkCnt} {\def\mlM@XCNT{0}\def\ml@lngthchunki{0}\def\ml@lngthchunkii{0}% \def\ml@qlngthchunki{0}\def\ml@qlngthchunkii{0}\def\revCrackAt{0}} {\edef\mlM@XCNT{\@nameuse{mLinkSyCnt\the\aeb@mLinkCnt}}% % \end{macrocode} % When \cs{mlM@XCNT} is known, and \cs{eq@mlcrackat} is known, we can calculate % the number of syllables of each chunk of the URL, for the first chunk, it is % \cs{eq@mlcrackat}, for the second it is $\cs{mlM@XCNT} - \cs{eq@mlcrackat}$. % \begin{macrocode} \ifx\eq@mlcrackat\@empty\else \@tempcnta\mlM@XCNT\relax\advance\@tempcnta-\eq@mlcrackat\relax \edef\ml@lngthchunki{\eq@mlcrackat}% \edef\ml@lngthchunkii{\the\@tempcnta}% \@tempcnta\ml@lngthchunki\relax\multiply\@tempcnta8\relax \edef\ml@qlngthchunki{\the\@tempcnta}% \@tempcnta\ml@lngthchunkii\relax\multiply\@tempcnta8\relax \edef\ml@qlngthchunkii{\the\@tempcnta}% % \end{macrocode} % We take these chunks off in reverse order so we measure each from the end of the url. % This calculation can be move to earlier code where it is not executed for each syllable (chunk). % \cs{revCrackAt} is the value of \cs{eq@mlcrackat} as measure from the end of the url. % \begin{macrocode} \@tempcnta\mlM@XCNT\relax \advance\@tempcnta-\eq@mlcrackat\relax \advance\@tempcnta\@ne \edef\revCrackAt{\the\@tempcnta}% \fi}% \@tempcnta\aeb@mLinkCnt\advance\@tempcnta\@ne \edef\aeb@mLinkCnt@{\the\@tempcnta}% \urldef\ml@url\nolinkurl{#2}% \def\SOUL@mlhpreamble{%\begingroup \mlh@preambleCmdInsert\ef@colorthislink}\hyper@chars \let\ef@thislinkcolor\@urlcolor \let\CurrentBorderColor\@urlbordercolor % \end{macrocode} % Within this group, we direct the \pkg{soul} package to our customized versions of the % commands. % \begin{macrocode} \let\ml@SOUL@doword@SAVE\SOUL@doword \let\SOUL@doword\ml@SOUL@doword % \end{macrocode} % The next several lines are taken from the definition of \cs{mlhypertext}, the basic command % for construction many of the `\cs{ml}' commands of this package. % \begin{macrocode} \ifx\eq@mlcrackat\@empty \ml@start@link{\the\aeb@mLinkCnt}{\ml@lngth}\fi \def\mlh@preambleCmdInsert{\ml@MrkLnk{\the\aeb@mLinkCnt}% \ml@earlyExecProps{#1}}% \def\mlh@postambleCmd{% \expandafter % \end{macrocode} % The coloring of the hypertext does not work unless we make the definition % global, so we do so and hope this does not mess other things up. % \changes{v2.0.1}{2017/09/19}{Save the incoming link color} % Save the incoming link color so we can globally change it. % After the link is formed, change it back again. % \begin{macrocode} \def\expandafter\ef@thislinkcolor \expandafter{\ef@thislinkcolor}}% % \end{macrocode} % Finally, we call \cs{aeb@mlh} which starts \textsf{soul} with \cs{SOUL@}. % This does this analysis, the custom command build the url in \cs{ml@urlbuild}, which % we then unbox. % \begin{macrocode} \aeb@mlh\ml@url\ef@colorthislink\unhcopy\ml@urlbuildi \expandafter\gdef\expandafter\ef@thislinkcolor \expandafter{\ef@thislinkcolor@SAVE}% \immediate\write\@auxout{\string\mlcsarg\string \gdef{mLinkSyCnt\the\aeb@mLinkCnt}{\the\syllableCnt}}% dpsa11 \immediate\write\@auxout{\string\mlcsarg \string\gdef{mLinkLngth\the\aeb@mLinkCnt}{\the\aeb@arrayIndx}}% \ifx\eq@mlcrackat\@empty \ml@finish@link{\the\aeb@mLinkCnt}{\ml@lngth}% \ml@setlink{\the\aeb@mLinkCnt}% \iffixmlinks\literalps@out{restore}\fi \else \ml@finish@link{\the\aeb@mLinkCnt}{\ml@qlngthchunki}% \ml@setlink{\the\aeb@mLinkCnt}% \iffixmlinks\literalps@out{restore}\fi \eq@mlcrackinsat\penalty-100 \ml@start@link{\aeb@mLinkCnt@}{\ml@qlngthchunkii}% \penalty0\@ifundefined{mLinkLngth\the\aeb@mLinkCnt}{} {\ml@MrkLnk{\aeb@mLinkCnt@}}\unhcopy\ml@urlbuildii \ml@finish@link{\aeb@mLinkCnt@}{\ml@qlngthchunkii}% \ml@setlink{\aeb@mLinkCnt@}\iffixmlinks \literalps@out{restore}\fi \global\advance\aeb@mLinkCnt\@ne \fi\aftergroup\normalcolor\endgroup } \def\ml@start@link#1#2{% Step 1 % #1=link number % #2 = final quad length \literalps@out{% /xoMsgB true def^^J% \ps@mark/_objdef {mLink#1}% /type /array /OBJ pdfmark^^J% \ifoldstylequads /mLinkFxup#1\space0 array def \else /bCreateLink mlIsBld #2\space eq not def^^J% bCreateLink{ /mLinkFxup#1\space #2\space array def }if \fi }% } % \end{macrocode} % Make \texttt{gFixup} into a macro, so other packages (\pkg{aeb\_mlink} can intercept and insert % its own procedure here. % \changes{v2.3.2}{2018/08/09}{We make \string\texttt{gFixup} into a macro name \string\cs{FixupProc}} % \begin{macrocode} \def\FixupProc{gFixup} \def\ml@finish@link#1#2{% Step 4 and 5 % #1=link number % #2 = final quad length \ifoldstylequads\else \ifnum\aeb@arrayIndx=0\relax \PackageWarning{aeb_mlink}{% Problem with mLink\the\aeb@mLinkCnt, Will skip the \MessageBreak creation of this link}\fi \literalps@out{% % \end{macrocode} % If \cs{iffixmlinks} is true, we fix the links, otherwise, we no not. % \begin{macrocode} \iffixmlinks \ifnum\aeb@arrayIndx>0 save^^J% bCreateLink {^^J% \mlDict\space/mLinkFxup#1\space known {^^J% (\ml@@nnotName#1) #2\space mLinkFxup#1\space quadpointsfixup^^J% \ps@mark{mLink#1} 0 \FixupProc\space /PUTINTERVAL pdfmark^^J% }if }if \fi \else % \end{macrocode} % (2018/04/20) Added \texttt{bCreateLink}, etc., to protect % against \app{distiller}/\app{ps2pdf} from crashing when \cs{mlfix\darg{n}}. % \changes{v2.1.18}{2018/04/20}{Added \string\texttt{bCreateLink}, etc., to protect % against distiller/ps2pdf from crashing} % \begin{macrocode} bCreateLink {^^J% \mlDict\space/mLinkFxup#1\space known {^^J% \ps@mark{mLink#1} 0 mLinkFxup#1 /PUTINTERVAL pdfmark^^J% }if }if \fi}% \fi} % \end{macrocode} % \end{macro} % \section{Macros used by the SOUL Interface} % \begin{macrocode} \ifHy@colorlinks \def\ef@colorthislink{\color{\ef@thislinkcolor}} \else \let\ef@colorthislink\relax \fi % \end{macrocode} % I've inserted \verb|\let\protect\@empty| to make |mlnameref| and |mlNameref| work. % \begin{macrocode} \def\ml@SOUL@stop{\relax} \def\SOUL@mlhpreamble{\begingroup % \end{macrocode} % (2011/12/27) Originally, I had \verb|\let\protect\@empty| here, but removing this % seems to do no harm, so, we'll go for it. % \begin{macrocode} \mlh@preambleCmdInsert\ef@colorthislink} \def\SOUL@mlheverysyllable{% dpsaug16 \global\advance\syllableCnt\@ne \ifx\eq@mlcrackat\@empty \expandafter\SOUL@mlheverysyllable@i \else \expandafter\SOUL@mleverysyllable@ii \fi } \let\eq@@mlhyph\@empty \def\ml@typset@syl#1{\raisebox{\ml@raiseamt} {\smash{\normalfont\normalcolor\tiny\strut\llap{\the#1}}}} % \end{macrocode} % \DescribeMacro\turnSyllbCntOn Turns on the counting of the syllables, % while \DescribeMacro\turnSyllbCntOff\cmd{\turnSyllbCntOff} counting marks off. % \begin{macrocode} \def\turnSyllbCntOn{\mlMarksOn\let\ml@typeset@@syl\ml@typset@syl} \def\turnSyllbCntOff{\let\ml@typeset@@syl\@gobble} \turnSyllbCntOff \def\SOUL@mlheverysyllable@i{% \mlh@setQuadSyllable{\the\aeb@arrayIndx}{\ml@lngth}% {\the\aeb@mLinkCnt}{\the\SOUL@syllable\eq@@mlhyph}% \the\SOUL@syllable %\SOUL@setkern\SOUL@charkern \ml@typeset@@syl{\syllableCnt}\eq@@mlhyph }% \def\SOUL@mleverysyllable@ii{% \ifnum\eq@mlchunk=0\relax \ifnum\syllableCnt>\eq@mlcrackat\relax \global\ml@displayfalse \else \global\ml@displaytrue \ifnum\syllableCnt=\eq@mlcrackat\relax \let\eq@@mlhyph\eq@mlhyph \global\let\ml@space\relax \else \let\eq@@mlhyph\@empty \global\let\ml@space\space \fi \SOUL@mlheverysyllable@i \fi \else \ifnum\syllableCnt>\eq@mlcrackat\relax \global\ml@displaytrue \SOUL@mlheverysyllable@i \else \global\ml@displayfalse \fi \fi \ml@dynamicsetup } %\def\SOUL@mlheveryspace#1{#1\space\hskip\spaceskip} \let\ml@space\space \def\SOUL@mlheveryspace#1{% #1\ml@space\global\let\ml@space\space } \def\SOUL@mlheveryhyphen{% \discretionary{% \unkern \SOUL@setkern\SOUL@hyphkern \SOUL@sethyphenchar }{}{}% } \def\SOUL@mlheveryexhyphen#1{\global\advance\syllableCnt\@ne \mlh@setQuadSyllable{\the\aeb@arrayIndx}{\ml@lngth}% {\the\aeb@mLinkCnt}{\SOUL@setkern\SOUL@hyphkern#1}% \SOUL@setkern\SOUL@hyphkern\hbox{#1}% \discretionary{}{}{% \SOUL@setkern\SOUL@charkern }% } \def\mlh@postambleCmd{\relax} \def\ml@dynamicsetup{%dpsaug16 \ifml@display \global\let\SOUL@everyspace\SOUL@mlheveryspace \global\let\SOUL@everyexhyphen\SOUL@mlheveryexhyphen \else \gdef\SOUL@everyspace##1{}% \gdef\SOUL@everyexhyphen##1{}% \fi } \def\SOUL@mlhpostamble{\mlh@postambleCmd} \def\SOUL@mlhsetup{\SOUL@setup \let\SOUL@preamble\SOUL@mlhpreamble \let\SOUL@everysyllable\SOUL@mlheverysyllable \ml@dynamicsetup % \let\SOUL@everyspace\SOUL@mlheveryspace \let\SOUL@everyhyphen\SOUL@mlheveryhyphen % \let\SOUL@everyexhyphen\SOUL@mlheveryexhyphen \def\SOUL@postamble{\SOUL@mlhpostamble}% } \DeclareRobustCommand*\aeb@mlh{\syllableCnt=0 \SOUL@mlhsetup\SOUL@} % \end{macrocode} % \begin{macrocode} % End of Package % % \end{macrocode} % \Finale \endinput