[Okular-devel] [PATCH] Re: how to invoke okular with inverse search with pdf?

Jochen Trumpf Jochen.Trumpf at anu.edu.au
Wed Aug 26 05:49:41 CEST 2009


Hi,

I believe that this hasn't been implemented for pdf files, yet, but the following patch enables the functionality for me. I also copy an excerpt from my .emacs.d/init.el 
that configures the command. Note however the current limitations due to KDE bug #205076 and bug #205084. Despite its title the latter bug also affects pdf files.

I have no idea if the okular developers approve of the approach I have taken with this, but we will see, I guess.

--- generators/poppler/generator_pdf.h.old	2009-08-24 11:05:46.000000000 +1000
+++ generators/poppler/generator_pdf.h	2009-08-24 12:14:23.000000000 +1000
@@ -129,6 +129,8 @@
         void loadPdfSync( const QString & fileName, QVector<Okular::Page*> & pagesVector );
         // init the synctex parser if a synctex file exists
         void initSynctexParser( const QString& filePath );
+	// search document for source reference
+	void fillViewportFromSourceReference( Okular::DocumentViewport &viewport, const QString &reference ) const;
 
         Okular::TextPage * abstractTextPage(const QList<Poppler::TextBox*> &text, double height, double width, int rot);
 
--- generators/poppler/generator_pdf.cpp.old	2009-08-24 10:12:49.000000000 +1000
+++ generators/poppler/generator_pdf.cpp	2009-08-24 17:19:37.000000000 +1000
@@ -958,17 +958,27 @@
     }
     else if ( key == "NamedViewport" && !option.toString().isEmpty() )
     {
-        // asking for the page related to a 'named link destination'. the
-        // option is the link name. @see addSynopsisChildren.
         Okular::DocumentViewport viewport;
-        userMutex()->lock();
-        Poppler::LinkDestination *ld = pdfdoc->linkDestination( option.toString() );
-        userMutex()->unlock();
-        if ( ld )
-        {
-            fillViewportFromLinkDestination( viewport, *ld );
-        }
-        delete ld;
+
+	// if option starts with "src:" assume that we are handling a 
+	// source reference
+	if (option.toString().indexOf("src:", 0, Qt::CaseInsensitive) == 0)
+	{
+	    fillViewportFromSourceReference( viewport, option.toString() );
+	} 
+	else
+	{
+	    // asking for the page related to a 'named link destination'. the
+	    // option is the link name. @see addSynopsisChildren.
+	    userMutex()->lock();
+	    Poppler::LinkDestination *ld = pdfdoc->linkDestination( option.toString() );
+	    userMutex()->unlock();
+	    if ( ld )
+	    {
+	        fillViewportFromLinkDestination( viewport, *ld );
+	    }
+	    delete ld;
+	}
         if ( viewport.pageNumber >= 0 )
             return viewport.toString();
     }
@@ -1484,6 +1494,57 @@
     return 0;
 }
 
+void PDFGenerator::fillViewportFromSourceReference( Okular::DocumentViewport &viewport, const QString &reference ) const
+{
+    if  ( !synctex_scanner )
+        return;
+
+    // The reference is of form "src:1111Filename", where "1111"
+    // points to line number 1111 in the file "Filename".
+    // Extract the file name and the numeral part from the reference string.
+    // This will fail if Filename starts with a digit.
+    QString name, line;
+    // Remove "src:". Presence of substring has been checked before this 
+    // function is called.
+    name = reference.mid(4);
+    // split
+    quint32 max = name.length();
+    quint32 i = 0;
+    for(i=0; i<max; ++i) if ( !name[i].isDigit()) break;
+    line = name.left(i);
+    name = name.mid(i);
+    // Remove spaces.
+    name = name.trimmed();
+    line = line.trimmed();
+    // Convert line to integer. 
+    bool ok;
+    int m_line = line.toInt(&ok);
+    if (!ok) m_line = -1;
+    
+    // Use column == -1 for now.
+    if( synctex_display_query( synctex_scanner, name.toLatin1(), m_line, -1 ) > 0 )
+    {
+        synctex_node_t node;
+	// For now use the first hit. Could possibly be made smarter
+	// in case there are multiple hits.
+        while( (node = synctex_next_result(synctex_scanner)) ) 
+	{
+	    // TeX pages start at 1.
+	    viewport.pageNumber = synctex_node_page( node ) - 1;
+
+	    if (!viewport.isValid()) return;
+
+	    // TeX small points ...
+	    viewport.rePos.normalizedX = (synctex_node_h( node ) * dpiX) / (72.27 * 65536.0 * document()->page(viewport.pageNumber)->width());
+	    viewport.rePos.normalizedY = (synctex_node_v( node ) * dpiY) / (72.27 * 65536.0 * document()->page(viewport.pageNumber)->height());
+	    viewport.rePos.enabled = true;
+	    viewport.rePos.pos = Okular::DocumentViewport::TopLeft;
+	    
+	    return;
+        }
+    }
+}
+
 QWidget* PDFGenerator::printConfigurationWidget() const
 {
     if ( !pdfOptionsPage )

And here the init.el excerpt. Note that my solution completely overwrites the view commands, so you probably want to modify this.

(add-hook 'LaTeX-mode-hook '(lambda () 
  (add-to-list 'TeX-expand-list
	       '("%u" Okular-make-url))))
(setq TeX-output-view-style
      '(("^dvi$" "." "okular --unique %u")
	("^pdf$" "." "okular --unique %u")
	("^html?$" "." "firefox %o")))
(defun Okular-make-url () (concat
  "file://"
  (expand-file-name (funcall file (TeX-output-extension) t))
  "#src:"
  (TeX-current-line)
  (TeX-current-file-name-master-relative)))

Cheers,
Jochen

On Wed, 26 Aug 2009 07:31:59 Oliver Heins wrote:
> Hello,
>
> I compiled the latest okular from svn for being able to do inverse
> search with synctex/pdf.  It works great for okular->emacs.  Sadly, i
> have no idea of how i should invoke okular from within emacs to be put
> to right place in the pdf.  I tried things like
>
> okular --unique 'diss.pdf#src:40 ./Chapters/Chapter12.tex'
>
> but that did not work.
>
> How do i have to invoke okular?
>
> TIA,
>  olli


More information about the Okular-devel mailing list