// -*- ASCII:EDT -*-
// %b\Exec\Acrobat OpenDoc-Find.edt
// (schlicht 20070213)
/////////////////////////
// ============================================================================
// *** Forward search for PDF documents ***
// (Adobe Reader, Acrobat Professional, Sumatra PDF Viewer, Foxit Reader)
//
// If the document is compiled either
// * with a recent pdftex (>= 1.40.8) called with `--synctex=-1', or
// * with older pdftex versions using the `pdfsync' package (less reliable),
// the PDF file will be opened on the page corresponding to the current
// location of the caret.
// Otherwise, or in case the page couldn't be figured out, the default macro
// "Acrobat OpenDoc.edt" will be executed, jumping back to the last viewed page.
// ============================================================================
Requires(20061121); // 5.5 beta 3, because of %#?
PushTagsandRegisters;
Assign("SYNC_page");
// ----------------------------------------------------------------------------
// PDF-XChange Viewer not supported, as it cannot open the PDF on a specific page
FindInString("%$('AcroRead');","PDFXCview");
IfOK(!"JMP('fallback');");
// ----------------------------------------------------------------------------
// --synctex or pdfsync?
IfFileExists("%O\%N.synctex",>
!"Assign('SYNC_method','synctex');",>
!"IfFileExists('%O\%N.pdfsync',>
!'Assign(''SYNC_method'',''pdfsync'');',>
!'JMP(''fallback'');');");
GetPreamble("\begin{document}",5);
// don't bother checking whether the pdfsync package was really loaded
// --- pdfsync ----------------------------------------------------------------
//IfStr("%$('SYNC_method');","synctex","=","JMP('done_usepackage');");
//// FIXME: \usepackage{whatever,%%> pdfsync}
//FindInString("%!5","<@{^{\\|%%}}\\usepackage@{ |>}@{\[\(@{>|^{\]}}\)\]}@{ |>}\{@{>| |^{pdfsync|%%|\}}}pdfsync",8,9,11);
//IfOK("","JMP('open_PDF');");
//FindInString(",%#0,",",off,",8,9);
//IfOK("JMP('open_PDF');");
//:done_usepackage::
// ----------------------------------------------------------------------------
IfFileOlder("%O\%N.%$('SYNC_method');","%f",>
"StartWorking('PDF sync file is not up to date!');",>
"StartWorking('PDF sync: getting current page...');");
// ----------------------------------------------------------------------------
// The free Sumatra PDF viewer
// has built-in support for forward and inverse (!) search.
// It supports both pdfsync and synctex.
// (The -inverse-search command line option is actually not required to
// be given every time; once at installation time would be enough.)
FindInString("%$('AcroRead');","Sumatra");
IfOK(!`>
DDEOpen('%$("AcroRead");',"SUMATRA","control",1);>
IfOK("",!'>
Run(|%$("AcroRead"); -reuse-instance -inverse-search "\"%B\WinEdt.exe\" \"[Open(||%%f||);SelPar(%%l,8);]\"" "%P\%N.pdf"|,|%P|);>
DDEOpen("%$(|AcroRead|);",|SUMATRA|,|control|,1);');>
DDEExe('[ForwardSearch("%P\%N.pdf","%q%n%t",%!l,0)]');>
DDEClose;>
Wait(33);>
SetFocus("%N.pdf");>
PopTagsandRegisters;>
Exit;`);
// ============================================================================
// [the following may be replaced by a call to `synctex',
// once that program is included in the major distributions.]
GetDocAsASCII(0,"%O\%N.%$('SYNC_method');",0,0);
// get current file
// ----------------------------------------------------------------------------
// synctex: each file is assigned a number
// pdfsync: files are marked with parentheses (needs more massaging)
JMP("do_file");
:rem_dtx_synctex::
FindInString('%!0',':@{\"?%/P/?}\"?%N%T?>',8,9,1);
IfOK(!'ReplaceInString("%!0","",%!8,%!9,0,0);');
Return;
:rem_dtx_pdfsync::
FindInString('%!0','%\(%N%T%\',8,9,10);
IfOK(!'ReplaceInString("%!0","",0,%!9,0,0);');
Return;
:main_file_synctex::
// get file no.
FindInString("%!0",'',8,9,1);
IfOK(!"Assign('SYNC_file','%#1');",>
!"Prompt('synctex: File symbol not found. Something''s wrong.');JMP('open_PDF');");
Return;
:main_file_pdfsync::
Relax;
Return;
:not_main_file_synctex::
FindInString("%!0",'Input:\(1+$Numeric$\):%/q%n@{\"?%t?}>',8,9,1);
IfOK(!"Assign('SYNC_file','%#1');",// included file <>
!"JMP('open_PDF');");// not related to main file
Return;
:not_main_file_pdfsync::
FindInString("%!0",'<(\"?%n?@{\"?%t?}>',8,9,1);
IfOK(!"ReplaceInString('%!0','',0,%!9,0,0);",// included file <>
!"JMP('open_PDF');");// not related to main file
Return;
:do_file::
IfStr("%F","%f","=",>
!`// inside the preamble? <>
GetLength(5,"%!5");>
SetCLStart(0);>
CLToIndex(1,%l,6);>
IfNum(%!5,%!6,">","Assign('SYNC_page','1');JMP('open_PDF');");>
IfisMode("DTX","%!M",>
!"// DTX files include themselves, we don't want the first instance <>
Call('rem_dtx_%$(|SYNC_method|);');",>
!"// after \end{document}? <>
GetPreamble('\end{document}',5);>
GetLength(5,'%!5');>
SetCLStart(0);>
CLToIndex(1,%l,6);>
IfNum(%!5,%!6,'<','Assign(''SYNC_page'',''99999'');JMP(''open_PDF'');');>
");>
Call("main_file_%$('SYNC_method');");`,>
!`Call("not_main_file_%$('SYNC_method');");`>
);
// --- pdfsync ----------------------------------------------------------------
IfStr("%$('SYNC_method');","synctex","=","JMP('done_include');");
// remove included files
LetRegNum(5,0); // stack count
LetRegNum(6,0); // begin index
LetRegNum(9,-1);
Loop(!`>
SetOK(1);>
FindInString("%!0","<\((|)\)",8,9,1011,%!9+1);>
IfOK(!">
IfStr('%#0','(','=',>
!'IfNum(%!5,0,''='',''LetRegNum(6,%!8);'');>
LetRegNum(5,%!5+1);',>
!'LetRegNum(5,%!5-1);');",>
!"Break;");// my first Break; ! <>
// end of included file:
IfNum(%!5,0,"=",!">
ReplaceInString('%!0','',%!6,%!9+2,0,0);>
LetRegNum(9,'%!6-1');>
");>
// end of %f, remove rest:
IfNum(%!5,-1,"=",!"ExtractByIndex(0,'%!0',0,%!8-2);");>
`);
:done_include::
// get record from current line
// ----------------------------------------------------------------------------
// synctex: find first line "[(gkhvx\$],:*"
// pdfsync: find first line "l ", remember
LetRegNum(5,%l);
LetRegNum(9,0);
IfStr("%$('SYNC_method');","pdfsync","=","JMP('line_pdfsync');");
Loop(!`>
//StartWorking("trying line %!5");>
FindInString("%!0","%$('SYNC_file');,%!5:",8,9,1010,%!9);>
IfOK(!"// is it really a record? (look at previous character) <>
ExtractByIndex(7,'%!0',%!8-1,%!8-1);>
FindInString('%!7','[(gkhvx\$]',1,2,11);>
IfOK('Stop;');",>
!"IfNum(%!5,%l+50,'=',!'JMP(''open_PDF'');',!'LetRegNum(9,0);LetRegNum(5,%!5+1);');");>
`);
JMP("done_line");
:line_pdfsync:: ---------------------------------------------------------------
Loop(!`>
//StartWorking("trying line %!5");>
// instead of the straight-forward:
//FindInString("%!0","",8,9,11);>
//IfOK(!"LetRegNum(6,'%#0');Stop;",>
// we do a non-regex search, which is much faster:
FindInString("%!0"," %!5%\",8,9,10);>
IfOK(!"// is it really an "l" record? <>
FindInString('%!0','%\',6,7,1110,%!8);>
ExtractByIndex(7,'%!0',%!7+1,%!8);>
FindInString('%!7','l \(+[0-9]\) ',7,8,11);>
IfOK(!'LetRegNum(6,''%#0'');Stop;',>
!'ReplaceInString(|%!0|,||,%!6,%!9,0,0);');",>
!"IfNum(%!5,%l+100,'=','JMP(''open_PDF'');',!'LetRegNum(5,%!5+1);');");>
`);
LetRegNum(5,%!6);
:done_line::
// get page from record
// ----------------------------------------------------------------------------
// synctex: search backwards for "{"
// pdfsync: find position "p *", then search backwards for "s "
IfStr("%$('SYNC_method');","pdfsync","=","JMP('page_pdfsync');");
FindInString("%!0","<\{\(+$Numeric$\)>",8,9,1111,%!9);
IfOK(!"Assign('SYNC_page','%#0');","Prompt('synctex: Page not found. Something''s wrong.',3,1);");
JMP("done_page");
:page_pdfsync:: ---------------------------------------------------------------
// have to read it anew
GetDocAsASCII(0,"%O\%N.pdfsync",0,0);
Loop(!`>
// get position from current record
FindInString("%!0","%\p %!5 ",8,9,10);>
IfOK(!"// get page from current position <>
FindInString('%!0','',8,9,1111,%!9);>
IfOK(!'Assign(|SYNC_page|,|%#0|);');>
Stop;",>
!"IfNum(%!5,%!6+50,'=','JMP(''open_PDF'');',!'LetRegNum(5,%!5+1);');");>
`);
:done_page::
// ============================================================================
:open_PDF::
StopWorking;
IfStr("%$('SYNC_page');","","=","JMP('fallback');");
FindInString("%$('AcroRead');","Foxit");
IfOK(!`Run('%$("AcroRead"); "%P\%N.pdf" -n %$("SYNC_page"); ','%P');>
PopTagsandRegisters;>
Exit;`);
FindInString(`%$('AcroRead')`,'Adobe',1,2,1000,1);
IfOK(!"JMP('adobe')");
FindInString(`%$('AcroRead')`,'Acrobat.exe',1,2,1000,1);
IfOK(!"JMP('adobe')");
FindInString(`%$('AcroRead')`,'AcroRd',1,2,1000,1);
IfOK(!"JMP('adobe')");
// No Search ability for this PDF Viewer (GSView, PDF-XChange, etc...)
JMP('fallback');
:adobe:: =========================================================
Run('%$("AcroRead"); "%P\%N.pdf"','%P');
LetRegNum(0,"%$('SYNC_page');-1"); // Acrobat pages are 0-based
DDEOpen('%$("AcroRead");',"acroview","control");
DDEExe('[DocOpen("%P\%N.pdf")]');
DDEExe('[DocOpen("%P\%N.pdf")]');
DDEExe('[FileOpen("%P\%N.pdf")]');
DDEExe('[DocGoTo("%P\%N.pdf","%!0")]');
//DDEExe('[DocScrollTo("%P\%N.pdf","0","%$(|SYNC_y|);")]'); // no good, as it depends on zoom factor...
DDEExe('[AppShow()]');
DDEClose;
ProcessMessages;
// Fix Focus:
SendMessage("%$('Acro-Title');", $0000, $0000);
IfOK(!|SetFocus("%$('Acro-Title');");|);
SendMessage("%N.pdf - %$('Acro-Title');", $0000, $0000);
IfOK(!|SetFocus("%N.pdf - %$('Acro-Title');");|);
SendMessage("%$('Acro-Title'); - [%N.pdf]", $0000, $0000);
IfOK(!|SetFocus("%$('Acro-Title'); - [%N.pdf]");|);
ProcessMessages;
PopTagsandRegisters;
Exit;
// ----------------------------------------------------------------------------
:fallback::
PopTagsandRegisters;
Exe("%b\Exec\Acrobat OpenDoc.edt");
Exit;
// ============================================================================
$Id: Acrobat\040OpenDoc-Find.edt,v 1.6 2007-03-29 16:22:49+02 schlicht Exp schlicht $