% \iffalse meta-comment
% A LaTeX Class and Package for OMDoc Text Fragments
% Copyright (c) 2010 Michael Kohlhase, all rights reserved
%               this file is released under the
%               LaTeX Project Public License (LPPL)
%
% The development version of this file can be found at
% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/omtext/omtext.dtx $
% \fi
%   
% \iffalse
%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%<package>\ProvidesPackage{omtext}[2010/06/25 v1.0 OMDoc Text Fragments]
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{url,array,omdoc,float}
\usepackage{omtext}
\usepackage[show]{ed}
\usepackage[hyperref=auto,style=alphabetic]{biblatex}
\bibliography{kwarc}
\usepackage[eso-foot,today]{svninfo}
\svnInfo $Id: omtext.dtx 1671 2010-11-06 07:05:15Z kohlhase $
\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/omtext/omtext.dtx $
\usepackage{stex-logo}
\usepackage{../ctansvn}
\usepackage{hyperref}
\makeindex
\floatstyle{boxed}
\newfloat{exfig}{thp}{lop}
\floatname{exfig}{Example}
\def\tracissue#1{\cite{sTeX:online}, \hyperlink{http://trac.kwarc.info/sTeX/ticket/#1}{issue #1}}
\begin{document}\DocInput{omtext.dtx}\end{document}
%</driver>
% \fi
% 
%\iffalse\CheckSum{333}\fi
% 
% \changes{v0.4}{2008/07/22}{added index markup}
% \changes{v0.4}{2008/09/29}{augmenting the index macros with optional values}
% \changes{v0.6}{2009/07/08}{removing {\texttt{ttin}} {\texttt{{emin}}} and friends, 
%   they were almost never used.}
% \changes{v0.6}{2009/07/08}{renmanig {\texttt{myindex}} to {\texttt{omdoc\@ index}},
%   {\texttt{twin}} to {\texttt{\@ twin}}, and {\texttt{atwin}} to {\texttt{\@ atwin}} to
%   make them packge-local} 
% \changes{v0.7}{2010/02/11}{changing blockquote to sblockquote and inlinequote similarly}
% \changes{v0.9}{2010/05/25}{separated out from \texttt{omdoc.dtx}}
% \changes{v1.0}{2010/06/18}{fixing typos}
% 
% \GetFileInfo{omtext.sty}
% 
% \MakeShortVerb{\|}
%
% \def\omdoc{OMDoc}
% \def\latexml{{\LaTeX}ML}
% \title{{\texttt{omtext}}: Semantic Markup for Mathematical Text Fragments in {\LaTeX}\thanks{Version {\fileversion} (last revised
%        {\filedate})}}
%    \author{Michael Kohlhase\\
%            Jacobs University, Bremen\\
%            \url{http://kwarc.info/kohlhase}}
% \maketitle
%
% \begin{abstract}
%   The |omtext| package is part of the {\sTeX} collection, a version of {\TeX/\LaTeX} that
%   allows to markup {\TeX/\LaTeX} documents semantically without leaving the document
%   format, essentially turning {\TeX/\LaTeX} into a document format for mathematical
%   knowledge management (MKM).
%
%   This package supplies an infrastructure for writing {\omdoc} text fragments in
%   {\LaTeX}.  
% \end{abstract}
%
%\newpage\tableofcontents\newpage
% 
%\begin{omgroup}[id=sec:STR]{Introduction}
%
%  The |omtext| package supplies macros and environment that allow to mark up mathematical
%  texts in {\sTeX}, a version of {\TeX/\LaTeX} that allows to markup {\TeX/\LaTeX}
%  documents semantically without leaving the document format, essentially turning
%  {\TeX/\LaTeX} into a document format for mathematical knowledge management (MKM). The
%  package supports direct translation to the {\omdoc} format~\cite{Kohlhase:omdoc1.2}
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:user]{The User Interface}
% 
% \begin{omgroup}[id=sec:user:options]{Package Options}
% 
%   The |omtext| package takes a single option: \DescribeMacro{showmeta}|showmeta|. If
%   this is set, then the metadata keys are shown (see~\cite{Kohlhase:metakeys:ctan} for
%   details and customization options).
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:user:omtext]{Mathematical Text}
% 
%   \DescribeEnv{omtext} The |omtext| environment is used for any text fragment that has a
%   contribution to a text that needs to be marked up. It can have a title, which can be
%   specified via the |title| key. Often it is also helpful to annotate the |type|
%   key. The standard relations from rhetorical structure theory |abstract|,
%   |introduction|, |conclusion|, |thesis|, |comment|, |antithesis|, |elaboration|,
%   |motivation|, |evidence|, |transition|, | note|, |annote| are recommended. Note that
%   some of them are unary relations like |introduction|, which calls for a target. In
%   this case, a target using the |for| key should be specified. The |transition| relation
%   is special in that it is binary (a ``transition between two statements''), so
%   additionally, a source should be specified using the |from| key.
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:user:phrase]{Phrase-Level Markup}
%
% \DescribeEnv{phrase} The |phrase| environment allows to mark up phrases with semantic
% information. It takes an optional |KeyVal| argument with the keys\ednote{continue} 
%
% \DescribeMacro{\sinlinequote} The |sinlinequote| macro allows to mark up quotes inline and
% attribute them. The quote itself is given as the argument, possibly preceded by the a
% specification of the source in a an optional argument. For instance, we would quote
% Hamlet with
% \begin{verbatim}
% \sinlinequote[Hamlet, \cite{Shak:1603:Hamlet}]{To be or not to be}
% \end{verbatim}
% which would appear as \sinlinequote[Hamlet, (Shakespeare 1603)]{To be or not to be} in
% the text. The style in which inline quotations appear in the text can be adapted by
% specializing the macros \DescribeMacro{\@sinlinequote}|\@sinlinequote| --- for quotations
% without source and \DescribeMacro{\@@sinlinequote}|\@@sinlinequote| --- for quotations with
% source.
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:user:block]{Block-Level Markup}
%
%   \DescribeEnv{sblockquote} The |sblockquote| environment is the big brother of the
%   |\sinlinequote| macro. It also takes an optional argument to specify the source. Here
%   the four internal macros \DescribeMacro{\begin@sblockquote}|\begin@sblockquote| to
%       \DescribeMacro{\end@@sblockquote}|\end@@sblockquote| are used for styling and can be
%   adapted by package integrators. Here a quote of Hamlet would marked up as
% \begin{verbatim}
% \begin{sblockquote}[Hamlet, \cite{Shak:1603:Hamlet}]\obeylines
%   To be, or not to be: that is the question:
%   Whether 'tis nobler in the mind to suffer
% \end{sblockquote}
% \end{verbatim}
% and would render as 
% \begin{sblockquote}[Hamlet, (Shakespeare 1603)]\obeylines
%   To be, or not to be: that is the question:
%   Whether 'tis nobler in the mind to suffer
% \end{sblockquote}
% 
% \DescribeMacro{\lec}The |\lec| macro takes one argument and sets it as a comment at the
% end of the line, making sure that if the content is too long it is pushed into a new
% line. We use it internally for placing the of source of the |sblockquote| environment
% above.  The actual appearance of the line end comment is determined by the
% \DescribeMacro{\@@lec}|\@@lec| macro, which can be customized in the document class.
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:user:index]{Index Markup}
%
%   The |omtext| package provides some extensions for the well-known indexing macros of
%   {\LaTeX}. The main reason for introducing these macros is that index markup in
%   {\omdoc} wraps the indexed terms rather than just marking the spot for
%   cross-referencing. Furthermore the index commands only indexes words unless
%   the\DescribeMacro{noindex} |noindex| option is set in the |\usepackage|. The |omtext|
%   package and class make the usual |\index| macro undefined\ednote{implement this and
%     issue the respective error message}.
% 
%   The \DescribeMacro{\indextoo}|\indextoo| macro renders a word and marks it for the
%   index. Sometimes, we want to index a slightly different form of the word, e.g. for
%   non-standard plurals: while |\indextoo{word}s| works fine, we cannot use this for the
%   word ``datum'', which has the plural ``data''. For this we have the macro
%   \DescribeMacro{\indexalt}|\indexalt|, which takes another argument for the displayed
%   text, allowing us to use |\indexalt{data}{datum}|, which prints ``data'' but puts
%   ``datum'' into the index.
% 
%   The second set of macros adds an infrastructure for two-word compounds. Take for
%   instance the compound ``OMDoc document'', which we usually want to add into the index
%   under ``OMDoc'' and ``document''. \DescribeMacro{\twintoo}|\twintoo{OMDoc}{document}|
%   is a variant of |\indextoo| that will do just this. Again, we have a version that
%   prints a variant: This is useful for situations like this the one in
%   Figure~\ref{fig:index-markup}:
% \begin{exfig}
% \begin{verbatim}
% We call group \twinalt{Abelian}{Abelian}{group}, iff \ldots
% \end{verbatim}
% \vspace*{-1em}will result in the following
% \begin{quote}
%   We call group \twinalt{Abelian}{Abelian}{group}, iff \ldots
% \end{quote}
% and put ``Abelian Group'' into the index.
% \caption{Index markup}\label{fig:index-markup}
% \end{exfig}
% 
% The third set of macros does the same for two-word compounds with adjectives,
% e.g. ``wonderful OMDoc
% document''. \DescribeMacro{\atwintoo}|\atwin{wonderful}{OMdoc}{document}| will make the
% necessary index entries under ``wonderful'' and ``document''. Again, we have a variant
% \DescribeMacro{\atwinalt}|\atwinalt| whose first argument is the alternative text.
%
% All index macros take an optional first argument that is used for ordering the
% respective entries in the index.
% \end{omgroup}
% \end{omgroup}
%
%
% \section{Limitations}\label{sec:limitations}
% 
% In this section we document known limitations. If you want to help alleviate them,
% please feel free to contact the package author. Some of them are currently discussed in
% the \sTeX TRAC~\cite{sTeX:online}. 
% \begin{compactenum}
% \item none reported yet
% \end{compactenum}
% 
% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography}\newpage
%
% \begin{omgroup}[id=sec:impl]{Implementation}
%
% The |omtext| package generates two files: the {\LaTeX} package (all the code between
% {\textsf{$\langle$*package$\rangle$}} and {\textsf{$\langle$/package$\rangle$}}) and the
% {\latexml} bindings (between {\textsf{$\langle$*ltxml$\rangle$ and
%     $\langle$/ltxml$\rangle$}}). We keep the corresponding code fragments together,
% since the documentation applies to both of them and to prevent them from getting out of
% sync.
%
% \begin{omgroup}[id=sec:impl:options]{Package Options}
% 
% The initial setup for {\latexml}: 
%
%    \begin{macrocode}
%<*ltxml>
package LaTeXML::Package::Pool;
use strict;
use LaTeXML::Package;
use Cwd qw(cwd abs_path);
%</ltxml>
%    \end{macrocode}
%
% We declare some switches which will modify the behavior according to the package
% options. Generally, an option |xxx| will just set the appropriate switches to true
% (otherwise they stay false).\ednote{need an implementation for {\latexml}}
%
%    \begin{macrocode}
%<*package>
\DeclareOption{showmeta}{\PassOptionsToPackage{\CurrentOption}{metakeys}}
\newif\ifindex\indextrue
\DeclareOption{noindex}{\indexfalse}
\ProcessOptions
\ifindex\makeindex\fi
%</package>
%<*ltxml>
DeclareOption('noindex','');
%</ltxml>
%    \end{macrocode}
%
% Then we need to set up the packages by requiring the |sref| package to be loaded.
%
%    \begin{macrocode}
%<*package>
\RequirePackage{sref}
\RequirePackage{comment}
%</package>
%<*ltxml>
RequirePackage('sref');
%</ltxml>
%    \end{macrocode}
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:impl:metadata]{Metadata}
% 
%   All the {\omdoc} elements allow to specify metadata in them, which is modeled by the
%   |omdoc:metadata| element. Since the content of this element is precisely controlled
%   by the Schema, we can afford to auto-open and auto-close it. Thus metadata elements
%   from various sources will just be included into one |omdoc:metadata| element, even if
%   they are supplied by different {\sTeX} bindings. Also we add numbering and location
%   facilities.
%
%    \begin{macrocode}
%<*ltxml> 
Tag('omdoc:metadata',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1,autoOpen=>1); 
%</ltxml>
%    \end{macrocode}
% 
% the |itemize|, |description|, and |enumerate| environments generate |omdoc:li|,
% |omdoc:di| with |autoclose| inside a CMP. This behavior will be overwritten later, so we
% remember that we are in a |CMP| by assigning |_LastSeenCMP|.
% 
%    \begin{macrocode}
%<*ltxml>
DefConstructor('\CMP@itemize@item[]',
       "<omdoc:li>?#1(<dc:title ?#locator(stex:srcref='#locator')()>#1</dc:title>)()",
       properties=>sub{ RefStepItemCounter(); });
DefConstructor('\CMP@enumerate@item[]',
       "<omdoc:li>?#1(<dc:title ?#locator(stex:srcref='#locator')()>#1</dc:title>)()",
       properties=>sub{ RefStepItemCounter(); });
DefConstructor('\CMP@description@item[]',
       "<omdoc:di>"
       . "?#1(<omdoc:dt>#1</omdoc:dt>)()<omdoc:dd>", # trust di and dt to autoclose
       properties=>sub{ RefStepItemCounter(); });
DefEnvironment('{CMP@itemize}',
	       "<omdoc:ul>#body</omdoc:ul>",
	       properties=>sub { beginItemize('CMP@itemize'); },
	       beforeDigest=>sub { Let(T_CS('\end{itemize}') =>T_CS('\end{CMP@itemize}')); });
DefEnvironment('{CMP@enumerate}',
	       "<omdoc:ol xml:id='#id'>#body</omdoc:ol>",
	       properties=>sub { beginItemize('CMP@enumerate'); },
	       beforeDigest=>sub { Let(T_CS('\end{enumerate}') =>T_CS('\end{CMP@enumerate}')); });
DefEnvironment('{CMP@description}',
 "<omdoc:dl xml:id='#id'>#body</omdoc:dl>",
	       properties=>sub { beginItemize('CMP@description'); },
	       beforeDigest=>sub { Let(T_CS('\end{description}') =>T_CS('\end{CMP@description}'));});
sub useCMPItemizations {
    Let(T_CS('\begin{itemize}')    =>T_CS('\begin{CMP@itemize}'));
    Let(T_CS('\begin{enumerate}')  =>T_CS('\begin{CMP@enumerate}'));
    Let(T_CS('\begin{description}')=>T_CS('\begin{CMP@description}'));
    return; }
sub declareFunctions{
  my ($stomach,$whatsit) = @_;
  my $keyval = $whatsit->getArg(1);
  my $funval = KeyVal($keyval,'functions') if KeyVal($keyval,'functions');
  my @funsymbs = ParseKeyValList($funval);
  #Unread the function declarations at the Gullet
  foreach (@funsymbs) {
    $stomach->getGullet->unread(Tokenize('\lxDeclare[role=FUNCTION]{$'.$_.'$}')->unlist);
  }
  return;
}
Tag('omdoc:CMP', afterOpen => sub {AssignValue('_LastSeenCMP', $_[1], 'global');return;});#$
Tag('omdoc:li', autoClose=>1);
Tag('omdoc:dd', autoClose=>1);
Tag('omdoc:di', autoClose=>1);
%</ltxml>
%    \end{macrocode}
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:impl:mtxt]{Mathematical Text}
%
% We define the actions that are undertaken, when the keys are encountered. Here this is
% very simple, we just define an internal macro with the value, so that we can use it
% later. Note that we allow math in the |title| field, so we do not declare it to be
% |Semiverbatim| (indeed not at all, which allows it by default). 
%
%    \begin{macrocode}
%<*package>
\srefaddidkey{omtext}
\addmetakey[]{omtext}{functions}
\addmetakey*{omtext}{display}
\addmetakey{omtext}{for}
\addmetakey{omtext}{from}
\addmetakey{omtext}{type}
\addmetakey*{omtext}{title}
\addmetakey*{omtext}{start}
\addmetakey{omtext}{theory}
\addmetakey{omtext}{continues}
\addmetakey{omtext}{verbalizes}
%</package>
%<*ltxml>
DefKeyVal('omtext','functions','Semiverbatim');
DefKeyVal('omtext','display','Semiverbatim');
DefKeyVal('omtext','for','Semiverbatim');
DefKeyVal('omtext','from','Semiverbatim');
DefKeyVal('omtext','type','Semiverbatim');
DefKeyVal('omtext','title','Plain'); #Math mode in titles.
DefKeyVal('omtext','start','Plain'); #Math mode in start phrases
DefKeyVal('omtext','theory','Semiverbatim');
DefKeyVal('omtext','continues','Semiverbatim');
DefKeyVal('omtext','verbalizes','Semiverbatim');
%</ltxml>
%    \end{macrocode}
%
% \begin{macro}{\st@flow}
% We define this macro, so that we can test whether the |display| key has the value |flow|
%    \begin{macrocode}
%<*package>
\def\st@flow{flow}
%</package>
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{omtext}
%   The |omtext| environment is different, it does not have a keyword that marks
%   it. Instead, it can have a title, which is used in a similar way. We redefine the
%   |\lec| macro so the trailing |\par| does not get into the way.
%    \begin{macrocode}
%<*package>
\def\omtext@pre@skip{\smallskip}
\def\omtext@post@skip{}
\providecommand{\stDMemph}[1]{\textbf{#1}}
\newenvironment{omtext}[1][]{\bgroup\metasetkeys{omtext}{#1}\sref@label@id{this paragraph}%
\def\lec##1{\@lec{##1}}
\ifx\omtext@display\st@flow\else\omtext@pre@skip\par\noindent%
\ifx\omtext@title\@empty\else\stDMemph{\omtext@title}: \fi\fi\ignorespaces}
{\egroup\omtext@post@skip}
%</package>
%<*ltxml>
DefCMPEnvironment('{omtext} OptionalKeyVals:omtext',
		  "<omdoc:omtext "
		     . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')() "
		     . "?&KeyVal(#1,'type')(type='&KeyVal(#1,'type')')() "
		     . "?&KeyVal(#1,'for')(for='&KeyVal(#1,'for')')() "
	             . "?&KeyVal(#1,'from')(from='&KeyVal(#1,'from')')()>"
		  . "?&KeyVal(#1,'title')(<dc:title>&KeyVal(#1,'title')</dc:title>)()"
		  . "<omdoc:CMP>"
                  .   "<omdoc:p>"
		  .     "?&KeyVal(#1,'start')(<omdoc:phrase type='startemph'>&KeyVal(#1,'start')</omdoc:phrase>)()"
                  .     "#body");
%</ltxml>
%    \end{macrocode}
% \end{environment}
%
% We also make our life easier If defining an environment that is
% turned into something that contains |<CMP>|\meta{body}|</CMP>|, use this method instead
%    \begin{macrocode}
%<*ltxml>
sub DefCMPEnvironment {
  my ($proto, $replacement, %options) = @_;
  my @before = $options{beforeDigest} ? ($options{beforeDigest}) : ();
  push(@before, \&useCMPItemizations);
  $options{beforeDigest} = \@before;
  my @after = $options{afterDigestBegin} ? ($options{afterDigestBegin}) : ();
  push(@after, \&declareFunctions);
  $options{afterDigestBegin} = \@after;
  DefEnvironment($proto, $replacement, %options);
}
sub DefCMPConstructor {
  my ($proto, $replacement, %options) = @_;
  my @before = $options{beforeDigest} ? ($options{beforeDigest}) : ();
  push(@before, \&useCMPItemizations);
  $options{beforeDigest} = \@before;
  DefConstructor($proto, $replacement, %options);
}#$
%</ltxml>
%    \end{macrocode}
% \end{omgroup}
%
% \begin{omgroup}[id=sec:impl:phrase]{Phrase-level Markup}
% 
% \begin{environment}{phrase}
%    For the moment, we do disregard the most of the keys
%    \begin{macrocode}
%<*package>
\srefaddidkey{phrase}
\addmetakey{phrase}{style}
\addmetakey{phrase}{class}
\addmetakey{phrase}{index}
\addmetakey{phrase}{verbalizes}
\addmetakey{phrase}{type}
\newenvironment{phrase}[1][]{\metasetkeys{phrase}{#1}}{}
%</package>
%<*ltxml>
DefKeyVal('phrase','id','Semiverbatim');
DefKeyVal('phrase','style','Semiverbatim');
DefKeyVal('phrase','class','Semiverbatim');
DefKeyVal('phrase','index','Semiverbatim');
DefKeyVal('phrase','verbalizes','Semiverbatim');
DefKeyVal('phrase','type','Semiverbatim');
DefConstructor('\phrase OptionalKeyVals:phrase {}',
	       "<omdoc:phrase %&KeyVals(#1)>#2</omdoc:phrase>");
%</ltxml>
%    \end{macrocode}
% \end{environment}
%
% \begin{environment}{nlex}
%    For the moment, we do disregard the most of the keys
%    \begin{macrocode}
%<*package>
\def\nlex#1{\green{\sl{#1}}}
\def\nlcex#1{*\green{\sl{#1}}}
%</package>
%<*ltxml>
DefConstructor('\nlex{}',
   "<omdoc:phrase type='nlex'>#1</omdoc:phrase>");
DefConstructor('\nlcex{}',
   "<omdoc:phrase type='nlcex'>#1</omdoc:phrase>");
%</ltxml>
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{sinlinequote}
%    \begin{macrocode}
%<*package>
\def\@sinlinequote#1{``{\sl{#1}}''}
\def\@@sinlinequote#1#2{\@sinlinequote{#2}~#1}
\newcommand{\sinlinequote}[2][]
{\def\@opt{#1}\ifx\@opt\@empty\@sinlinequote{#2}\else\@@sinlinequote\@opt{#2}\fi}
%</package>
%<*ltxml>
DefConstructor('\sinlinequote [] {}',
               "<omdoc:phrase type='inlinequote'>"
               . "?#1(<dc:source ?#locator(stex:srcref='#locator')()>#1</dc:source>\n)()"
               . "#2"
             . "</omdoc:phrase>");
%</ltxml>
%    \end{macrocode}
% \end{macro}
% \end{omgroup}
%
% \begin{omgroup}[id=sec:impl:block]{Block-Level Markup}
%
% \begin{environment}{sblockquote}
%  \ednote{describe above}
%    \begin{macrocode}
%<*package>
\def\begin@sblockquote{\begin{quote}\sl}
\def\end@sblockquote{\end{quote}}
\def\begin@@sblockquote#1{\begin@sblockquote}
\def\end@@sblockquote#1{\def\@@lec##1{{\rm ##1}}\@lec{#1}\end@sblockquote}
\newenvironment{sblockquote}[1][]
  {\def\@opt{#1}\ifx\@opt\@empty\begin@sblockquote\else\begin@@sblockquote\@opt\fi}
  {\ifx\@opt\@empty\end@sblockquote\else\end@@sblockquote\@opt\fi}
%</package>
%<*ltxml>
DefEnvironment('{sblockquote} []',
               "?#1(<omdoc:omtext type='quote'>"
               .     "<dc:source>#1</dc:source>"
               .     "#body"
             . "    </omdoc:omtext>)"
             .    "(<omdoc:p class='quote'>#body</omdoc:p>)");
%</ltxml>
%    \end{macrocode}
% \end{environment}
%
% The line end comment macro makes sure that it will not be forced on the next line unless
% necessary.
% \begin{macro}{\lec}
%   The actual appearance of the line end comment is determined by the |\@@lec| macro,
%   which can be customized in the document class. The basic one here is provided so that
%   it is not missing.
%    \begin{macrocode}
%<*package>
\providecommand{\@@lec}[1]{(#1)}
\def\@lec#1{\strut\hfil\strut\null\nobreak\hfill\hbox{\@@lec{#1}}}
\def\lec#1{\@lec{#1}\par}
%</package>
%<*ltxml>
DefConstructor('\lec{}',
   "\n<omdoc:note type='line-end-comment'>#1</omdoc:note>");
%</ltxml>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\my*graphics}
% We set up a special treatment for including graphics to respect the intended {\omdoc}
% document structure. The main work is done in the transformation stylesheet though. 
% 
%    \begin{macrocode}
%<ltxml>RawTeX('
%<*ltxml|package>
\newcommand\mygraphics[2][]{\includegraphics[#1]{#2}}
\newcommand\mycgraphics[2][]{\begin{center}\includegraphics[#1]{#2}\end{center}}
\newcommand\mybgraphics[2][]{\fbox{\includegraphics[#1]{#2}\end{center}}}
%</ltxml|package>
%<ltxml>');
%    \end{macrocode}
% \end{macro}
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:impl:index]{Index Markup}
%
%    \begin{macrocode}
%<*package>
\newcommand{\omdoc@index}[2][]{\def\@test{#1}%
\ifindex\ifx\@test\@empty\index{#2}\else\index{#1@#2}\fi\fi}  
\newcommand{\indexalt}[3][]{{#2}\omdoc@index[#1]{#3}}               % word in text and index
\newcommand{\indextoo}[2][]{{#2}\omdoc@index[#1]{#2}}               % word in text and index
%</package>
%    \end{macrocode}
%
% this puts two-compound words into the index in various permutations
%
%    \begin{macrocode}
%<*package>
\newcommand{\@twin}[3][]{\def\@test{#1}%
\ifindex\ifx\@test\@empty\index{#2!#3}\else\index{#1@#2!#3}\fi\index{#3!#2}\fi}
\newcommand{\twinalt}[4][]{#2\@twin[#1]{#3}{#4}}
\newcommand{\twintoo}[3][]{{#2 #3}\@twin[#1]{#2}{#3}}             % and use the word compound too
%</package>
%    \end{macrocode}
%
% this puts adjectivized two-compound words into the index in various
% permutations\ednote{what to do with the optional argument here and below?}
%
%    \begin{macrocode}
%<*package>
\newcommand{\@atwin}[4][]{\def\@test{#1}%
\ifindex\ifx\@test\@empty\index{#2!#3!#4}\else\index{#1@#2!#3!#4}\fi\index{#3!#2 (#1)}\fi}
\newcommand{\atwinalt}[5][]{#2\@atwin[#1]{#3}{#4}{#4}}
\newcommand{\atwintoo}[4][]{{#2 #3 #4}\@atwin[#1]{#2}{#3}{#4}}         % and use it too
%</package>
%<*ltxml>
DefConstructor('\indextoo[]{}',
	       "<omdoc:idx>"
	      .  "<omdoc:idt>#2</omdoc:idt>"
	      .  "<omdoc:ide ?#1(sort-by='#1')()>"
	      .    "<omdoc:idp>#2</omdoc:idp>"
	      .  "</omdoc:ide>"
	      ."</omdoc:idx>");
DefConstructor('\indexalt[]{}{}',
	       "<omdoc:idx>"
	      .  "<omdoc:idt>#2</omdoc:idt>"
	      .  "<omdoc:ide ?#1(sort-by='#1')()>"
	      .    "<omdoc:idp>#3</omdoc:idp>"
	      .  "</omdoc:ide>"
	      ."</omdoc:idx>");
%</ltxml>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*ltxml>
DefConstructor('\twintoo[]{}{}',
	       "<omdoc:idx>"
	      .  "<omdoc:idt>#2 #3</omdoc:idt>"
	      .  "<omdoc:ide ?#1(sort-by='#1')()>"
	      .    "<omdoc:idp>#2</omdoc:idp>"
	      .    "<omdoc:idp>#3</omdoc:idp>"
	      .  "</omdoc:ide>"
	      ."</omdoc:idx>");
DefConstructor('\twinalt[]{}{}{}',
	       "<omdoc:idx>"
	      .  "<omdoc:idt>#2</omdoc:idt>"
	      .  "<omdoc:ide ?#1(sort-by='#1')()>"
	      .    "<omdoc:idp>#2</omdoc:idp>"
	      .    "<omdoc:idp>#3</omdoc:idp>"
	      .  "</omdoc:ide>"
	      ."</omdoc:idx>");
%</ltxml>
%    \end{macrocode}
%
%    \begin{macrocode}
%<*ltxml>
DefConstructor('\atwintoo[]{}{}{}',
	       "<omdoc:idx>"
	      .  "<omdoc:idt>#2 #3</omdoc:idt>"
	      .  "<omdoc:ide ?#1(sort-by='#1')()>"
	      .    "<omdoc:idp>#2</omdoc:idp>"
	      .    "<omdoc:idp>#3</omdoc:idp>"
	      .    "<omdoc:idp>#4</omdoc:idp>"
	      .  "</omdoc:ide>"
	      ."</omdoc:idx>");

DefConstructor('\atwinalt[]{}{}{}{}',
	       "<omdoc:idx>"
	      .  "<omdoc:idt>#2</omdoc:idt>"
	      .  "<omdoc:ide ?#1(sort-by='#1')()>"
	      .    "<omdoc:idp>#2</omdoc:idp>"
	      .    "<omdoc:idp>#3</omdoc:idp>"
	      .    "<omdoc:idp>#4</omdoc:idp>"
	      .  "</omdoc:ide>"
	      ."</omdoc:idx>");
%</ltxml>
%    \end{macrocode}
% \end{omgroup}
% 
% \begin{omgroup}{{\LaTeX} Commands we interpret differently}
%
% The first think we have to take care of are the paragraphs, we want to generate {\omdoc}
% that uses the |omdoc:p| element for paragraphs inside |CMP|s. For that we have modified
% the DTD only to allowed |omdoc:p| elements in |omdoc:CMP| (in particular no text). Then
% we instruct the |\par| macro to close a |omdoc:p| element if possible. The next
% |omdoc:p| element is then opened automatically, since we make |omdoc:p| and |omdoc:CMP|
% autoclose and autoopen.
%
%    \begin{macrocode}
%<*ltxml>
DefConstructor('\par',sub { $_[0]->maybeCloseElement('omdoc:p'); },alias=>"\\par\n");
Tag('omdoc:p', autoClose=>1, autoOpen=>1);
Tag('omdoc:CMP', autoClose=>1, autoOpen=>1);
Tag('omdoc:omtext', autoClose=>1, autoOpen=>1);
%</ltxml>#$
%    \end{macrocode}
% the rest of the reinterpretations is quite simple, we either disregard presentational
% markup or we re-interpret it in terms of {\omdoc}.
%    \begin{macrocode}
%<package>\def\omspace#1{\hspace*{#1}}
%<*ltxml>
DefConstructor('\omspace{}','');  
DefConstructor('\emph{}',"<omdoc:phrase class='emphasis'>#1</omdoc:phrase>");
DefConstructor('\em',"<omdoc:phrase class='emphasis'>");
DefConstructor('\texttt{}',"<omdoc:phrase class='code'>#1</omdoc:phrase>"); 
DefConstructor('\tt',"<omdoc:phrase class='code'>"); 
DefConstructor('\textbf{}',"<omdoc:phrase class='bold'>#1</omdoc:phrase>"); 
DefConstructor('\bf',"<omdoc:phrase class='bold'>"); 
DefConstructor('\textsf{}',"<omdoc:phrase class='sans-serif'>#1</omdoc:phrase>"); 
DefConstructor('\sf',"<omdoc:phrase class='sans-serif'>"); 
DefConstructor('\textsl{}',"<omdoc:phrase class='slanted'>#1</omdoc:phrase>"); 
DefConstructor('\sl',"<omdoc:phrase class='slanted'>"); 
DefConstructor('\textit{}',"<omdoc:phrase class='italic'>#1</omdoc:phrase>"); 
DefConstructor('\it',"<omdoc:phrase class='italic'>"); 
Tag('omdoc:phrase', autoClose=>1);
DefEnvironment('{center}','#body');
DefEnvironment('{flushleft}','#body');
DefEnvironment('{flushright}','#body');
DefEnvironment('{minipage}[]{}','#body');
DefEnvironment('{quote}',
    "<omdoc:phrase type='quote' style='display:block'>"
   .  "#body"
   ."</omdoc:phrase>");
DefEnvironment('{quotation}',
    "<omdoc:phrase type='quote' style='display:block'>
   .  "#body"
   ."</omdoc:phrase>");
DefEnvironment('{LARGE}','#body');
DefEnvironment('{Large}','#body');
DefEnvironment('{large}','#body');
DefEnvironment('{small}','#body');
DefEnvironment('{footnotesize}','#body');
DefEnvironment('{tiny}','#body');
DefEnvironment('{scriptsize}','#body');
DefConstructor('\LARGE','');
DefConstructor('\Large','');
DefConstructor('\large','');
DefConstructor('\small',''); 
DefConstructor('\footnotesize',''); 
DefConstructor('\scriptsize',''); 
DefConstructor('\tiny',''); 
DefConstructor('\fbox{}','#1');
DefConstructor('\footnote[]{}',
       "<omdoc:note type='foot' ?#1(mark='#1')>#2</omdoc:note>");
DefConstructor('\footnotemark[]',"");
DefConstructor('\footnotetext[]{}',
	       "<omdoc:note class='foot' ?#1(mark='#1')>#2</omdoc:note>");
DefConstructor('\sf', '');
DefConstructor('\sc', '');
%</ltxml>
%    \end{macrocode}
% \end{omgroup}
% 
% \begin{omgroup}[id=sec:impl:ids]{Providing IDs for {\omdoc} Elements}
% 
%   To provide default identifiers, we tag all {\omdoc} elements that allow |xml:id|
%   attributes by executing the |numberIt| procedure below.
% 
%    \begin{macrocode}
%<*ltxml>
Tag('omdoc:p',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:omtext',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:omgroup',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:CMP',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:link',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:meta',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:resource',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:ul',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:li',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:di',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:dt',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:dd',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:ol',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:dl',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:idx',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:phrase',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('omdoc:note',afterOpen=>\&numberIt,afterClose=>\&locateIt);
%</ltxml>
%    \end{macrocode}
% We also have to number some {\latexml} tags, so that we do not get into trouble with the
% \omdoc tags inside them.
%    \begin{macrocode}
%<*ltxml>
Tag('ltx:tabular',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('ltx:thead',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('ltx:td',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('ltx:tr',afterOpen=>\&numberIt,afterClose=>\&locateIt);
Tag('ltx:caption',afterOpen=>\&numberIt,afterClose=>\&locateIt);
%</ltxml>
%    \end{macrocode}
% The |numberIt| procedure gets the prefix from first parent with an |xml:id| attribute and then
% extends it with a label that reflects the number of preceding siblings, provided that
% there is not already an identifier. Additionally, it estimates an XPointer position in the original document
% of the command sequence which produced the tag.
% The |locateIt| subroutine is a sibling of |numberIt| as it is required as an |afterClose| handle for tags
% produced by {\LaTeX} environments, as opposed to commands. |locateIt| estimates an XPointer end position of
% the LaTeX environment, allowing to meaningfully locate the entire environment at the source.
%    \begin{macrocode}
%<*ltxml>
sub numberIt {
  my($document,$node,$whatsit)=@_;
  my(@parents)=$document->findnodes('ancestor::*[@xml:id]',$node);
  my $prefix= (@parents ? $parents[$#parents]->getAttribute('xml:id')."." : '');
  my(@siblings)=$document->findnodes('preceding-sibling::*[@xml:id]',$node);
  my $n = scalar(@siblings)+1;
  my $id = ($node -> getAttribute('xml:id'));
  $node->setAttribute('xml:id'=>$prefix."p$n") unless $id;
  my $about = $node -> getAttribute('about');
  $node->setAttribute('about'=>'#'.$node->getAttribute('xml:id')) unless $about;
  #Also, provide locators:
  my $locator = $whatsit->getProperty('locator');
  #Need to inherit locators if missing:
  $locator = (@parents ? $parents[$#parents]->getAttribute('stex:srcref') : '') unless $locator;
  $node->setAttribute('stex:srcref'=>$locator) if $locator; }
sub locateIt {
  my($document,$node,$whatsit)=@_;
  #Estimate trailer locator:
  my $trailer = $whatsit->getProperty('trailer');
  return unless $trailer; #Nothing we can do if the trailer isn't defined
  $trailer = $trailer->getLocator;
  return unless ($trailer &&  $trailer!~/^\s*$/); #Useless if broken
  my $locator = $node->getAttribute('stex:srcref');
  if ($locator) {
    $locator =~ /^(.+from=\d+;\d+)/;
    my $from = $1;
    $trailer =~ /(,to=\d+;\d+.+)$/;
    my $to = $1;
    $locator = $from.$to;
  } else {
    $locator = $trailer; #This should never happen
  }
  $node->setAttribute('stex:srcref' => $locator);
}
%</ltxml>#$
%    \end{macrocode}
% \end{omgroup}
% 
% \begin{omgroup}{Finale}
%
% We need to terminate the file with a success mark for perl.
%    \begin{macrocode}
%<ltxml>1;
%    \end{macrocode}
% \end{omgroup}
%\end{omgroup}
% \Finale
\endinput
% \iffalse
% LocalWords:  GPL structuresharing STR omdoc dtx stex CPERL LoadClass url dc
%%% Local Variables: 
%%% mode: doctex
%%% TeX-master: t
%%% End: 
% \fi
% LocalWords:  RequirePackage RegisterNamespace namespace xsl DocType ltxml dtd
% LocalWords:  ltx DefEnvironment beforeDigest AssignValue inPreamble getGullet
% LocalWords:  afterDigest keyval omgroup DefKeyVal Semiverbatim KeyVal locator
% LocalWords:  OptionalKeyVals DefParameterType IfBeginFollows skipSpaces CMP
% LocalWords:  ifNext DefMacro needwrapper unlist DefConstructor omtext bgroup
% LocalWords:  useCMPItemizations RefStepItemCounter egroup beginItemize li di
% LocalWords:  beforeDigestEnd dt autoclose ul ol dl env showignores srcref def
% LocalWords:  afterOpen LastSeenCMP autoClose DefCMPEnvironment proto ToString
% LocalWords:  addAttribute nlex nlcex omdocColorMacro args tok MergeFont qw rm
% LocalWords:  TokenizeInternal toString isMath foreach maybeCloseElement id'd
% LocalWords:  autoOpen minipage footnotesize scriptsize numberIt whatsit href
% LocalWords:  getAttribute setAttribute OMDoc RelaxNGSchema noindex xml lec sc
% LocalWords:  Subsubsection useDefaultItemizations refundefinedtrue sblockquote
% LocalWords:  DefCMPConstructor sinlinequote idx idt ide idp emph  extrefs sref
% LocalWords:  flushleft flushright DeclareOption PassOptions undef cls iffalse
% LocalWords:  ProcessOptions subparagraph ignoresfalse ignorestrue raisebox tr
% LocalWords:  texorpdfstring latexml texttt fileversion maketitle newpage iff
% LocalWords:  tableofcontents newpage ednote obeylines usepackage indextoo Cwd
% LocalWords:  indextoo twintoo twintoo exfig vspace twinalt ldots ttin emin
% LocalWords:  renmanig myindex atwin atwin packge-local blockquote inlinequote
% LocalWords:  atwintoo atwinalt atwinalt printbibliography impl cwd newif ifx
% LocalWords:  ifindex indextrue indexfalse srefaddidkey smallskip showmeta
% LocalWords:  providecommand stDMemph textbf newenvironment hfil showmeta
% LocalWords:  noindent ignorespaces newcommand nobreak hfill hbox mygraphics
% LocalWords:  includegraphics mycgraphics mybgraphics fbox adjectivized hspace
% LocalWords:  printindex jobname.ind jobname.ind omspace footnotemark thead
% LocalWords:  footnotetext findnodes doctex textsf langle textsf langle funval
% LocalWords:  metakeys funsymbs addmetakey metasetkeys startemph textsl textit
