The following code (for use with pdfLaTeX) defines the command \zoombox[box line width]{contents}
. It creates a click-to-zoom box for fitting the second argument 'contents' into the AdobeReader window. A dotted line is drawn around the box if the optional 'box line width' is >0.
EDIT: The code has been optimized for presentation PDFs (such as beamer
generated ones) looked at in full screen mode. The zoom-to box is now centred on the screen when clicked, as requested by @alfC.
\documentclass{beamer}
\usepackage{graphicx}
\usepackage{mwe}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% \zoombox[box line width]{contents}
%
% optimized version for beamer: in full screen, zoom boxes are centred
% in the viewer; useable with any documenclass
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatletter
\newsavebox\zb@x
\newcounter{z@@m}
\usepackage{calc}
\newdimen\B@r\newdimen\P@r
\newdimen\@zw\newdimen\@zh\newdimen\@zd
\newcommand{\zoombox}[2][0]{%
\leavevmode%
\sbox\zb@x{#2}%
\setlength\B@r{1pt*\ratio{\wd\zb@x}{\ht\zb@x+\dp\zb@x}}%
\setlength\P@r{1pt*\ratio{\paperwidth}{\paperheight}}%
\ifdim\B@r>\P@r\relax%
\setlength\@zw{\wd\zb@x}\setlength\@zh{\@zw*\ratio{\paperheight}{\paperwidth}}%
\setlength\@zd{(\@zh-\ht\zb@x-\dp\zb@x)*\real{0.5}+\dp\zb@x}%
\setlength\@zh{\@zh-\@zd}%
\else%
\setlength\@zh{\ht\zb@x+\dp\zb@x}%
\setlength\@zw{\@zh*\ratio{\paperwidth}{\paperheight}}%
\setlength\@zh{\ht\zb@x}\setlength\@zd{\dp\zb@x}%
\fi%
\makebox[0pt][l]{\makebox[\wd\zb@x][c]{\makebox[\@zw][l]{%
\pdfdest name {zbfs\thez@@m} fitr
width \@zw\space
height \@zh\space
depth \@zd\space
}}}%
\pdfdest name {zb\thez@@m} fitr
width \wd\zb@x\space
height \ht\zb@x\space
depth \dp\zb@x\space
\immediate\pdfannot
width \wd\zb@x\space
height \ht\zb@x\space
depth \dp\zb@x\space
{%
/Subtype/Link/H/N
/Border [0 0 #1 [1 2]]
/A <<
/S/JavaScript
/JS (
if(typeof(zoomed)=='undefined'||!zoomed){
var lastView=this.viewState;
if(app.fs.isFullScreen) this.gotoNamedDest('zbfs\thez@@m');
else this.gotoNamedDest('zb\thez@@m');
zoomed=true;
}else{
this.viewState=lastView;
zoomed=false;
}
)
>>
}%
\usebox{\zb@x}%
\stepcounter{z@@m}%
}
\makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\begin{frame}
\zoombox{\includegraphics[width=1cm]{example-image-a}}
\zoombox{\includegraphics[width=1cm]{example-image-b}}
\zoombox{\includegraphics[width=1cm]{example-image-c}}
\zoombox{\includegraphics[height=1cm]{example-image-golden}}
\zoombox{\includegraphics[width=1cm]{example-image-golden-upright}}
\end{frame}
\end{document}
The second example defines pairs of commands for marking opposing corners (lower left & upper right .OR. upper left & lower right) of a zoom box, and commands for marking text sequences/entire paragraphs.
\documentclass{article}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatletter
\InputIfFileExists{\jobname.zom}{}{}
\newwrite\zoomdat
\immediate\openout\zoomdat=\jobname.zom
\newcommand{\startzoombox}[2][0]{%
\leavevmode%
\pdfsavepos%
\protected@write\zoomdat{}{%
\string\expandafter\string\def\string\csname\space zb#2.ulx\string\endcsname{%
\noexpand\number\pdflastxpos}%
\string\expandafter\string\def\string\csname\space zb#2.uly\string\endcsname{%
\noexpand\number\pdflastypos}%
}%
\ifcsname zb#2.ulx\endcsname\ifcsname zb#2.lrx\endcsname%
\edef\zoomwd{\dimexpr \csname zb#2.lrx\endcsname sp- \csname zb#2.ulx\endcsname sp\relax}%
\edef\zoomdp{\dimexpr \csname zb#2.uly\endcsname sp- \csname zb#2.lry\endcsname sp\relax}%
\pdfdest name {zb#2.in} fitr
width \zoomwd
height 0pt
depth \zoomdp
\immediate\pdfannot
width \zoomwd
height 0pt
depth \zoomdp
{%
/Subtype/Link/H/N
/Border [0 0 1 [1 2]]
/A <<
/S/JavaScript
/JS (
if(typeof(zoomed)=='undefined'||!zoomed){
var lastView=this.viewState;
zoomed=true;
this.gotoNamedDest('zb#2.in');
}else{
this.viewState=lastView;
zoomed=false;
}
)
>>
}%
\fi\fi%
}
\def\stopzoombox#1{%\leavevmode%
\leavevmode%
\pdfsavepos%
\protected@write\zoomdat{}{%
\string\expandafter\string\def\string\csname\space zb#1.lrx\string\endcsname{%
\noexpand\number\pdflastxpos}%
\string\expandafter\string\def\string\csname\space zb#1.lry\string\endcsname{%
\noexpand\number\pdflastypos}%
}%
}
\def\startzoom{%
\stepcounter{@zb@id}%
\xdef\@lblStack{\the@zb@id.\@lblStack}%
\@ifstar\@startzoomstar\@startzoom%
}
\newcommand{\@startzoom}[1][0]{%
\raisebox{\baselineskip}[0pt][0pt]{\startzoombox[#1]{.\the@zb@id}}%
}
\newcommand{\@startzoomstar}[1][0]{%
\makebox[0pt][r]{\raisebox{\baselineskip}[0pt][0pt]{\startzoombox[#1]{.\the@zb@id}}%
\hspace{\parindent}}%
}
\def\stopzoom{%
\@ifstar\@stopzoomstar\@stopzoom%
}
\def\@stopzoom{%
\@popStack\@lblStack%
\raisebox{-1ex}[0pt][0pt]{\stopzoombox{.\@lblCur}}%
\xspace%
}
\def\@stopzoomstar{%
\@popStack\@lblStack%
\hfill\raisebox{-1ex}[0pt][0pt]{\stopzoombox{.\@lblCur}}%
\xspace%
}
\newcounter{@zb@id}
\def\@lblStack{}
\def\@popStack#1{\expandafter\@@popStack#1\nil}
\def\@@popStack#1.#2\nil{\gdef\@lblCur{#1}\gdef\@lblStack{#2}}
\RequirePackage{xspace}
\makeatother
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{document}
\section{Paragraph zooming}
\startzoom[1]First paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first \startzoom[1]\emph{Do not miss this one.}\stopzoom First paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph first paragraph.\stopzoom*
\startzoom*[1]Second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph second paragraph.\stopzoom*
\end{document}
The two commands for marking the corners of a zoom area are
\startzoombox[line width]{label}
and
\stopzoombox{label}
They are meant to be used in picture-making environments, such as pspicture
or tikzpicture
. Associated command pairs must be identified by unique labels.
For marking text and paragraphs the following commands have been provided:
\startzoom[lwidth]
\startzoom*[lwidth]
\stopzoom
\stopzoom*
The starred versions insert horizontal space (negative \parindent
on first line, \hfill
at the end of the paragraph).
Zoom areas may be nested. However, smaller ones should be placed on top of bigger ones (i.e. to appear later in the code), in order not to be obscured.
Note that at least two pdflatex
runs are necessary.
EDIT:
A dvipdfmx/XeLaTeX version of the \zoombox
macro is given in: How do I include a click-to-zoom thumbnail picture in a non-beamer document?
Worst case scenario, the PDF has the hyphens at the end of the line rendered as the same hyphen that sits between words, let's call them 'line break' and 'interword' hyphens for now.
That would mean they are indistinguishable automatically (an interword hyphen might coincide with a line break; impossible to detect). In which case, search & replace (with nothing) to get rid of all of them, then S&R for words that are now known to miss a hyphen. Sorry.
Better case scenario is that the actual characters inside the PDF are different, even though they might look the same. Copying & pasting, depending on your PDF reader, tends to lose that distinction, if it was there in the first place. Same issue makes for 'end of line' (EOL) characters for every visible line in the PDF, rather than one at the end of a paragraph. LaTeX doesn't mind (it looks for empty lines) but your other text editing needs or tooling might.
On the assumption you have been copying&pasting, you might be able to get more results to work with by extracting the text from the PDF automatically. Google for 'PDF to text'; there are a number of options available, from Windows GUI tools, to OS X builtin PDF handling (look into Automator) to command line tooling for UNIX/Linux/Cygwin environments.
The output would be plain text. Some tools perform or allow for some manipulation of the extracted text, preserving only actual line endings rather than merely the ones shown, etc.
For text manipulation perse, the typical command line tools in a UNIX environment would be able to get the bulk of your issues out of the way. That may or may not be useable advice to you, but I would reach for Vim, sed and a sprinkling of regular expressions all wrapped in some Bash.
Best Answer
I'm happy to report that it is possible, even if with some limitations:
app.execMenuItem("Copy");
requires privilege.That being said, here's an MWE:
setFocus
command requires a couple of milliseconds to work, and that, for some reason, theexecMenuItem("Copy")
command is executed before the former is done).You can actually also include this in a command of your own, as in e.g.
Now, as noted above, on my machine a pause between some of the commands is required, either via
setTimeOut
(which makes the function in its argument be executed after the given time has passed), or by making an alert pop up in between.I believe my trying to minimize the pauses in the
setTimeOut
approach has a negative impact on reliability (I got it to, for example, not remove the form after some testing), so perhaps a slightly higher number would be more appropriate (also considering that different machines may require higher or lower pauses).Please note, though, that this attempt was mostly a proof of concept; I doubt this is all that practical in the real world, at least not if the PDF is to be widely distributed. But I'd be happy to be proven wrong, especially by someone improving this answer. All the best!
Further reading:
execMenuItem
in JavaScript for Acrobat API Reference