From a3a90743203a26d3fc71f0d9ba58aeb645279d04 Mon Sep 17 00:00:00 2001 From: Jose Aliste Date: Sun, 27 Jun 2010 12:12:15 +0200 Subject: [PATCH] [libdocument] Add synctex methods to search backward and forward --- libdocument/Makefile.am | 12 ++-- libdocument/ev-document.c | 148 +++++++++++++++++++++++++++++++++++--- libdocument/ev-document.h | 26 +++++++ libdocument/ev-mapping.h | 7 -- 4 files changed, 174 insertions(+), 19 deletions(-) diff --git a/libdocument/Makefile.am b/libdocument/Makefile.am index 2d745406..dae69534 100644 --- a/libdocument/Makefile.am +++ b/libdocument/Makefile.am @@ -100,9 +100,10 @@ libevdocument_la_CPPFLAGS = \ $(AM_CPPFLAGS) libevdocument_la_CFLAGS = \ - $(LIBDOCUMENT_CFLAGS) \ - $(WARN_CFLAGS) \ - $(DISABLE_DEPRECATED) \ + $(LIBDOCUMENT_CFLAGS) \ + -I$(top_srcdir)/cut-n-paste/synctex \ + $(WARN_CFLAGS) \ + $(DISABLE_DEPRECATED) \ $(AM_CFLAGS) libevdocument_la_LDFLAGS = \ @@ -111,7 +112,10 @@ libevdocument_la_LDFLAGS = \ -export-symbols-regex "^ev_*" \ $(AM_LDFLAGS) -libevdocument_la_LIBADD = $(LIBDOCUMENT_LIBS) +libevdocument_la_LIBADD = \ + $(LIBDOCUMENT_LIBS) \ + $(top_builddir)/cut-n-paste/synctex/libsynctex.la + BUILT_SOURCES = \ ev-document-type-builtins.c \ diff --git a/libdocument/ev-document.c b/libdocument/ev-document.c index 09f58870..1747bf1b 100644 --- a/libdocument/ev-document.c +++ b/libdocument/ev-document.c @@ -25,6 +25,7 @@ #include #include "ev-document.h" +#include "synctex_parser.h" #define EV_DOCUMENT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EV_TYPE_DOCUMENT, EvDocumentPrivate)) @@ -53,16 +54,19 @@ struct _EvDocumentPrivate gchar **page_labels; EvPageSize *page_sizes; EvDocumentInfo *info; + + synctex_scanner_t synctex_scanner; }; -static gint _ev_document_get_n_pages (EvDocument *document); -static void _ev_document_get_page_size (EvDocument *document, - EvPage *page, - double *width, - double *height); -static gchar *_ev_document_get_page_label (EvDocument *document, - EvPage *page); -static EvDocumentInfo *_ev_document_get_info (EvDocument *document); +static gint _ev_document_get_n_pages (EvDocument *document); +static void _ev_document_get_page_size (EvDocument *document, + EvPage *page, + double *width, + double *height); +static gchar *_ev_document_get_page_label (EvDocument *document, + EvPage *page); +static EvDocumentInfo *_ev_document_get_info (EvDocument *document); +static gboolean _ev_document_support_synctex (EvDocument *document); GMutex *ev_doc_mutex = NULL; GMutex *ev_fc_mutex = NULL; @@ -122,6 +126,11 @@ ev_document_finalize (GObject *object) document->priv->info = NULL; } + if (document->priv->synctex_scanner) { + synctex_scanner_free (document->priv->synctex_scanner); + document->priv->synctex_scanner = NULL; + } + G_OBJECT_CLASS (ev_document_parent_class)->finalize (object); } @@ -314,6 +323,16 @@ ev_document_load (EvDocument *document, } priv->info = _ev_document_get_info (document); + if (_ev_document_support_synctex (document)) { + gchar *filename; + + filename = g_filename_from_uri (uri, NULL, NULL); + if (filename != NULL) { + priv->synctex_scanner = + synctex_scanner_new_with_output_file (filename, NULL, 1); + g_free (filename); + } + } } return retval; @@ -348,6 +367,119 @@ ev_document_get_page (EvDocument *document, return klass->get_page (document, index); } +static gboolean +_ev_document_support_synctex (EvDocument *document) +{ + EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS (document); + + return klass->support_synctex ? klass->support_synctex (document) : FALSE; +} + +gboolean +ev_document_has_synctex (EvDocument *document) +{ + g_return_val_if_fail (EV_IS_DOCUMENT (document), FALSE); + + return document->priv->synctex_scanner != NULL; +} + +/** + * ev_document_synctex_backward_search: + * @document: + * @page: the target page + * @x: + * @y: + * + * Peforms a Synctex backward search to obtain the TeX input file, line and + * (possibly) column corresponding to the position (@x,@y) (in 72dpi + * coordinates) in the @page of @document. + * + * Returns: A pointer to the EvSourceLink structure that holds the result. @NULL if synctex + * is not enabled for the document or no result is found. + * The EvSourceLink pointer should be freed with g_free after it is used. + */ +EvSourceLink * +ev_document_synctex_backward_search (EvDocument *document, + gint page_index, + gfloat x, + gfloat y) +{ + EvSourceLink *result = NULL; + synctex_scanner_t scanner; + + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + + scanner = document->priv->synctex_scanner; + if (!scanner) + return NULL; + + if (synctex_edit_query (scanner, page_index + 1, x, y) > 0) { + synctex_node_t node; + + /* We assume that a backward search returns either zero or one result_node */ + node = synctex_next_result (scanner); + if (node != NULL) { + result = g_new (EvSourceLink, 1); + result->filename = synctex_scanner_get_name (scanner, + synctex_node_tag (node)); + result->line = synctex_node_line (node); + result->col = synctex_node_column (node); + } + } + + return result; +} + +/** + * ev_document_synctex_forward_search: + * @document: + * @filename: the source filename + * @line: line number in the source file + * @col: column number in the source file + * + * Peforms a Synctex forward search to obtain the area in the document + * corresponding to the position @line and @column number in the source Tex file + * + * Returns: An EvMapping with the page number and area corresponfing to + * the given line in the source file. It must be free with g_free when done + */ +EvMapping * +ev_document_synctex_forward_search (EvDocument *document, + const gchar *filename, + gint line, + gint col) +{ + EvMapping *result = NULL; + synctex_scanner_t scanner; + + g_return_val_if_fail (EV_IS_DOCUMENT (document), NULL); + + scanner = document->priv->synctex_scanner; + if (!scanner) + return NULL; + + if (synctex_display_query (scanner, filename, line, col) > 0) { + synctex_node_t node; + gint page; + + if ((node = synctex_next_result (scanner))) { + result = g_new (EvMapping, 1); + + page = synctex_node_page (node) - 1; + result->data = GINT_TO_POINTER (page); + + result->area.x1 = synctex_node_box_visible_h (node); + result->area.y1 = synctex_node_box_visible_v (node) - + synctex_node_box_visible_height (node); + result->area.x2 = synctex_node_box_visible_width (node) + result->area.x1; + result->area.y2 = synctex_node_box_visible_depth (node) + + synctex_node_box_visible_height (node) + result->area.y1; + } + } + + return result; +} + static gint _ev_document_get_n_pages (EvDocument *document) { diff --git a/libdocument/ev-document.h b/libdocument/ev-document.h index 68b33075..578cc7ff 100644 --- a/libdocument/ev-document.h +++ b/libdocument/ev-document.h @@ -65,6 +65,7 @@ typedef struct { } EvPoint; typedef struct _EvRectangle EvRectangle; +typedef struct _EvMapping EvMapping; typedef struct _EvDocumentBackendInfo EvDocumentBackendInfo; struct _EvDocumentBackendInfo @@ -73,6 +74,12 @@ struct _EvDocumentBackendInfo const gchar *version; }; +typedef struct { + const gchar *filename; + gint line; + gint col; +} EvSourceLink; + struct _EvDocument { GObject base; @@ -105,6 +112,7 @@ struct _EvDocumentClass EvDocumentInfo * (* get_info) (EvDocument *document); gboolean (* get_backend_info)(EvDocument *document, EvDocumentBackendInfo *info); + gboolean (* support_synctex) (EvDocument *document); }; GType ev_document_get_type (void) G_GNUC_CONST; @@ -157,6 +165,19 @@ gboolean ev_document_has_text_page_labels (EvDocument *document); gboolean ev_document_find_page_by_label (EvDocument *document, const gchar *page_label, gint *page_index); +gboolean ev_document_has_synctex (EvDocument *document); + +EvSourceLink *ev_document_synctex_backward_search + (EvDocument *document, + gint page_index, + gfloat x, + gfloat y); + +EvMapping *ev_document_synctex_forward_search + (EvDocument *document, + const gchar *filename, + gint line, + gint col); gint ev_rect_cmp (EvRectangle *a, EvRectangle *b); @@ -175,6 +196,11 @@ EvRectangle *ev_rectangle_new (void); EvRectangle *ev_rectangle_copy (EvRectangle *ev_rect); void ev_rectangle_free (EvRectangle *ev_rect); +struct _EvMapping { + EvRectangle area; + gpointer data; +}; + /* convenience macro to ease interface addition in the CODE * section of EV_BACKEND_REGISTER_WITH_CODE (this macro relies on * the g_define_type_id present within EV_BACKEND_REGISTER_WITH_CODE()). diff --git a/libdocument/ev-mapping.h b/libdocument/ev-mapping.h index 2a3c130e..b6024c5c 100644 --- a/libdocument/ev-mapping.h +++ b/libdocument/ev-mapping.h @@ -29,13 +29,6 @@ G_BEGIN_DECLS -typedef struct _EvMapping EvMapping; - -struct _EvMapping { - EvRectangle area; - gpointer data; -}; - EvMapping *ev_mapping_list_find (GList *mapping_list, gconstpointer data); EvMapping *ev_mapping_list_find_custom (GList *mapping_list, -- 2.43.0