%\iffalse % makeindex -s gglo.ist -o xbmks.gls xbmks.glo % makeindex -s gind.ist -o xbmks.ind xbmks.idx %<*copyright> %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% xbmks.sty package, %% %% Copyright (C) 2016--2018 %% %% dpstory@uakron.edu %% %% %% %% 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}[1997/12/01] %\ProvidesPackage{xbmks} % [2020/01/16 v2.0.3 xbmks: Cross-document bookmarks (dps)] %<*driver> \documentclass{ltxdoc} \usepackage{xcolor} \usepackage[colorlinks,hyperindex=false,bookmarksopen]{hyperref} \usepackage{fancyvrb,array,calc} \usepackage{xbmks} \xbmksetup{colors={int=red},styles={intbf}} %\pdfstringdefDisableCommands{\let\\\textbackslash} \EnableCrossrefs \CodelineIndex \RecordChanges \bgroup\ttfamily \gdef\brpr#1{\char123\relax#1\char125\relax}\egroup \let\darg\brpr \let\env\texttt \let\opt\texttt \let\pkg\textsf \let\app\textsf \def\visispace{\symbol{32}} %\def\hardspace{{\fontfamily{cmtt}\selectfont\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\cs#1{\texttt{\bslash#1}} \DeclareRobustCommand{\tmspace}[3]{% \ifmmode\mskip#1#2\else\kern#1#3\fi\relax} \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}} \let\thinspace\, \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}} \let\negthinspace\! \renewcommand{\:}{\tmspace+\medmuskip{.2222em}} \let\medspace\: \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}} \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}} \let\thickspace\; \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}} \makeatletter \renewcommand{\paragraph} {\@startsection{paragraph}{4}{0pt}{6pt}{-3pt} {\normalfont\normalsize\bfseries}} \renewenvironment{quote}[1][] {\def\@rgi{#1}\ifx\@rgi\@empty \let\rghtm\@empty\else\def\rghtm{\rightmargin\leftmargin}\fi \list{}{\rghtm} %{\rightmargin\leftmargin}% \item\relax} {\endlist} \makeatother \InputIfFileExists{aebdocfmt.def}{\PackageInfo{xbmks}{Inputting aebdocfmt.def}} {\def\IndexOpt{\DescribeMacro}\def\IndexKey{\DescribeMacro}\let\setupFullwidth\relax \PackageInfo{xbmks}{aebdocfmt.def cannot be found}} \begin{document} \def\CMD#1{\textbackslash#1} \GetFileInfo{xbmks.sty} \title{\textsf{xbmks}: Cross-document bookmarks} \author{D. P. Story\\ Email: \texttt{dpstory@acrotex.net}} \date{processed \today} \maketitle \tableofcontents \let\Email\texttt \DocInput{xbmks.dtx} \IfFileExists{\jobname.ind}{\newpage\setupFullwidth\par\PrintIndex}{\paragraph*{Index} The index goes here.\\Execute \texttt{makeindex -s gind.ist -o xbmks.ind xbmks.idx}\\on the command line and recompile \texttt{xbmks.dtx}.} \IfFileExists{\jobname.gls}{\PrintChanges}{\paragraph*{Change History} The list of changes goes here.\\Execute \texttt{makeindex -s gglo.ist -o xbmks.gls xbmks.glo}\\on the command line and recompile \texttt{xbmks.dtx}.} \end{document} % % \fi % \MakeShortVerb{|} % % \InputIfFileExists{aebdonotindex.def}{\PackageInfo{web}{Inputting aebdonotindex.def}} % {\PackageInfo{web}{cannot find aebdonotindex.def}} % % \begin{macrocode} % Begin package %<*package> \RequirePackage{xkeyval} \RequirePackage{ifpdf}[2006/02/20] \RequirePackage{ifxetex}[2006/08/21] % \end{macrocode} % %\section{Description} % More than a couple decades ago (counting back from 2018), I wrote two mathematics tutorials: \textsl{\href{http://www.math.uakron.edu/~dpstory/e-calculus.html}{eCalculus}} and % \textsl{\href{http://www.math.uakron.edu/~dpstory/mpt_home.html}{Algebra Review in Ten Lessons}}. The tutorials consisted of a number of lessons, each in a separate PDF. % The bookmarks of each lessons contained the table of contents for the whole tutorial. A student, in theory, could then % jump from one lesson to another by selecting an entry of interest from the bookmarks. In the intervening years I have not seen % a {\LaTeX} package for merging the table of contents of a set of PDFs and merge them in this each member of the % set. This package attempts to do just that. % % \section{Drivers and options} % We support the drivers \app{dvips} (and \app{dvipsone}), \app{pdflatex}, \app{lualatex}, and \app{xelatex}; these % options are then named \opt{dvipsone}, \opt{dvips}, \opt{pdftex}, \opt{luatex}, and \opt{xetex}. % \changes{v1.1}{2018/06/13}{Fixed misspelling of drive command for pdfmark case} % \begin{macrocode} \def\xbmk@driver{xbmks-pdfmark.def} \DeclareOptionX{dvipsone}{\def\xbmk@driver{xbmks-pdfmark.def}} \DeclareOptionX{dvips}{\def\xbmk@driver{xbmks-pdfmark.def}} \DeclareOptionX{pdftex}{\def\xbmk@driver{xbmks-pdftex.def}} \DeclareOptionX{luatex}{\def\xbmk@driver{xbmks-pdftex.def}} \DeclareOptionX{xetex}{\def\xbmk@driver{xbmks-xetex.def}} % \end{macrocode} % \section{Process the options} % \changes{v2.0.3}{2020/01/16}{Modification to conform to the new \string\texttt{web.cfg} format} % \begin{macrocode} \let\bWebCustomize\endinput \let\eWebCustomize\relax \ifpdf\ExecuteOptionsX{pdftex}\else \ifxetex\ExecuteOptionsX{xetex}\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 \ProcessOptionsX % \end{macrocode} % \section{Requirements} % The minimal requirement is \pkg{hyperref} and its built-in bookmark system. It is important to note that % the \pkg{bookmark} package is not supported. % \begin{macrocode} \RequirePackage{hyperref} % \end{macrocode} % \begin{macro}{\xbmksetup} % Set the cross-document options: % \changes{v1.1}{2018/06/13}{Allow an empty value of docbundle, its value is set to \string\cs{jobname}}% %\begin{quote}\ttfamily\obeylines %\string\xbmksetup\darg{% %\qquad docbundle=\darg{\ameta{doc\SUB1},\ameta{doc\SUB2},...,\ameta{doc\SUB{n}}}, %\qquad colors=\darg{int=\ameta{color},ext=\ameta{color}}, %\qquad styles=\darg{intbf,extbf,intit,extit} %} %\end{quote} %This command must appear in one and only one of the document bundle, perhaps one %of the documents you are calling the `main file'. It writes %the key-values to the file \texttt{xbmks.cfg} which is then read back in by the other %members of the document bundle, as specified by the \texttt{dobundle} key. The base names %of the document bundle must match the name given to it by \cs{jobname}, exact spelling, case %sensitive. % %\paragraph*{Key-values for \cs{xbmksetup}.} The keys belonging to the \texttt{xbmksetup} family: %\IndexOpt{docbundle}\texttt{docbundle}, \IndexOpt{colors}\texttt{colors}, and \IndexOpt{styles}\texttt{styles}. % \begin{macrocode} \define@key{xbmksetup}{docbundle}[]{\def\x@bmks@docs{#1}} \let\x@bmks@docs\@empty \define@key{xbmksetup}{colors}[]{\def\x@bmks@colors{#1}} \let\x@bmks@colors\@empty \define@key{xbmksetup}{styles}[]{\def\x@bmks@styles{#1}} \let\x@bmks@styles\@empty % \end{macrocode} %\subparagraph*{Values for the key \texttt{colors}.} The value recognized are %\begin{quote}\ttfamily % colors=\darg{int=\ameta{color},ext=\ameta{color}} %\end{quote} %If the value of \texttt{int} or \texttt{ext} is empty, then the PDF viewer's default %colors are using (black). % \begin{macrocode} \define@key{xbmk@colors}{int}[]{% \HyColor@BookmarkColor{#1}{\xbmks@intC}{xbmks}{int}% \ifx\xbmks@intC\@empty\else \edef\xbmks@intC{/C[\xbmks@intC]}\fi } \let\xbmks@intC\@empty \define@key{xbmk@colors}{ext}[]{% \HyColor@BookmarkColor{#1}{\xbmks@extC}{xbmks}{ext}% \ifx\xbmks@extC\@empty\else \edef\xbmks@extC{/C[\xbmks@extC]}\fi } \let\xbmks@extC\@empty \let\xbmks@Yes=y \let\xbmks@No=n % \end{macrocode} %\subparagraph*{Values for the key \texttt{colors}.} The value recognized are %\begin{quote}\ttfamily % styles=\darg{intbf,intit,extbf,extit} %\end{quote} %These are valueless keys (Boolean keys, actually). \texttt{intbf} means the interior document bookmarks %are set in bold while \texttt{intbf,intit} creates bold and italic font. % \begin{macrocode} \define@boolkey{xbmk@styles}{intbf}[true]{} \define@boolkey{xbmk@styles}{extbf}[true]{} \define@boolkey{xbmk@styles}{intit}[true]{} \define@boolkey{xbmk@styles}{extit}[true]{} % \end{macrocode} % We evaluate the values of \cs{xbmksetup} by getting the values of % the \texttt{xbmksetup} family. % \begin{macrocode} \newcommand{\xbmksetup}[1]{\setkeys{xbmksetup}{docbundle,#1}% % \end{macrocode} % \changes{v2.0.2}{2018/07/04}{Added an empty docbundle argument. This solves a problem % that the bookmarks not appearing after an even number of compiles.} % \begin{macrocode} \ifx\x@bmks@docs\@empty % \end{macrocode} % If there is no \texttt{docbundle} is specified, we use \cs{jobname} as its % value. % \begin{macrocode} \PackageInfo{xbmks}{The docbundle key of \string\xbmksetup\space is empty,\MessageBreak I will give it a value of `\jobname',\MessageBreak in hopes this is your intention}% \gdef\xbmk@cnt{1}% \def\xbmks@next{\write@xbmks@cfg{docbundle={\jobname},#1}}\else \def\xbmks@next{\write@xbmks@cfg{#1}}\fi\xbmks@next } % \end{macrocode} % We write the key-values of \cs{xbmksetup} to the hard drive in the file % \texttt{xbmks.cfg}, this is \cs{xbmksetupi\darg{\ameta{KVPairs}}}. \cs{xbmksetupi} % is defined below, it is the command that actually does the heavy lifting in % processing the key-values. % \begin{macrocode} \def\write@xbmks@cfg#1{% \newwrite\xbmks@setup \immediate\openout \xbmks@setup xbmks.cfg \set@display@protect \immediate\write\xbmks@setup{\protect\xbmksetupi{#1}}% \set@typeset@protect \immediate\closeout\xbmks@setup } % \end{macrocode} % \cs{xbmksetupi} is an internal command that sets the key-values across all files in the \texttt{docbundle}. % \begin{macrocode} \newcommand{\xbmksetupi}[1]{% \setkeys{xbmksetup}{#1}% \edef\x{\noexpand\x@docbundle{\x@bmks@docs}}\x \edef\x{\noexpand \setkeys{xbmk@colors}{\x@bmks@colors}}\x \edef\x{\noexpand \setkeys{xbmk@styles}{\x@bmks@styles}}\x \let\xbmk@intF\@empty \ifKV@xbmk@styles@intit \ifKV@xbmk@styles@intbf \def\xbmk@intF{/F 3}\else \def\xbmk@intF{/F 1}\fi \else \ifKV@xbmk@styles@intbf \def\xbmk@intF{/F 2}\fi \fi \let\xbmk@extF\@empty \ifKV@xbmk@styles@extit \ifKV@xbmk@styles@extbf \def\xbmk@extF{/F 3}\else \def\xbmk@extF{/F 1}\fi \else \ifKV@xbmk@styles@extbf \def\xbmk@extF{/F 2}\fi \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\x@docbundle} % is a comma-delimited list of document base names: %\begin{quote}\ttfamily\obeylines %\string\x@docbundle\darg{\ameta{doc\SUB1},\ameta{doc\SUB2},...,\ameta{doc\SUB{n}}} %\end{quote} %This command is called internally by \cs{xbmksetupi}. % \begin{macrocode} \def\xbmkcsarg#1#2{\expandafter#1\csname#2\endcsname} \xdef\xbmk@cnt{0} \newcommand{\x@docbundle}[1]{\bgroup \def\thisDoc{\jobname}\count\z@=0 % \edef\@tmpexp{\noexpand\@for\noexpand\@arg:=#1}% \@tmpexp\do{\advance\count\z@ by 1\relax \edef\x{\noexpand\xbmk@recordDoc{\@arg}}\x \edef\x{\noexpand\xbmk@docID{\@arg}}\x }% \xdef\xbmk@cnt{\the\count\z@}\egroup } \newcommand{\xbmk@recordDoc}[1]{% \xbmkcsarg\xdef{xbmk@doc\the\count\z@}{#1}} % \end{macrocode} % Because we are bringing in multiple outline files, there may be duplicate anchor names. % We assign each file in the document bundle a unique ID `\texttt{x1\ameta{anchor}}', `\texttt{x2\ameta{anchor}}', etc. % The IDs are ultimately assigned through \cs{pdfbookmarkx}. % \begin{macrocode} \newcommand{\xbmk@docID}[1]{% \xbmkcsarg\xdef{x#1}{x\the\count\z@}} \xbmkcsarg\xdef{x\jobname}{x0} % \end{macrocode} % \end{macro} % % \section{Extending bookmarks to arbitrary actions} % % It is possible to create bookmarks with arbitrary actions, just as the \pkg{bookmark} % package, does. Here we try to use \pkg{hyperref}'s native bookmark support. The % \pkg{hyperref} commands \cs{pdfbookmark}, \cs{currentbookmark}, \cs{subpdfbookmark}, and % \cs{belowpdfbookmark} are modified. % \begin{macro}{\pdfbookmarkx}\hskip-\marginparsep\, % \texttt{[\ameta{level}]\darg{\ameta{text}}[\ameta{xbmkskeys-kvp}]\darg{\ameta{name}}}\\ % Defines a bookmark at \ameta{level}. If \ameta{level} is not provided, the level 1 is assumed. % We write to the outline file the action desired for this bookmark. % \cs{currentAction} is defined below. We do not set an anchor; if the % document author wants an anchor, he should use \cs{pdfbookmark}. As with % \cs{pdfbookmark}, the \cs{pdfbookmarkx} should not normally be directly % used. % \paragraph*{Key-values for the `\cs{...bookmarkx}' commands.} Recognized keys are % \IndexKey{action}\texttt{action}, \IndexKey{color}\texttt{color}, and \IndexKey{style}\texttt{style}. % Note that these keys are singular, as opposed to \texttt{colors} and \texttt{styles} defined in the % \texttt{xbmksetup} family. This is the \texttt{xbmkskeys} family. % \changes{v2.0}{2018/06/21}{Added `\string\cs{...bookmarkx} commands} % \changes{v2.0.1}{2018/06/25}{Added key-values for action, color, and style for custom `\string\cs{...bookmarkx} commands} % \begin{macrocode} \define@key{xbmkskeys}{action}{\def\x@bmks@action{#1}} \let\x@bmks@action\@empty \define@key{xbmkskeys}{color}[]{% \HyColor@BookmarkColor{#1}{\x@bmks@C}{xbmks}{color}% \ifx\x@bmks@C\@empty\else \edef\x@bmks@C{/C[\x@bmks@C]}\fi } \let\x@bmks@C\@empty \define@key{xbmkskeys}{style}[]{% \edef\x{\noexpand\setkeys{xbmks@style}{#1}}\x \let\x@bmks@F\@empty \ifKV@xbmks@style@it \ifKV@xbmks@style@bf \def\x@bmks@F{/F 3}\else \def\x@bmks@F{/F 1}\fi \else \ifKV@xbmks@style@bf \def\x@bmks@F{/F 2}\fi \fi } \let\x@bmks@F\@empty % \end{macrocode} % The \texttt{style} key takes zero, one, or two values, these are \texttt{bf} and \texttt{it}. % \begin{macrocode} \define@boolkey{xbmks@style}{bf}[true]{} \define@boolkey{xbmks@style}{it}[true]{} \def\x@rollCFIntoActionBmrk#1{% \xbmkcsarg\ifx{X_#1}\relax \let\x@bmks@C\@empty\let\x@bmks@F\@empty\fi \ifx\xbmk@J\xbmk@filename \ifx\x@bmks@C\@empty\let\thisCol\xbmks@intC\else \let\thisCol\x@bmks@C\fi \ifx\x@bmks@F\@empty\let\thisF\xbmk@intF\else \let\thisF\x@bmks@F\fi \else \ifx\x@bmks@C\@empty\let\thisCol\xbmks@extC\else \let\thisCol\x@bmks@C\fi \ifx\x@bmks@F\@empty\let\thisF\xbmk@extF\else \let\thisF\x@bmks@F\fi \fi \global\let\x@bmks@C\@empty\global\let\x@bmks@F\@empty } % \end{macrocode} % We finally arrive at \cs{pdfbookmarkx} command. % \begin{macrocode} \newcommand\pdfbookmarkx[2][0]{% \@ifnextchar[%] {\pdfbookmarkx@i{#1}{#2}} {\pdfbookmarkx@i{#1}{#2}[]}} \def\pdfbookmarkx@i#1#2[#3]#4{% level, title, action, name \def\x@rgiii{#3}\ifx\x@rgiii\@empty % \end{macrocode} % if there is no action, treat as a destination % \begin{macrocode} \Hy@writebookmark{}{#2}{#4.#1}{#1}{toc}% \hyper@anchorstart{#4.#1}\hyper@anchorend \else \protected@write\@outlinefile{}{% \string\nextAction% assign doc ID {\@nameuse{x\jobname}#4.#1}{#3}}% \Hy@writebookmark{}{#2}{\@nameuse{x\jobname}#4.#1}{#1}{toc}% \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\currentpdfbookmarkx} % \hskip-\marginparsep\,\texttt{\darg{\ameta{text}}[\ameta{xbmkskeys-kvp}]\darg{\ameta{name}}}\\ % The \texttt{action=\ameta{action}} is raw PDF code, for example, %\begin{quote}\ttfamily %\string\currentpdfbookmarkx[/S/URI/URI(http://www.acrotex.net)]\\\null %\qquad\darg{http://www.acrotex.net}\darg{home} %\end{quote} % The command creates a bookmark at the current % bookmark level in the outline tree and associates the specified \ameta{action}. The argument % \ameta{text} appears in the bookmark panel. The \ameta{name} is used for identification purposes. % \begin{macrocode} \newcommand{\currentpdfbookmarkx}[1]{% \@ifnextchar[%] {\currentpdfbookmarkx@i{#1}} {\currentpdfbookmarkx@i{#1}[]}} \def\currentpdfbookmarkx@i#1[#2]#3{% \pdfbookmarkx[\Hy@currentbookmarklevel]{#1}[{#2}]{#3}} % \end{macrocode} % \end{macro} % \begin{macro}{\subpdfbookmarkx} % \hskip-\marginparsep\,\texttt{\darg{\ameta{text}}[\ameta{\ameta{xbmkskeys-kvp}}]\darg{\ameta{name}}}\\ % Reduces the current bookmark level by one, then creates % the bookmark at that level. The reduced level is the new current % bookmark level. % \begin{macrocode} \newcommand{\subpdfbookmarkx}[1]{% \@ifnextchar[%] {\subpdfbookmarkx@i{#1}} {\subpdfbookmarkx@i{#1}[]}} \def\subpdfbookmarkx@i#1[#2]#3{% \@tempcnta\Hy@currentbookmarklevel \Hy@StepCount\@tempcnta \expandafter \pdfbookmarkx\expandafter[\the\@tempcnta]{#1}[{#2}]{#3}} % \end{macrocode} % \end{macro} % \begin{macro}{\belowpdfbookmarkx} % \hskip-\marginparsep\,\texttt{\darg{\ameta{text}}[\ameta{xbmkskeys-kvp}]\darg{\ameta{name}}}\\ % Creates a bookmark at one level below the current % bookmark level without changing the value of the current bookmark % level. % \begin{macrocode} \newcommand{\belowpdfbookmarkx}[1]{% \@ifnextchar[%] {\belowpdfbookmarkx@i{#1}} {\belowpdfbookmarkx@i{#1}[]}} \def\belowpdfbookmarkx@i#1[#2]#3{% \@tempcnta\Hy@currentbookmarklevel \Hy@StepCount\@tempcnta \expandafter \pdfbookmarkx\expandafter[\the\@tempcnta]{#1}[{#2}]{#3}% \advance\@tempcnta by -1 % \xdef\Hy@currentbookmarklevel{\the\@tempcnta}} % \end{macrocode} % \end{macro} % \begin{macro}{\nextAction@i} % \hskip-\marginparsep\,\texttt{\darg{\ameta{anchor.level}}\darg{\ameta{xbmkskeys-kvp}}}\\ % This command is used internally, the document author need not do anything. % The command \cs{nextAction} is \cs{let} to \cs{nextAction@i} just prior to when % the outline file is input; and is \cs{let} to \cs{@gobbletwo}, otherwise. % \begin{macrocode} \def\nextAction@i#1#2{\@ifundefined{X_#1}{% \setkeys{xbmkskeys}{#2}% \xbmkcsarg\xdef{X_#1}{\x@bmks@action}% }{\global\xbmkcsarg\let{X_#1}\relax \PackageWarning{xbmks} {The anchor name `#1' is already defined,\MessageBreak change this name, the bookmark will be created\MessageBreak but it will have no associated action}}} % \end{macrocode} % \end{macro} % \begin{macrocode} \def\x@outWarningMsg{\PackageWarningNoLine{xbmks}{% @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak @@ Outline files were not input, compile again @@\MessageBreak @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}}% % \end{macrocode} % These commands are implemented in the driver dependent sections. % \begin{macrocode} % End package % %<*pdfmark> % \end{macrocode} % \section{Driver dependent code} % \subsection{The pdfmark driver} % We redefine/modify the \cs{ReadBookmarks} command of \pkg{hyperref}, % this definition is driver dependent. % \begin{macrocode} \def\ReadBookmarks{% \pdf@ifdraftmode{}{% \begingroup\def\\{\@backslashchar\@backslashchar}% dps \def\calc@bm@number##1{% \@tempcnta=\check@bm@number{##1}\relax \advance\@tempcnta by 1 % \expandafter\edef\csname B_##1\endcsname{\the\@tempcnta}% }% \def\do##1{% \ifnum\catcode`##1=\active \@makeother##1% \else \ifnum\catcode`##1=6 % \@makeother##1% \fi \fi }% \dospecials \Hy@safe@activestrue \escapechar=`\\% \ifx\WriteBookmarks\relax \global\let\WriteBookmarks\relax \fi \begingroup \def\WriteBookmarks{0}% \count\z@=0\relax \edef\xbmk@J{\jobname}% \@whilenum \count\z@<\xbmk@cnt\relax\do{% \advance\count\z@ by 1 % \edef\xbmk@thisdoc{xbmk@doc\the\count\z@}% \edef\xbmk@filename{\@nameuse{\xbmk@thisdoc}}% \@onelevel@sanitize\xbmk@filename \bgroup \def\@@BOOKMARK[##1][##2]##3##4##5{% \calc@bm@number{##5}% }% \let\nextAction\@gobbletwo \InputIfFileExists{\xbmk@filename.out}{}{\x@outWarningMsg}% \def\@@BOOKMARK[##1][##2]##3##4##5{% \def\Hy@temp{##4}% % \end{macrocode} % If `\texttt{X\_\#\#3}' is undefined (\cs{relax}), it is a normal bookmark. % \begin{macrocode} \xbmkcsarg\ifx{X_##3}\relax \ifx\xbmk@J\xbmk@filename \pdfmark{% pdfmark=/OUT,% Count={##2\check@bm@number{##3}},% Raw={\xbmks@intC\xbmk@intF},% Dest={##3},% Title=\expandafter\strip@prefix\meaning\Hy@temp }% \else \pdfmark{% pdfmark=/OUT,% Count={##2\check@bm@number{##3}},% Raw={\xbmks@extC\xbmk@extF},% Action=/GoToR,% File={\xbmk@filename.pdf},% Dest={##3},% Title=\expandafter\strip@prefix\meaning\Hy@temp }% \fi \else % \end{macrocode} % The anchor has an `\texttt{X\_}' definition, it is a bookmark created % from one of the `\texttt{bookmarkx}' commands. We treat this as a separate case. % \begin{macrocode} \x@rollCFIntoActionBmrk{##3}% \pdfmark{% pdfmark=/OUT,% Count={##2\check@bm@number{##3}},% Raw={/Action<<\@nameuse{X_##3}>>\thisCol\thisF},% Title=\expandafter\strip@prefix\meaning\Hy@temp }% \fi }% bookmark \let\nextAction\nextAction@i \InputIfFileExists{\xbmk@filename.out}{}{}% \egroup }% \@whilenum \endgroup \endgroup }% \ifx\WriteBookmarks\relax\else \if@filesw \newwrite\@outlinefile \Hy@OutlineRerunCheck \immediate\openout\@outlinefile=\jobname.out\relax \ifHy@typexml \immediate\write\@outlinefile{\relax}% \fi \fi \fi } % % \end{macrocode} % \subsection{Code for pdftex/luatex driver} % We redefine/modify the \cs{ReadBookmarks} command of \pkg{hyperref}, % this definition is driver dependent. % \begin{macrocode} %<*pdftex> \def\ReadBookmarks{% \pdf@ifdraftmode{}{% \begingroup\def\\{\@backslashchar\@backslashchar}% dps \def\calc@bm@number##1{% \@tempcnta=\check@bm@number{##1}\relax \advance\@tempcnta by 1 % \expandafter\edef\csname B_##1\endcsname{\the\@tempcnta}% }% \def\Hy@OutlineName##1##2##3##4{\def\@rgi{##1}% \expandafter\pdfoutline\ifx\@rgi\@empty\else attr {##1} \fi user {##2} count##3{##4}% % goto name{#2} count#3{#4}% }% \def\do##1{% \ifnum\catcode`##1=\active \@makeother##1% \else \ifnum\catcode`##1=6 % \@makeother##1% \fi \fi }% \dospecials \Hy@safe@activestrue \escapechar=`\\% \ifx\WriteBookmarks\relax \global\let\WriteBookmarks\relax \fi \begingroup \def\WriteBookmarks{0}% \count\z@=0\relax \edef\xbmk@J{\jobname}% \@whilenum \count\z@<\xbmk@cnt\relax\do{% \advance\count\z@ by 1 % \edef\xbmk@thisdoc{xbmk@doc\the\count\z@}% \edef\xbmk@filename{\@nameuse{\xbmk@thisdoc}}% \@onelevel@sanitize\xbmk@filename \bgroup \gdef\@@BOOKMARK[##1][##2]##3##4##5{% \calc@bm@number{##5}% }% \let\nextAction\@gobbletwo \InputIfFileExists{\xbmk@filename.out}{}{\x@outWarningMsg}% \gdef\@@BOOKMARK[##1][##2]##3##4##5{% \def\Hy@temp{##4}% \Hy@pstringdef\Hy@pstringName{\HyperDestNameFilter{##3}}% \xbmkcsarg\ifx{X_##3}\relax % \end{macrocode} % Ordinary bookmark % \begin{macrocode} \ifx\xbmk@J\xbmk@filename \Hy@OutlineName{\xbmks@intC\xbmk@intF}{<>}{% ##2\check@bm@number{\Hy@pstringName}% }{% \expandafter\strip@prefix\meaning\Hy@temp }% \else \Hy@OutlineName{\xbmks@extC\xbmk@extF}{<>}{% ##2\check@bm@number{##3}% }{% \expandafter\strip@prefix\meaning\Hy@temp }% \fi \else % \end{macrocode} % Bookmark created by one of the `\texttt{...bookmarkx} commands % \begin{macrocode} \x@rollCFIntoActionBmrk{##3}% \Hy@OutlineName{\thisCol\thisF} {<<\@nameuse{X_##3}>>}{% ##2\check@bm@number{\Hy@pstringName}% }{% \expandafter\strip@prefix\meaning\Hy@temp }% \fi }% bookmark \let\nextAction\nextAction@i \InputIfFileExists{\xbmk@filename.out}{}{}% \egroup } % \@whilenum \endgroup }% \ifx\WriteBookmarks\relax \else \if@filesw \newwrite\@outlinefile \Hy@OutlineRerunCheck \immediate\openout\@outlinefile=\jobname.out\relax \ifHy@typexml \immediate\write\@outlinefile{\relax}% \fi \fi \fi } % %<*xetex> % \end{macrocode} % \subsection{Code for xetex driver} % We redefine/modify the \cs{ReadBookmarks} command of \pkg{hyperref}, % this definition is driver dependent. % \begin{macrocode} \def\ReadBookmarks{% \pdf@ifdraftmode{}{% \begingroup\def\\{\@backslashchar\@backslashchar}% dps \def\calc@bm@number##1{% \@tempcnta=\check@bm@number{##1}\relax \advance\@tempcnta by 1 % \expandafter\edef\csname B_##1\endcsname{\the\@tempcnta}% }% \def\do##1{% \ifnum\catcode`##1=\active \@makeother##1% \else \ifnum\catcode`##1=6 % \@makeother##1% \fi \fi }% \dospecials \Hy@safe@activestrue \escapechar=`\\% \ifx\WriteBookmarks\relax \global\let\WriteBookmarks\relax \fi \begingroup \def\WriteBookmarks{0}% \count\z@=0\relax \edef\xbmk@J{\jobname}% \@whilenum \count\z@<\xbmk@cnt\relax\do{% \advance\count\z@ by 1 % \edef\xbmk@thisdoc{xbmk@doc\the\count\z@}% \edef\xbmk@filename{\@nameuse{\xbmk@thisdoc}}% \@onelevel@sanitize\xbmk@filename \bgroup \def\@@BOOKMARK[##1][##2]##3##4##5{% \calc@bm@number{##5}% }% \let\nextAction\@gobbletwo \InputIfFileExists{\xbmk@filename.out}{}{\x@outWarningMsg}% \def\@@BOOKMARK[##1][##2]##3##4##5{% \def\Hy@temp{##4}% \Hy@pstringdef\Hy@pstringName{\HyperDestNameFilter{##3}}% \x@rollCFIntoActionBmrk{##3}% \@pdfm@mark{% outline \ifHy@DvipdfmxOutlineOpen [\ifnum##21>\z@\else-\fi] \fi ##1<<% /Title(\expandafter\strip@prefix\meaning\Hy@temp)% \xbmkcsarg\ifx{X_##3}\relax % \end{macrocode} % Ordinary bookmark % \begin{macrocode} \ifx\xbmk@J\xbmk@filename /A<<% /S/GoTo% /D(\Hy@pstringName)% >>% \else /A<<% /S/GoToR/F(\xbmk@filename.pdf)% /D(\Hy@pstringName)% >>% \fi \else % \end{macrocode} % Bookmark created by one of the \texttt{\string\...bookmarkx} commands % \begin{macrocode} /A<<\@nameuse{X_##3}>> \fi \thisCol\thisF >>% }% \@pdfm@mark \let\thisC\@empty\let\thisF\@empty }% bookmark \let\nextAction\nextAction@i \InputIfFileExists{\xbmk@filename.out}{}{}% \egroup }% \@whilenum \endgroup \endgroup }% \ifx\WriteBookmarks\relax \else \if@filesw \newwrite\@outlinefile \Hy@OutlineRerunCheck \immediate\openout\@outlinefile=\jobname.out\relax \ifHy@typexml \immediate\write\@outlinefile{\relax}% \fi \fi \fi } % %<*package> \InputIfFileExists{xbmks.cfg}{}{} \@ifpackageloaded{bookmark}{\PackageWarningNoLine{xbmks}{The bookmark package is not supported;\MessageBreak this package does nothing, as a result}} {\InputIfFileExists{\xbmk@driver}{}{}} % % \end{macrocode} % \Finale