% Copyright (c) 2008  Ross Moore <ross@maths.mq.edu.au>
% mmap package -- include CMap resources for math symbols into PDF
%   to make "search" and "copy-n-paste" functions work properly
%
%  -m.cmap  CMap uses ascii strings for the macro-names
%  .cmap    CMap uses the Unicode code-point of the symbols
%
% You may distribute and/or modify this program under the terms of LPPL
% the program consists of mmap.sty and .cmap files:
%
%   {t1,lmr,ly1,oml,oms,omx,ot1,ulasy,umsa,umsb,ueuf,upsy,upzd}.cmap
%   {oml{b,m}it,omsb,ot1{rbxit,rbxn,rmit,rmn,ssbxn,ssmn,ttmn}}.cmap
%
%   {t1,oml,oms,omx,ot1,ueuf,ueufb,ulasy,umsa,umsb,upsy,upzd}-m.cmap
%   {oml{b,m}it,omsb,ot1{rbxit,rbxn,rmit,rmn,ssbxn,ssmn,ttmn}}-m.cmap
%
% Usage: 
%  put \usepackage{mmap}  to load CMAP resources from -m.cmap files.
%  Or put \usepackage[noTeX]{mmap}  to load CMAP resources from .cmap files.
%  Or put \usepackage[useTeX]{mmap} to load CMAP resources from -m.cmap files.
%
%  IMPORTANT:  place this immediately after the \documentclass line
%     to ensure that all fonts are checked for appropriate resources.
%
% TODO:
%   add *.cmap files for other font encodings (contributions are welcome):
%     TS1, OT2, IL2, ...
%   support dvips?
%
% History:
% 2008/08/11  Fixed error for <3D> character ('equals') in ot1*-m files.
%
% 2008/07/08  Adjusted the documentation in the header of this file.
%
% 2008/07/02  Full support for math styles in OT1 and Euler Fraktur.
%             Fixed loading to avoid multiple inclusion of CMaps.
%             Ensure default OT1 font cancelled, to get CMap for math.
%             Improved CMap ranges and support for Plane-0 math letters.
%             Added /CMapVersion number to all .cmap files
%
% 2008/06/29  Now has partial support for different math styles in OT1.
%
% 2008/05/26  First version, including patch for \setaccent .
%             Cancel the default pre-loaded main font, so it can reload
%             later with a associated CMap resource.
%         
% 2007/04/22  First attempt, to work seamlessly with cmap.sty
%             Previous work used a modified version of that package.
%         

\ProvidesPackage{mmap}[2008/08/11 v1.03 CMAP support for math in PDF]

\@ifundefined{pdffontattr}{%
% The  mmap  package can be used only with pdflatex,
% but not with ordinary latex
  \PackageWarningNoLine{mmap}{pdftex not detected - will not do anything}%
  \endinput
}\relax
\ifnum\pdfoutput<1
  \PackageWarningNoLine{mmap}{pdftex in DVI mode - will not do anything}
  \expandafter\endinput
\fi
\RequirePackage{cmap}
\RequirePackage{ifpdf}
\let\real@cmap@load\cmap@load

\bgroup \catcode`\m 12\relax
 \def\next{\egroup\def\nonletter@style{m}}%
\next
{\catcode`\U 12\relax \catcode`\O 12\relax \catcode`\T 12\relax
 \catcode`\M 12\relax \catcode`\L 12\relax \catcode`\S 12\relax 
 \gdef\mmap@enc@unknown@{U}%
 \gdef\mmap@enc@math@{OML}%
 \gdef\mmap@enc@symb@{OMS}%
 \gdef\mmap@enc@oldtex@{OT1}%
 \gdef\mmap@enc@newtex@{T1}%
 \gdef\mmap@oti@cancel@#1/#2/#3/#4/#5@@{%
  \def\oti@font@name{OT1/#2/#3/#4/#5}%
  \expandafter\let\csname\oti@font@name\endcsname\relax
 }%
 \gdef\mmap@enc@getname@#1/#2/#3/#4/#5@@{%
  \def\cmap@f@namestyle{#1-#3}%
  \def\this@f@style{#3}%
  \ifx\nonletter@style\this@f@style
   \def\cmap@f@encoding{u#2}%
  \else  % use the style when not 'm'
   \def\cmap@f@encoding{u#2#3}%
  \fi}%
 \gdef\mmap@enc@getmathname@#1/#2/#3/#4/#5@@{%
  \def\cmap@f@namestyle{#1-#3}%
  \def\cmap@f@encoding{oml#3#4}}%
 \gdef\mmap@enc@getsymbname@#1/#2/#3/#4/#5@@{%
  \def\cmap@f@namestyle{#1-#3}%
  \def\this@f@style{#3}%
  \ifx\nonletter@style\this@f@style
   \def\cmap@f@encoding{oms}%
  \else  % use the style when not 'm'
   \def\cmap@f@encoding{oms#3}%
  \fi}%
 \gdef\mmap@enc@oldtexname@#1/#2/#3/#4/#5@@{%
  \def\cmap@f@namestyle{#1-#3}%
  \ifmmode\def\cmap@f@encoding{ot1#2#3#4}%
  \else\def\cmap@f@encoding{ot1}\fi}%
 \gdef\mmap@enc@newtexname@#1/#2/#3/#4/#5@@{%
  \def\cmap@f@namestyle{#1-#3}%
  \ifmmode\def\cmap@f@encoding{t1#2#3#4}%
  \show\cmap@f@encoding % this is not accessed normally
  \else\def\cmap@f@encoding{t1}\fi}%
}%
%
% strip the 'cm' part from the resulting name
{\catcode`\m 12\relax \catcode`\c 12\relax
 \gdef\strip@CM@prefix@#1cm#2@#3!{%
  \def\this@f@enCoding{#1#2}}%
}%  end of \catcode
\def\strip@CM@prefix{%
 \expandafter\strip@CM@prefix@\cmap@f@encoding @cm@!%
 \edef\cmap@f@encoding{\this@f@enCoding}}
%
%
%  extra indirection, to allow features to be easily isolated
%  when doing detailed testing
\edef\mmap@enc@unknown{\mmap@enc@unknown@}
\edef\mmap@enc@math{\mmap@enc@math@}
\edef\mmap@enc@symb{\mmap@enc@symb@}
\edef\mmap@enc@oldtex{\mmap@enc@oldtex@}
\edef\mmap@enc@newtex{\mmap@enc@newtex@}
%
\def\mmap@cmap@load{%
 \ifx\cmap@f@encoding\mmap@enc@unknown
  % check unknown encoding for math support
  \expandafter\expandafter\expandafter\mmap@enc@getname@\expandafter\string\font@name @@%
 \else % cmap doesn't get this far !
  % check OT1 encoding for old-tex letters
  \ifx\cmap@f@encoding\mmap@enc@oldtex
   \expandafter\expandafter\expandafter\mmap@enc@oldtexname@\expandafter\string\font@name @@%
   \ifmmode\strip@CM@prefix\fi
  \else 
  % check T1 encoding for new-tex letters
  \ifx\cmap@f@encoding\mmap@enc@newtex
   \expandafter\expandafter\expandafter\mmap@enc@newtexname@\expandafter\string\font@name @@%
   \ifmmode\strip@CM@prefix\fi
  \else 
  % check OML encoding for math style
  \ifx\cmap@f@encoding\mmap@enc@math
   \expandafter\expandafter\expandafter\mmap@enc@getmathname@\expandafter\string\font@name @@%
  \else 
  % check OMS encoding for math style
  \ifx\cmap@f@encoding\mmap@enc@symb
   \expandafter\expandafter\expandafter\mmap@enc@getsymbname@\expandafter\string\font@name @@%
  \else 
   % write out a message to the .log file, but don't change the encoding,
   % unless \mmap@enc@getname@ alters the value of \this@f@encoding 
   \edef\this@f@encoding{\cmap@f@encoding}%
   \expandafter\expandafter\expandafter\mmap@enc@getname@\expandafter\string\font@name @@%
   \typeout{\cmap@f@namestyle\space encoding encountered}%
   \edef\cmap@f@encoding{\this@f@encoding}%
  \fi\fi\fi\fi
 \fi
 \mmap@filecheck@
}
\def\mmap@filecheck@@{%
 \edef\reserved@f{\lowercase{\def\noexpand\reserved@f{\cmap@f@encoding\mmap@end@}}}%
 \reserved@f
 \IfFileExists{\reserved@f}{\mmap@loadi}{%
  \PackageWarning{mmap}{!!! No \mmap@end@\space file found for \cmap@f@encoding\space !!! }%
  \real@cmap@load}%  fall back to the original cmap loading
}
\let\mmap@filecheck@\mmap@filecheck@@

%  \cmap@hook  is used when loading math-versions
\let\real@cmap@hook\cmap@hook
\def\mmap@cmap@hook{%
 \edef\cmap@f@encoding{\f@encoding}%
 \let\mmap@filecheck@\relax
 \mmap@cmap@load
 \@ifundefined{cmap@set@\cmap@f@encoding}%
  {\mmap@filecheck@@}\relax
 \csname cmap@set@\cmap@f@encoding\endcsname
 \let\mmap@filecheck@\mmap@filecheck@@
}


% place the /ToUnincode resource and save its object reference
\def\mmap@loadi{%
 \immediate\pdfobj stream
 %attr {/Type /CIDFile}
   file {\reserved@f}%
 \expandafter\xdef\csname cmap@set@\cmap@f@encoding\endcsname{%
  \noexpand\expandafter\pdffontattr\noexpand\font@name
    {/ToUnicode \the\pdflastobj\space 0 R}}%
}


% for combining accent characters to work, they must come
% after the letter being accented. 
% The following coding achieves this; e.g. for OT1 encoded fonts.
\let\mmap@latex@add@accent\add@accent
\def\mmap@add@accent#1#2{%
 \hmode@bgroup 
  \let \hmode@start@before@group \@firstofone 
  \setbox\@tempboxa\hbox{%
   #2\global\mathchardef\accent@spacefactor\spacefactor}%
  #2\kern-\wd\@tempboxa
%  \ifdim\ht\@tempboxa>1ex\relax
   \dimen@=\ht\@tempboxa\advance\dimen@-1ex\relax
   \raise\dimen@\hbox to\wd\@tempboxa{\hss
    \accent#1{\vphantom{#2}}\hss}%
%  \else
%  \accent#1{%\vphantom{#2}
%   \vrule width\z@ height\ht\@tempboxa depth\dp\@tempboxa}%
% \fi
 \egroup 
 \spacefactor\accent@spacefactor
%
% \accent#1 #2\spacefactor\accent@spacefactor
}
\def\mmap@check@add@accent{%
 \ifx\mmap@end@\cmap@ending
  \let\add@accent\mmap@add@accent
 \else
  \let\add@accent\mmap@latex@add@accent
 \fi
}

%%% 
%%%   Handle some special cases
%%% 

%\OT1\c #1->
\def\mmap@OTcedilla#1{\bgroup
  \leavevmode\setbox\z@\hbox{#1}%
  {\ooalign{\unhbox\z@\crcr\hidewidth\char 24\hidewidth}}%
 \egroup
}
\def\mmap@OTcedillabefore#1{\bgroup
  \leavevmode\setbox\z@\hbox{#1}%
  {\ooalign{\cr\hidewidth\char 24\hidewidth\cr\raise\baselineskip\box\z@\cr\cr}}%
 \egroup
}
\def\mmap@bindOTcedilla{\expandafter\let\csname OT1\string\c\endcsname\mmap@OTcedilla}
\def\mmap@bindcedillabefore{%
 \expandafter\let\csname OT1\string\c\endcsname\mmap@OTcedillabefore
% \expandafter\let\csname T1\string\c\endcsname\mmap@TIcedillabefore
}

%\OT1\b #1->
\def\mmap@OTunderbar#1{%
  \hmode@bgroup \setbox\z@\hbox{#1}%
  \o@lign{\unhbox\z@\crcr\hidewidth\ltx@sh@ft{-3ex}\vbox to.2ex{\hbox{\char22}\vss}\hidewidth}%
 \egroup
}
\def\mmap@OTunderbarbefore#1{%
  \hmode@bgroup
  \o@lign{\relax#1\crcr\hidewidth\ltx@sh@ft{-3ex}\vbox to.2ex{\hbox{\char22}\vss}\hidewidth}%
 \egroup
}
\def\mmap@bindOTunderbar{\expandafter\let\csname OT1\string\b\endcsname\mmap@OTunderbar}
\def\mmap@bindunderbarbefore{%
 \expandafter\let\csname OT1\string\b\endcsname\mmap@OTunderbarbefore
% \expandafter\let\csname T1\string\b\endcsname\mmap@TIunderbarbefore
}

%\T1\c #1->
\def\mmap@TIcedilla#1{%
 \@text@composite\T1\c#1\@empty\@text@composite
  {\leavevmode \setbox \z@ \hbox {#1}%
   {\ooalign{\unhbox\z@\crcr\hidewidth\char 11\hidewidth}}%
  }%
}
\def\mmap@bindTIcedilla{\expandafter\let\csname T1\string\c\endcsname\mmap@TIcedilla}

%\T1\k #1->
\def\mmap@TIcedillabefore#1{%
 \@text@composite\T1\c#1\@empty\@text@composite
  {\hmode@bgroup\setbox\z@\hbox{#1}%
   \ooalign{\cr\hidewidth\char 11\hidewidth\cr\raise\baselineskip\box\z@\cr\cr}%
  \egroup}%
}
\def\mmap@bindTIcedillabefore{\expandafter\let\csname T1\string\c\endcsname\mmap@TIcedillabefore}

%\T1\k #1->
\def\mmap@TIcaronbefore#1{%
 \@text@composite\T1\c#1\@empty\@text@composite
  {\hmode@bgroup\setbox\z@\hbox{#1}%
   \ooalign{\cr\hidewidth\char 12\hidewidth\cr\raise\baselineskip\box\z@\cr\cr}%
  \egroup}%
}
\def\mmap@bindTIcaronbefore{\expandafter\let\csname T1\string\k\endcsname\mmap@TIcaronbefore}


%\OT1\d #1->
\def\mmap@underdotbefore#1{\bgroup
  \leavevmode\setbox\z@\hbox{#1}%
  \dimen@=\dp\z@ \advance\dimen@.4ex\relax
  {\ooalign{\cr\hidewidth\lower\dimen@\hbox{\char 46}\hidewidth\cr\raise\baselineskip\box\z@\cr\cr}}%
 \egroup
}
\def\mmap@bindunderdotbefore{%
 \expandafter\let\csname OT1\string\d\endcsname\mmap@underdotbefore
% \expandafter\let\csname T1\string\d\endcsname\mmap@underdotbefore
}

%\\OT1\r-A ->
\def\mmap@Aring{\mmap@add@accent{23}A}
\def\mmap@bindOTring{\expandafter\let\csname\string\OT1\string\r-A\endcsname\mmap@Aring}

%\OT1\L ->
%\OT1\l ->
\expandafter\let\expandafter\realOTL\csname OT1\string\L\endcsname
\expandafter\let\expandafter\realOTl\csname OT1\string\l\endcsname
\def\mmap@stroke#1#2{\hmode@bgroup
  \setbox\@tempboxa\hbox{#1}%
   \hbox to\wd\@tempboxa{#1%\global\mathchardef\accent@spacefactor\spacefactor
   \kern-\wd\@tempboxa\kern-#2em\hss\@xxxii\hfil}%
 \egroup 
 \spacefactor\accent@spacefactor
}
% These don't work well, as the combination isn't honored adequately
\def\mmap@bindOTLstroke{\expandafter\def\csname OT1\string\L\endcsname{\mmap@stroke{L}{.27}}}
\def\mmap@bindOTlstroke{\expandafter\def\csname OT1\string\l\endcsname{\mmap@stroke{l}{0}}}


%  cancel the current font, which have been preloaded without a CMap
%  when needed it will load again, this time having a CMap
%  also always cancel OT1, as this may be needed in math
\expandafter\expandafter\expandafter\mmap@oti@cancel@\expandafter\string\font@name @@%
\expandafter\let\font@name\relax

\def\mmap@ending{-m.cmap}
\def\cmap@ending{.cmap}
\DeclareOption{noTeX}{\let\mmap@end@\cmap@ending\mmap@check@add@accent}
\DeclareOption{useTeX}{\let\mmap@end@\mmap@ending\mmap@check@add@accent}
\def\mmapnotexcodes{\ds@noTeX\AtBeginDocument{\ds@noTeX}}
\def\mmapusetexcodes{\ds@useTeX\AtBeginDocument{\ds@useTeX}}
\ExecuteOptions{useTeX}%
\ProcessOptions
% Cannot delay the rebinding, since the .aux file or a package
% may cause font-loading without the correct CMap
\AtEndOfPackage{%
 \let\cmap@load\mmap@cmap@load
 \let\cmap@hook\mmap@cmap@hook
}
\ifx\mmap@end@\mmap@ending
 \AtEndOfPackage{\AtBeginDocument{%
   \mmap@bindcedillabefore
   \mmap@bindunderbarbefore
   \mmap@bindTIcedillabefore
   \mmap@bindTIcaronbefore
   \mmap@bindunderdotbefore
}}\else
 \AtEndOfPackage{\AtBeginDocument{%
   \mmap@bindOTring
   \mmap@bindOTcedilla
   \mmap@bindTIcedilla
%   \mmap@bindOTLstroke
%   \mmap@bindOTlstroke
}}\fi
\endinput