diff --git a/Makefile b/Makefile index 19c5a39..203d0fb 100644 --- a/Makefile +++ b/Makefile @@ -21,20 +21,10 @@ LIBS += $(MAGIC_LIB) CPPFLAGS += -DWITH_MAGIC endif -ifneq ($(WITH_SYSTEM_SYNCTEX),0) -INCS += $(SYNCTEX_INC) -LIBS += $(SYNCTEX_LIB) -else -INCS += $(ZLIB_INC) -LIBS += $(ZLIB_LIB) -SOURCE += $(wildcard ${PROJECT}/synctex/*.c) - -ifeq (,$(findstring -Isynctex,${CPPFLAGS})) -CPPFLAGS += -I${PROJECT}/synctex -endif -ifeq (,$(findstring -DSYNCTEX_VERBOSE=0,${CPPFLAGS})) -CPPFLAGS += -DSYNCTEX_VERBOSE=0 -endif +ifneq ($(WITH_SYNCTEX),0) +INCS += $(SYNCTEX_INC) +LIBS += $(SYNCTEX_LIB) +CPPFLAGS += -DWITH_SYNCTEX endif ifneq ($(wildcard ${VALGRIND_SUPPRESSION_FILE}),) diff --git a/config.mk b/config.mk index 1da1e58..620c25c 100644 --- a/config.mk +++ b/config.mk @@ -38,7 +38,7 @@ WITH_SQLITE ?= $(shell (${PKG_CONFIG} --atleast-version=3.5.9 sqlite3 && echo 1) # synctex # To use the embedded copy of the syntex parser set WITH_SYSTEM_SYNCTEX to 0. -WITH_SYSTEM_SYNCTEX ?= $(shell (${PKG_CONFIG} synctex && echo 1) || echo 0) +WITH_SYNCTEX ?= $(shell (${PKG_CONFIG} synctex && echo 1) || echo 0) # mimetype detection # To disable support for mimetype detction with libmagic set WITH_MAGIC to 0. @@ -91,12 +91,9 @@ MAGIC_INC ?= MAGIC_LIB ?= -lmagic endif -ifneq ($(WITH_SYSTEM_SYNCTEX),0) +ifneq ($(WITH_SYNCTEX),0) SYNCTEX_INC ?= $(shell ${PKG_CONFIG} --cflags synctex) SYNCTEX_LIB ?= $(shell ${PKG_CONFIG} --libs synctex) -else -ZLIB_INC ?= $(shell ${PKG_CONFIG} --cflags zlib) -ZLIB_LIB ?= $(shell ${PKG_CONFIG} --libs zlib) endif INCS = ${GIRARA_INC} ${GTK_INC} ${GTHREAD_INC} ${GMODULE_INC} ${GLIB_INC} diff --git a/tests/Makefile b/tests/Makefile index 8ec87fb..a1e7e4b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -33,21 +33,10 @@ LIBS += $(MAGIC_LIB) CPPFLAGS += -DWITH_MAGIC endif -ifneq ($(WITH_SYSTEM_SYNCTEX),0) +ifneq ($(WITH_SYNCTEX),0) INCS += $(SYNCTEX_INC) LIBS += $(SYNCTEX_LIB) -else -ZATHURA_OBJECTS += $(wildcard ../${BUILDDIR_RELEASE}/zathura/synctex/*.o) -ZATHURA_OBJECTS_DEBUG += $(wildcard ../${BUILDDIR_DEBUG}/zathura/synctex/*.o) -ZATHURA_OBJECTS_GCOV += $(wildcard ../${BUILDDIR_GCOV}/zathura/synctex/*.o) -LIBS += $(ZLIB_LIB) - -ifeq (,$(findstring -Isynctex,${CPPFLAGS})) -CPPFLAGS += -I../zathura/synctex -endif -ifeq (,$(findstring -DSYNCTEX_VERBOSE=0,${CPPFLAGS})) -CPPFLAGS += -DSYNCTEX_VERBOSE=0 -endif +CPPFLAGS += -DWITH_SYNCTEX endif ifneq ($(wildcard ${VALGRIND_SUPPRESSION_FILE}),) diff --git a/zathura/main.c b/zathura/main.c index a8b4ed3..c94f535 100644 --- a/zathura/main.c +++ b/zathura/main.c @@ -13,7 +13,9 @@ #include "zathura.h" #include "utils.h" #include "dbus-interface.h" +#ifdef WITH_SYNCTEX #include "synctex.h" +#endif /* main function */ int @@ -41,13 +43,17 @@ main(int argc, char* argv[]) gchar* plugin_path = NULL; gchar* loglevel = NULL; gchar* password = NULL; +#ifdef WITH_SYNCTEX gchar* synctex_editor = NULL; gchar* synctex_fwd = NULL; +#endif gchar* mode = NULL; bool forkback = false; bool print_version = false; int page_number = ZATHURA_PAGE_NUMBER_UNSPECIFIED; +#ifdef WITH_SYNCTEX int synctex_pid = -1; +#endif #ifdef GDK_WINDOWING_X11 Window embed = 0; #endif @@ -65,9 +71,11 @@ main(int argc, char* argv[]) { "page", 'P', 0, G_OPTION_ARG_INT, &page_number, _("Page number to go to"), "number" }, { "debug", 'l', 0, G_OPTION_ARG_STRING, &loglevel, _("Log level (debug, info, warning, error)"), "level" }, { "version", 'v', 0, G_OPTION_ARG_NONE, &print_version, _("Print version information"), NULL }, +#ifdef WITH_SYNCTEX { "synctex-editor-command", 'x', 0, G_OPTION_ARG_STRING, &synctex_editor, _("Synctex editor (forwarded to the synctex command)"), "cmd" }, { "synctex-forward", '\0', 0, G_OPTION_ARG_STRING, &synctex_fwd, _("Move to given synctex position"), "position" }, { "synctex-pid", '\0', 0, G_OPTION_ARG_INT, &synctex_pid, _("Highlight given position in the given process"), "pid" }, +#endif { "mode", '\0', 0, G_OPTION_ARG_STRING, &mode, _("Start in a non-default mode"), "mode" }, { NULL, '\0', 0, 0, NULL, NULL, NULL } }; @@ -94,6 +102,7 @@ main(int argc, char* argv[]) girara_set_debug_level(GIRARA_ERROR); } +#ifdef WITH_SYNCTEX /* handle synctex forward synchronization */ if (synctex_fwd != NULL) { if (argc != 2) { @@ -138,6 +147,7 @@ main(int argc, char* argv[]) girara_debug("No instance found. Starting new one."); } +#endif /* check mode */ if (mode != NULL && g_strcmp0(mode, "presentation") != 0 && g_strcmp0(mode, "fullscreen") != 0) { @@ -179,9 +189,11 @@ main(int argc, char* argv[]) return -1; } +#ifdef WITH_SYNCTEX if (synctex_editor != NULL) { girara_setting_set(zathura->ui.session, "synctex-editor-command", synctex_editor); } +#endif /* Print version */ if (print_version == true) { @@ -199,7 +211,11 @@ main(int argc, char* argv[]) if (argc > 1) { if (page_number > 0) --page_number; +#ifdef WITH_SYNCTEX document_open_idle(zathura, argv[1], password, page_number, mode, synctex_fwd); +#else + document_open_idle(zathura, argv[1], password, page_number, mode, NULL); +#endif } if (argc > 2) { char* new_argv[2 * sizeof(entries) / sizeof(GOptionEntry) + 3] = { @@ -239,6 +255,7 @@ main(int argc, char* argv[]) new_argv[idx++] = g_strdup("--debug"); new_argv[idx++] = g_strdup(loglevel); } +#ifdef WITH_SYNCTEX if (synctex_editor != NULL) { new_argv[idx++] = g_strdup("--synctex-editor-command"); new_argv[idx++] = g_strdup(synctex_editor); @@ -247,6 +264,7 @@ main(int argc, char* argv[]) new_argv[idx++] = g_strdup("--synctex-forward"); new_argv[idx++] = g_strdup(synctex_fwd); } +#endif /* no need to pass synctex-pid */ if (mode != NULL) { new_argv[idx++] = g_strdup("--mode"); diff --git a/zathura/synctex.c b/zathura/synctex.c index cdb42fd..87ae15f 100644 --- a/zathura/synctex.c +++ b/zathura/synctex.c @@ -4,10 +4,8 @@ #include #include -#ifdef WITH_SYSTEM_SYNCTEX +#ifdef WITH_SYNCTEX #include -#else -#include "synctex/synctex_parser.h" #endif #include "synctex.h" @@ -17,6 +15,7 @@ #include "utils.h" #include "adjustment.h" +#ifdef WITH_SYNCTEX bool synctex_get_input_line_column(const char* filename, unsigned int page, int x, int y, char** input_file, unsigned int* line, unsigned int* column) @@ -193,6 +192,32 @@ synctex_rectangles_from_position(const char* filename, const char* input_file, return hitlist; } +#else +bool +synctex_get_input_line_column(const char* UNUSED(filename), + unsigned int UNUSED(page), int UNUSED(x), + int UNUSED(y), char** UNUSED(input_file), + unsigned int* UNUSED(line), + unsigned int* UNUSED(column)) +{ + return false; +} + +void +synctex_edit(const char* UNUSED(editor), zathura_page_t* UNUSED(page), + int UNUSED(x), int UNUSED(y)) +{} + +girara_list_t* +synctex_rectangles_from_position(const char* UNUSED(filename), + const char* UNUSED(input_file), + int UNUSED(line), int UNUSED(column), + unsigned int* UNUSED(page), + girara_list_t** UNUSED(secondary_rects)) +{ + return NULL; +} +#endif bool synctex_parse_input(const char* synctex, char** input_file, int* line, diff --git a/zathura/synctex/LICENSE b/zathura/synctex/LICENSE deleted file mode 100644 index c739c44..0000000 --- a/zathura/synctex/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2008, 2009, 2010, 2011 jerome DOT laurens AT u-bourgogne DOT fr - -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE - -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written -authorization from the copyright holder. diff --git a/zathura/synctex/Makefile b/zathura/synctex/Makefile deleted file mode 100644 index a26a879..0000000 --- a/zathura/synctex/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -FILES=synctex_parser.c synctex_parser.h synctex_parser_utils.c synctex_parser_utils.h synctex_parser_version.txt - -.PHONY: update -update: - set -e; for FILE in $(FILES) ; do \ - wget -O "$$FILE" "http://www.tug.org/svn/texlive/trunk/Build/source/texk/web2c/synctexdir/$$FILE?view=co" ; \ - done diff --git a/zathura/synctex/synctex_parser.c b/zathura/synctex/synctex_parser.c deleted file mode 100644 index 3175495..0000000 --- a/zathura/synctex/synctex_parser.c +++ /dev/null @@ -1,4419 +0,0 @@ -/* -Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr - -This file is part of the SyncTeX package. - -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 - -Version: 1.17 - -See synctex_parser_readme.txt for more details - -License: --------- -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE - -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written -authorization from the copyright holder. - -Acknowledgments: ----------------- -The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh, -and significant help from XeTeX developer Jonathan Kew - -Nota Bene: ----------- -If you include or use a significant part of the synctex package into a software, -I would appreciate to be listed as contributor and see "SyncTeX" highlighted. - -Version 1 -Thu Jun 19 09:39:21 UTC 2008 - -*/ - -/* We assume that high level application like pdf viewers will want - * to embed this code as is. We assume that they also have locale.h and setlocale. - * For other tools such as TeXLive tools, you must define SYNCTEX_USE_LOCAL_HEADER, - * when building. You also have to create and customize synctex_parser_local.h to fit your system. - * In particular, the HAVE_LOCALE_H and HAVE_SETLOCALE macros should be properly defined. - * With this design, you should not need to edit this file. */ - -# if defined(SYNCTEX_USE_LOCAL_HEADER) -# include "synctex_parser_local.h" -# else -# define HAVE_LOCALE_H 1 -# define HAVE_SETLOCALE 1 -# if defined(_MSC_VER) -# define SYNCTEX_INLINE __inline -# else -# define SYNCTEX_INLINE inline -# endif -# endif - -#include -#include -#include -#include -#include - -#if defined(HAVE_LOCALE_H) -#include -#endif - -/* The data is organized in a graph with multiple entries. - * The root object is a scanner, it is created with the contents on a synctex file. - * Each leaf of the tree is a synctex_node_t object. - * There are 3 subtrees, two of them sharing the same leaves. - * The first tree is the list of input records, where input file names are associated with tags. - * The second tree is the box tree as given by TeX when shipping pages out. - * First level objects are sheets, containing boxes, glues, kerns... - * The third tree allows to browse leaves according to tag and line. - */ - -#include "synctex_parser.h" -#include "synctex_parser_utils.h" - -/* These are the possible extensions of the synctex file */ -const char * synctex_suffix = ".synctex"; -const char * synctex_suffix_gz = ".gz"; - -/* each synctex node has a class */ -typedef struct __synctex_class_t _synctex_class_t; -typedef _synctex_class_t * synctex_class_t; - - -/* synctex_node_t is a pointer to a node - * _synctex_node is the target of the synctex_node_t pointer - * It is a pseudo object oriented program. - * class is a pointer to the class object the node belongs to. - * implementation is meant to contain the private data of the node - * basically, there are 2 kinds of information: navigation information and - * synctex information. Both will depend on the type of the node, - * thus different nodes will have different private data. - * There is no inheritancy overhead. - */ -typedef union _synctex_info_t { - int INT; - char * PTR; -} synctex_info_t; - -# if defined(SYNCTEX_USE_CHARINDEX) -# define SYNCTEX_DECLARE_CHARINDEX synctex_charindex_t char_index; -# define SYNCTEX_CHARINDEX(NODE) (NODE->char_index) -# define SYNCTEX_PRINT_CHARINDEX printf("#%i\n",SYNCTEX_CHARINDEX(node)) -# define SYNCTEX_DECLARE_CHAR_OFFSET synctex_charindex_t charindex_offset -# define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION) NODE->char_index = (synctex_charindex_t)(scanner->charindex_offset+SYNCTEX_CUR-SYNCTEX_START+(CORRECTION)); -# else -# define SYNCTEX_DECLARE_CHARINDEX -# define SYNCTEX_CHARINDEX(NODE) 0 -# define SYNCTEX_PRINT_CHARINDEX printf("\n") -# define SYNCTEX_DECLARE_CHAR_OFFSET synctex_charindex_t charindex_offset -# define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION) -# endif - -struct _synctex_node { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t * implementation; -}; - -/* Each node of the tree, except the scanner itself belongs to a class. - * The class object is just a struct declaring the owning scanner - * This is a pointer to the scanner as root of the tree. - * The type is used to identify the kind of node. - * The class declares pointers to a creator and a destructor method. - * The log and display fields are used to log and display the node. - * display will also display the child, sibling and parent sibling. - * parent, child and sibling are used to navigate the tree, - * from TeX box hierarchy point of view. - * The friend field points to a method which allows to navigate from friend to friend. - * A friend is a node with very close tag and line numbers. - * Finally, the info field point to a method giving the private node info offset. - */ - -typedef synctex_node_t *(*_synctex_node_getter_t)(synctex_node_t); -typedef synctex_info_t *(*_synctex_info_getter_t)(synctex_node_t); - -struct __synctex_class_t { - synctex_scanner_t scanner; - int type; - synctex_node_t (*new)(synctex_scanner_t scanner); - void (*free)(synctex_node_t); - void (*log)(synctex_node_t); - void (*display)(synctex_node_t); - _synctex_node_getter_t parent; - _synctex_node_getter_t child; - _synctex_node_getter_t sibling; - _synctex_node_getter_t friend; - _synctex_node_getter_t next_hbox; - _synctex_info_getter_t info; -}; - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Abstract OBJECTS and METHODS -# endif - -/* These macros are shortcuts - * This macro checks if a message can be sent. - */ -# define SYNCTEX_CAN_PERFORM(NODE,SELECTOR)\ - (NULL!=((((NODE)->class))->SELECTOR)) - -/* This macro is some kind of objc_msg_send. - * It takes care of sending the proper message if possible. - */ -# define SYNCTEX_MSG_SEND(NODE,SELECTOR) if (NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR)) {\ - (*((((NODE)->class))->SELECTOR))(NODE);\ - } - -/* read only safe getter - */ -# define SYNCTEX_GET(NODE,SELECTOR)((NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR))?SYNCTEX_GETTER(NODE,SELECTOR)[0]:(NULL)) - -/* read/write getter - */ -# define SYNCTEX_GETTER(NODE,SELECTOR)\ - ((synctex_node_t *)((*((((NODE)->class))->SELECTOR))(NODE))) - -# define SYNCTEX_FREE(NODE) SYNCTEX_MSG_SEND(NODE,free); - -/* Parent getter and setter - */ -# define SYNCTEX_PARENT(NODE) SYNCTEX_GET(NODE,parent) -# define SYNCTEX_SET_PARENT(NODE,NEW_PARENT) if (NODE && NEW_PARENT && SYNCTEX_CAN_PERFORM(NODE,parent)){\ - SYNCTEX_GETTER(NODE,parent)[0]=NEW_PARENT;\ - } - -/* Child getter and setter - */ -# define SYNCTEX_CHILD(NODE) SYNCTEX_GET(NODE,child) -# define SYNCTEX_SET_CHILD(NODE,NEW_CHILD) if (NODE && NEW_CHILD){\ - SYNCTEX_GETTER(NODE,child)[0]=NEW_CHILD;\ - SYNCTEX_GETTER(NEW_CHILD,parent)[0]=NODE;\ - } - -/* Sibling getter and setter - */ -# define SYNCTEX_SIBLING(NODE) SYNCTEX_GET(NODE,sibling) -# define SYNCTEX_SET_SIBLING(NODE,NEW_SIBLING) if (NODE && NEW_SIBLING) {\ - SYNCTEX_GETTER(NODE,sibling)[0]=NEW_SIBLING;\ - if (SYNCTEX_CAN_PERFORM(NEW_SIBLING,parent) && SYNCTEX_CAN_PERFORM(NODE,parent)) {\ - SYNCTEX_GETTER(NEW_SIBLING,parent)[0]=SYNCTEX_GETTER(NODE,parent)[0];\ - }\ - } -/* Friend getter and setter. A friend is a kern, math, glue or void box node which tag and line numbers are similar. - * This is a first filter on the nodes that avoids testing all of them. - * Friends are used mainly in forward synchronization aka from source to output. - */ -# define SYNCTEX_FRIEND(NODE) SYNCTEX_GET(NODE,friend) -# define SYNCTEX_SET_FRIEND(NODE,NEW_FRIEND) if (NODE && NEW_FRIEND){\ - SYNCTEX_GETTER(NODE,friend)[0]=NEW_FRIEND;\ - } - -/* Next box getter and setter. The box tree can be traversed from one horizontal box to the other. - * Navigation starts with the deeper boxes. - */ -# define SYNCTEX_NEXT_hbox(NODE) SYNCTEX_GET(NODE,next_hbox) -# define SYNCTEX_SET_NEXT_hbox(NODE,NEXT_HBOX) if (NODE && NEXT_HBOX){\ - SYNCTEX_GETTER(NODE,next_hbox)[0]=NEXT_HBOX;\ - } - -/* A node is meant to own its child and sibling. - * It is not owned by its parent, unless it is its first child. - * This destructor is for all nodes with children. - */ -static void _synctex_free_node(synctex_node_t node) { - if (node) { - (*((node->class)->sibling))(node); - SYNCTEX_FREE(SYNCTEX_SIBLING(node)); - SYNCTEX_FREE(SYNCTEX_CHILD(node)); - free(node); - } - return; -} - -/* A node is meant to own its child and sibling. - * It is not owned by its parent, unless it is its first child. - * This destructor is for nodes with no child. - * The first sheet is onwned by the scanner. - */ -static void _synctex_free_leaf(synctex_node_t node) { - if (node) { - SYNCTEX_FREE(SYNCTEX_SIBLING(node)); - free(node); - } - return; -} -# ifdef __SYNCTEX_WORK__ -# include "/usr/include/zlib.h" -# else -# include -# endif - -/* The synctex scanner is the root object. - * Is is initialized with the contents of a text file or a gzipped file. - * The buffer_? are first used to parse the text. - */ -struct __synctex_scanner_t { - gzFile file; /* The (possibly compressed) file */ - SYNCTEX_DECLARE_CHAR_OFFSET; - char * buffer_cur; /* current location in the buffer */ - char * buffer_start; /* start of the buffer */ - char * buffer_end; /* end of the buffer */ - char * output_fmt; /* dvi or pdf, not yet used */ - char * output; /* the output name used to create the scanner */ - char * synctex; /* the .synctex or .synctex.gz name used to create the scanner */ - int version; /* 1, not yet used */ - struct { - unsigned has_parsed:1; /* Whether the scanner has parsed its underlying synctex file. */ - unsigned reserved:sizeof(unsigned)-1; /* alignment */ - } flags; - int pre_magnification; /* magnification from the synctex preamble */ - int pre_unit; /* unit from the synctex preamble */ - int pre_x_offset; /* X offste from the synctex preamble */ - int pre_y_offset; /* Y offset from the synctex preamble */ - int count; /* Number of records, from the synctex postamble */ - float unit; /* real unit, from synctex preamble or post scriptum */ - float x_offset; /* X offset, from synctex preamble or post scriptum */ - float y_offset; /* Y Offset, from synctex preamble or post scriptum */ - synctex_node_t sheet; /* The first sheet node, its siblings are the other sheet nodes */ - synctex_node_t input; /* The first input node, its siblings are the other input nodes */ - int number_of_lists; /* The number of friend lists */ - synctex_node_t * lists_of_friends;/* The friend lists */ - _synctex_class_t class[synctex_node_number_of_types]; /* The classes of the nodes of the scanner */ -}; - -/* SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts - */ -# define SYNCTEX_CUR (scanner->buffer_cur) -# define SYNCTEX_START (scanner->buffer_start) -# define SYNCTEX_END (scanner->buffer_end) - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark OBJECTS, their creators and destructors. -# endif - -/* Here, we define the indices for the different informations. - * They are used to declare the size of the implementation. - * For example, if one object uses SYNCTEX_HORIZ_IDX is its size, - * then its info will contain a tag, line, column, horiz but no width nor height nor depth - */ - -/* The sheet is a first level node. - * It has no parent (the parent is the scanner itself) - * Its sibling points to another sheet. - * Its child points to its first child, in general a box. - * A sheet node contains only one synctex information: the page. - * This is the 1 based page index as given by TeX. - */ -/* The next macros are used to access the node info - * SYNCTEX_INFO(node) points to the first synctex integer or pointer data of node - * SYNCTEX_INFO(node)[index] is the information at index - * for example, the page of a sheet is stored in SYNCTEX_INFO(sheet)[SYNCTEX_PAGE_IDX] - */ -# define SYNCTEX_INFO(NODE) ((*((((NODE)->class))->info))(NODE)) -# define SYNCTEX_PAGE_IDX 0 -# define SYNCTEX_PAGE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_PAGE_IDX].INT - -/* This macro defines implementation offsets - * It is only used for pointer values - */ -# define SYNCTEX_MAKE_GET(SYNCTEX_GETTER,OFFSET)\ -static synctex_node_t * SYNCTEX_GETTER (synctex_node_t node) {\ - return node?(synctex_node_t *)((&((node)->implementation))+OFFSET):NULL;\ -} -SYNCTEX_MAKE_GET(_synctex_implementation_0,0) -SYNCTEX_MAKE_GET(_synctex_implementation_1,1) -SYNCTEX_MAKE_GET(_synctex_implementation_2,2) -SYNCTEX_MAKE_GET(_synctex_implementation_3,3) -SYNCTEX_MAKE_GET(_synctex_implementation_4,4) -SYNCTEX_MAKE_GET(_synctex_implementation_5,5) - -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[3+SYNCTEX_PAGE_IDX+1];/* child, sibling, next box, - * SYNCTEX_PAGE_IDX */ -} synctex_node_sheet_t; - -/* sheet node creator */ - -#define DEFINE_synctex_new_NODE(NAME)\ -static synctex_node_t _synctex_new_##NAME(synctex_scanner_t scanner) {\ - if (scanner) {\ - synctex_node_t node = _synctex_malloc(sizeof(synctex_node_##NAME##_t));\ - if (node) {\ - SYNCTEX_IMPLEMENT_CHARINDEX(node,0);\ - ++SYNCTEX_CUR;\ - node->class = scanner->class+synctex_node_type_##NAME;\ - }\ - return node;\ - }\ - return NULL;\ -} -DEFINE_synctex_new_NODE(sheet) - -static void _synctex_display_sheet(synctex_node_t node); -static void _synctex_log_sheet(synctex_node_t node); - -static _synctex_class_t synctex_class_sheet = { - NULL, /* No scanner yet */ - synctex_node_type_sheet, /* Node type */ - &_synctex_new_sheet, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_sheet, /* log */ - &_synctex_display_sheet, /* display */ - NULL, /* No parent */ - &_synctex_implementation_0, /* child */ - &_synctex_implementation_1, /* sibling */ - NULL, /* No friend */ - &_synctex_implementation_2, /* Next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 /* info */ -}; - -/* A box node contains navigation and synctex information - * There are different kind of boxes. - * Only horizontal boxes are treated differently because of their visible size. - */ -# define SYNCTEX_TAG_IDX 0 -# define SYNCTEX_LINE_IDX (SYNCTEX_TAG_IDX+1) -# define SYNCTEX_COLUMN_IDX (SYNCTEX_LINE_IDX+1) -# define SYNCTEX_HORIZ_IDX (SYNCTEX_COLUMN_IDX+1) -# define SYNCTEX_VERT_IDX (SYNCTEX_HORIZ_IDX+1) -# define SYNCTEX_WIDTH_IDX (SYNCTEX_VERT_IDX+1) -# define SYNCTEX_HEIGHT_IDX (SYNCTEX_WIDTH_IDX+1) -# define SYNCTEX_DEPTH_IDX (SYNCTEX_HEIGHT_IDX+1) -/* the corresponding info accessors */ -# define SYNCTEX_TAG(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_TAG_IDX].INT -# define SYNCTEX_LINE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_LINE_IDX].INT -# define SYNCTEX_COLUMN(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_COLUMN_IDX].INT -# define SYNCTEX_HORIZ(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HORIZ_IDX].INT -# define SYNCTEX_VERT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_VERT_IDX].INT -# define SYNCTEX_WIDTH(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_WIDTH_IDX].INT -# define SYNCTEX_HEIGHT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HEIGHT_IDX].INT -# define SYNCTEX_DEPTH(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_DEPTH_IDX].INT -# define SYNCTEX_ABS_WIDTH(NODE) ((SYNCTEX_WIDTH(NODE)>0?SYNCTEX_WIDTH(NODE):-SYNCTEX_WIDTH(NODE))) -# define SYNCTEX_ABS_HEIGHT(NODE) ((SYNCTEX_HEIGHT(NODE)>0?SYNCTEX_HEIGHT(NODE):-SYNCTEX_HEIGHT(NODE))) -# define SYNCTEX_ABS_DEPTH(NODE) ((SYNCTEX_DEPTH(NODE)>0?SYNCTEX_DEPTH(NODE):-SYNCTEX_DEPTH(NODE))) - -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[5+SYNCTEX_DEPTH_IDX+1]; /* parent,child,sibling,friend,next box, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH */ -} synctex_node_vbox_t; - -/* vertical box node creator */ -DEFINE_synctex_new_NODE(vbox) - -static void _synctex_log_vbox(synctex_node_t node); -static void _synctex_display_vbox(synctex_node_t node); - -/* These are static class objects, each scanner will make a copy of them and setup the scanner field. - */ -static _synctex_class_t synctex_class_vbox = { - NULL, /* No scanner yet */ - synctex_node_type_vbox, /* Node type */ - &_synctex_new_vbox, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_vbox, /* log */ - &_synctex_display_vbox, /* display */ - &_synctex_implementation_0, /* parent */ - &_synctex_implementation_1, /* child */ - &_synctex_implementation_2, /* sibling */ - &_synctex_implementation_3, /* friend */ - &_synctex_implementation_4, /* next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_5 -}; - -/* Horizontal boxes must contain visible size, because 0 width does not mean emptiness. - * They also contain an average of the line numbers of the containing nodes. */ -# define SYNCTEX_MEAN_LINE_IDX (SYNCTEX_DEPTH_IDX+1) -# define SYNCTEX_NODE_WEIGHT_IDX (SYNCTEX_MEAN_LINE_IDX+1) -# define SYNCTEX_HORIZ_V_IDX (SYNCTEX_NODE_WEIGHT_IDX+1) -# define SYNCTEX_VERT_V_IDX (SYNCTEX_HORIZ_V_IDX+1) -# define SYNCTEX_WIDTH_V_IDX (SYNCTEX_VERT_V_IDX+1) -# define SYNCTEX_HEIGHT_V_IDX (SYNCTEX_WIDTH_V_IDX+1) -# define SYNCTEX_DEPTH_V_IDX (SYNCTEX_HEIGHT_V_IDX+1) -/* the corresponding info accessors */ -# define SYNCTEX_MEAN_LINE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_MEAN_LINE_IDX].INT -# define SYNCTEX_NODE_WEIGHT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_NODE_WEIGHT_IDX].INT -# define SYNCTEX_HORIZ_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HORIZ_V_IDX].INT -# define SYNCTEX_VERT_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_VERT_V_IDX].INT -# define SYNCTEX_WIDTH_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_WIDTH_V_IDX].INT -# define SYNCTEX_HEIGHT_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HEIGHT_V_IDX].INT -# define SYNCTEX_DEPTH_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_DEPTH_V_IDX].INT -# define SYNCTEX_ABS_WIDTH_V(NODE) ((SYNCTEX_WIDTH_V(NODE)>0?SYNCTEX_WIDTH_V(NODE):-SYNCTEX_WIDTH_V(NODE))) -# define SYNCTEX_ABS_HEIGHT_V(NODE) ((SYNCTEX_HEIGHT_V(NODE)>0?SYNCTEX_HEIGHT_V(NODE):-SYNCTEX_HEIGHT_V(NODE))) -# define SYNCTEX_ABS_DEPTH_V(NODE) ((SYNCTEX_DEPTH_V(NODE)>0?SYNCTEX_DEPTH_V(NODE):-SYNCTEX_DEPTH_V(NODE))) - -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[5+SYNCTEX_DEPTH_V_IDX+1]; /*parent,child,sibling,friend,next box, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH, - * SYNCTEX_MEAN_LINE,SYNCTEX_NODE_WEIGHT, - * SYNCTEX_HORIZ_V,SYNCTEX_VERT_V,SYNCTEX_WIDTH_V,SYNCTEX_HEIGHT_V,SYNCTEX_DEPTH_V*/ -} synctex_node_hbox_t; - -/* horizontal box node creator */ -DEFINE_synctex_new_NODE(hbox) - -static void _synctex_display_hbox(synctex_node_t node); -static void _synctex_log_hbox(synctex_node_t node); - - -static _synctex_class_t synctex_class_hbox = { - NULL, /* No scanner yet */ - synctex_node_type_hbox, /* Node type */ - &_synctex_new_hbox, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_hbox, /* log */ - &_synctex_display_hbox, /* display */ - &_synctex_implementation_0, /* parent */ - &_synctex_implementation_1, /* child */ - &_synctex_implementation_2, /* sibling */ - &_synctex_implementation_3, /* friend */ - &_synctex_implementation_4, /* next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_5 -}; - -/* This void box node implementation is either horizontal or vertical - * It does not contain a child field. - */ -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[3+SYNCTEX_DEPTH_IDX+1]; /* parent,sibling,friend, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH*/ -} synctex_node_void_vbox_t; - -/* vertical void box node creator */ -DEFINE_synctex_new_NODE(void_vbox) - -static void _synctex_log_void_box(synctex_node_t node); -static void _synctex_display_void_vbox(synctex_node_t node); - -static _synctex_class_t synctex_class_void_vbox = { - NULL, /* No scanner yet */ - synctex_node_type_void_vbox,/* Node type */ - &_synctex_new_void_vbox, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_void_box, /* log */ - &_synctex_display_void_vbox,/* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -typedef synctex_node_void_vbox_t synctex_node_void_hbox_t; - -/* horizontal void box node creator */ -DEFINE_synctex_new_NODE(void_hbox) - -static void _synctex_display_void_hbox(synctex_node_t node); - -static _synctex_class_t synctex_class_void_hbox = { - NULL, /* No scanner yet */ - synctex_node_type_void_hbox,/* Node type */ - &_synctex_new_void_hbox, /* creator */ - &_synctex_free_node, /* destructor */ - &_synctex_log_void_box, /* log */ - &_synctex_display_void_hbox,/* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -/* The medium nodes correspond to kern, glue, penalty and math nodes. - * In LuaTeX, the size of the nodes may have changed. */ -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[3+SYNCTEX_WIDTH_IDX+1]; /* parent,sibling,friend, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH */ -} synctex_node_medium_t; - -#define SYNCTEX_IS_BOX(NODE)\ - ((NODE->class->type == synctex_node_type_vbox)\ - || (NODE->class->type == synctex_node_type_void_vbox)\ - || (NODE->class->type == synctex_node_type_hbox)\ - || (NODE->class->type == synctex_node_type_void_hbox)) - -#define SYNCTEX_HAS_CHILDREN(NODE) (NODE && SYNCTEX_CHILD(NODE)) - -static void _synctex_log_medium_node(synctex_node_t node); - -typedef synctex_node_medium_t synctex_node_math_t; - -/* math node creator */ -DEFINE_synctex_new_NODE(math) - -static void _synctex_display_math(synctex_node_t node); - -static _synctex_class_t synctex_class_math = { - NULL, /* No scanner yet */ - synctex_node_type_math, /* Node type */ - &_synctex_new_math, /* creator */ - &_synctex_free_leaf, /* destructor */ - &_synctex_log_medium_node, /* log */ - &_synctex_display_math, /* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -typedef synctex_node_medium_t synctex_node_kern_t; - -/* kern node creator */ -DEFINE_synctex_new_NODE(kern) - -static void _synctex_display_kern(synctex_node_t node); - -static _synctex_class_t synctex_class_kern = { - NULL, /* No scanner yet */ - synctex_node_type_kern, /* Node type */ - &_synctex_new_kern, /* creator */ - &_synctex_free_leaf, /* destructor */ - &_synctex_log_medium_node, /* log */ - &_synctex_display_kern, /* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -/* The small nodes correspond to glue and boundary nodes. */ -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[3+SYNCTEX_VERT_IDX+1]; /* parent,sibling,friend, - * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN, - * SYNCTEX_HORIZ,SYNCTEX_VERT */ -} synctex_node_small_t; - -static void _synctex_log_small_node(synctex_node_t node); - -/* glue node creator */ -typedef synctex_node_small_t synctex_node_glue_t; -DEFINE_synctex_new_NODE(glue) -static void _synctex_display_glue(synctex_node_t node); - -static _synctex_class_t synctex_class_glue = { - NULL, /* No scanner yet */ - synctex_node_type_glue, /* Node type */ - &_synctex_new_glue, /* creator */ - &_synctex_free_leaf, /* destructor */ - &_synctex_log_medium_node, /* log */ - &_synctex_display_glue, /* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -/* boundary node creator */ -typedef synctex_node_small_t synctex_node_boundary_t; -DEFINE_synctex_new_NODE(boundary) - -static void _synctex_display_boundary(synctex_node_t node); - -static _synctex_class_t synctex_class_boundary = { - NULL, /* No scanner yet */ - synctex_node_type_boundary, /* Node type */ - &_synctex_new_boundary, /* creator */ - &_synctex_free_leaf, /* destructor */ - &_synctex_log_small_node, /* log */ - &_synctex_display_boundary, /* display */ - &_synctex_implementation_0, /* parent */ - NULL, /* No child */ - &_synctex_implementation_1, /* sibling */ - &_synctex_implementation_2, /* friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_3 -}; - -# define SYNCTEX_NAME_IDX (SYNCTEX_TAG_IDX+1) -# define SYNCTEX_NAME(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_NAME_IDX].PTR - -/* Input nodes only know about their sibling, which is another input node. - * The synctex information is the SYNCTEX_TAG and SYNCTEX_NAME*/ -typedef struct { - SYNCTEX_DECLARE_CHARINDEX - synctex_class_t class; - synctex_info_t implementation[1+SYNCTEX_NAME_IDX+1]; /* sibling, - * SYNCTEX_TAG,SYNCTEX_NAME */ -} synctex_input_t; - -# define SYNCTEX_INPUT_MARK "Input:" -static synctex_node_t _synctex_new_input(synctex_scanner_t scanner) { - if (scanner) { - synctex_node_t node = _synctex_malloc(sizeof(synctex_input_t)); - if (node) { - SYNCTEX_IMPLEMENT_CHARINDEX(node,strlen(SYNCTEX_INPUT_MARK)); - node->class = scanner->class+synctex_node_type_input; - } - return node; - } - return NULL; -} - -static void _synctex_free_input(synctex_node_t node){ - if (node) { - SYNCTEX_FREE(SYNCTEX_SIBLING(node)); - free(SYNCTEX_NAME(node)); - free(node); - } -} - -static void _synctex_display_input(synctex_node_t node); -static void _synctex_log_input(synctex_node_t node); - -static _synctex_class_t synctex_class_input = { - NULL, /* No scanner yet */ - synctex_node_type_input, /* Node type */ - &_synctex_new_input, /* creator */ - &_synctex_free_input, /* destructor */ - &_synctex_log_input, /* log */ - &_synctex_display_input, /* display */ - NULL, /* No parent */ - NULL, /* No child */ - &_synctex_implementation_0, /* sibling */ - NULL, /* No friend */ - NULL, /* No next hbox */ - (_synctex_info_getter_t)&_synctex_implementation_1 -}; - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Navigation -# endif -synctex_node_t synctex_node_parent(synctex_node_t node) -{ - return SYNCTEX_PARENT(node); -} -synctex_node_t synctex_node_sheet(synctex_node_t node) -{ - while(node && node->class->type != synctex_node_type_sheet) { - node = SYNCTEX_PARENT(node); - } - /* exit the while loop either when node is NULL or node is a sheet */ - return node; -} -synctex_node_t synctex_node_child(synctex_node_t node) -{ - return SYNCTEX_CHILD(node); -} -synctex_node_t synctex_node_sibling(synctex_node_t node) -{ - return SYNCTEX_SIBLING(node); -} -synctex_node_t synctex_node_next(synctex_node_t node) { - if (SYNCTEX_CHILD(node)) { - return SYNCTEX_CHILD(node); - } -sibling: - if (SYNCTEX_SIBLING(node)) { - return SYNCTEX_SIBLING(node); - } - if ((node = SYNCTEX_PARENT(node))) { - if (node->class->type == synctex_node_type_sheet) {/* EXC_BAD_ACCESS? */ - return NULL; - } - goto sibling; - } - return NULL; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark CLASS -# endif - -/* Public node accessor: the type */ -synctex_node_type_t synctex_node_type(synctex_node_t node) { - if (node) { - return (((node)->class))->type; - } - return synctex_node_type_error; -} - -/* Public node accessor: the human readable type */ -const char * synctex_node_isa(synctex_node_t node) { -static const char * isa[synctex_node_number_of_types] = - {"Not a node","input","sheet","vbox","void vbox","hbox","void hbox","kern","glue","math","boundary"}; - return isa[synctex_node_type(node)]; -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark SYNCTEX_LOG -# endif - -# define SYNCTEX_LOG(NODE) SYNCTEX_MSG_SEND(NODE,log) - -/* Public node logger */ -void synctex_node_log(synctex_node_t node) { - SYNCTEX_LOG(node); -} - -static void _synctex_log_input(synctex_node_t node) { - if (node) { - printf("%s:%i,%s",synctex_node_isa(node),SYNCTEX_TAG(node),SYNCTEX_NAME(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_log_sheet(synctex_node_t node) { - if (node) { - printf("%s:%i",synctex_node_isa(node),SYNCTEX_PAGE(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node)); - printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node)); - } -} - -static void _synctex_log_small_node(synctex_node_t node) { - if (node) { - printf("%s:%i,%i:%i,%i", - synctex_node_isa(node), - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node)); - } -} - -static void _synctex_log_medium_node(synctex_node_t node) { - if (node) { - printf("%s:%i,%i:%i,%i:%i", - synctex_node_isa(node), - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node)); - } -} - -static void _synctex_log_void_box(synctex_node_t node) { - if (node) { - printf("%s",synctex_node_isa(node)); - printf(":%i",SYNCTEX_TAG(node)); - printf(",%i",SYNCTEX_LINE(node)); - printf(",%i",0); - printf(":%i",SYNCTEX_HORIZ(node)); - printf(",%i",SYNCTEX_VERT(node)); - printf(":%i",SYNCTEX_WIDTH(node)); - printf(",%i",SYNCTEX_HEIGHT(node)); - printf(",%i",SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node)); - } -} - -static void _synctex_log_vbox(synctex_node_t node) { - if (node) { - printf("%s",synctex_node_isa(node)); - printf(":%i",SYNCTEX_TAG(node)); - printf(",%i",SYNCTEX_LINE(node)); - printf(",%i",0); - printf(":%i",SYNCTEX_HORIZ(node)); - printf(",%i",SYNCTEX_VERT(node)); - printf(":%i",SYNCTEX_WIDTH(node)); - printf(",%i",SYNCTEX_HEIGHT(node)); - printf(",%i",SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node)); - printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node)); - } -} - -static void _synctex_log_hbox(synctex_node_t node) { - if (node) { - printf("%s",synctex_node_isa(node)); - printf(":%i",SYNCTEX_TAG(node)); - printf(",%i~%i*%i",SYNCTEX_LINE(node),SYNCTEX_MEAN_LINE(node),SYNCTEX_NODE_WEIGHT(node)); - printf(",%i",0); - printf(":%i",SYNCTEX_HORIZ(node)); - printf(",%i",SYNCTEX_VERT(node)); - printf(":%i",SYNCTEX_WIDTH(node)); - printf(",%i",SYNCTEX_HEIGHT(node)); - printf(",%i",SYNCTEX_DEPTH(node)); - printf("/%i",SYNCTEX_HORIZ_V(node)); - printf(",%i",SYNCTEX_VERT_V(node)); - printf(":%i",SYNCTEX_WIDTH_V(node)); - printf(",%i",SYNCTEX_HEIGHT_V(node)); - printf(",%i",SYNCTEX_DEPTH_V(node)); - SYNCTEX_PRINT_CHARINDEX; - printf("SELF:%p",(void *)node); - printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node)); - printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node)); - printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node)); - printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node)); - printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node)); - } -} - -# define SYNCTEX_DISPLAY(NODE) SYNCTEX_MSG_SEND(NODE,display) - -void synctex_node_display(synctex_node_t node) { - SYNCTEX_DISPLAY(node); -} - -static void _synctex_display_input(synctex_node_t node) { - if (node) { - printf("....Input:%i:%s", - SYNCTEX_TAG(node), - SYNCTEX_NAME(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_sheet(synctex_node_t node) { - if (node) { - printf("....{%i",SYNCTEX_PAGE(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_CHILD(node)); - printf("....}\n"); - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_vbox(synctex_node_t node) { - if (node) { - printf("....[%i,%i:%i,%i:%i,%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node), - SYNCTEX_HEIGHT(node), - SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_CHILD(node)); - printf("....]\n"); - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_hbox(synctex_node_t node) { - if (node) { - printf("....(%i,%i~%i*%i:%i,%i:%i,%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_MEAN_LINE(node), - SYNCTEX_NODE_WEIGHT(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node), - SYNCTEX_HEIGHT(node), - SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_CHILD(node)); - printf("....)\n"); - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_void_vbox(synctex_node_t node) { - if (node) { - printf("....v%i,%i;%i,%i:%i,%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node), - SYNCTEX_HEIGHT(node), - SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_void_hbox(synctex_node_t node) { - if (node) { - printf("....h%i,%i:%i,%i:%i,%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node), - SYNCTEX_HEIGHT(node), - SYNCTEX_DEPTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_glue(synctex_node_t node) { - if (node) { - printf("....glue:%i,%i:%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_math(synctex_node_t node) { - if (node) { - printf("....math:%i,%i:%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_kern(synctex_node_t node) { - if (node) { - printf("....kern:%i,%i:%i,%i:%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node), - SYNCTEX_WIDTH(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -static void _synctex_display_boundary(synctex_node_t node) { - if (node) { - printf("....boundary:%i,%i:%i,%i", - SYNCTEX_TAG(node), - SYNCTEX_LINE(node), - SYNCTEX_HORIZ(node), - SYNCTEX_VERT(node)); - SYNCTEX_PRINT_CHARINDEX; - SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node)); - } -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark SCANNER -# endif - -/* Here are gathered all the possible status that the next scanning functions will return. - * All these functions return a status, and pass their result through pointers. - * Negative values correspond to errors. - * The management of the buffer is causing some significant overhead. - * Every function that may access the buffer returns a status related to the buffer and file state. - * status >= SYNCTEX_STATUS_OK means the function worked as expected - * status < SYNCTEX_STATUS_OK means the function did not work as expected - * status == SYNCTEX_STATUS_NOT_OK means the function did not work as expected but there is still some material to parse. - * status == SYNCTEX_STATUS_EOF means the function did not work as expected and there is no more material. - * statusfile) - -/* Actually, the minimum buffer size is driven by integer and float parsing. - * ±0.123456789e123 - */ -# define SYNCTEX_BUFFER_MIN_SIZE 16 -# define SYNCTEX_BUFFER_SIZE 32768 - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Prototypes -# endif -synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, size_t * size_ptr); -synctex_status_t _synctex_next_line(synctex_scanner_t scanner); -synctex_status_t _synctex_match_string(synctex_scanner_t scanner, const char * the_string); -synctex_status_t _synctex_decode_int(synctex_scanner_t scanner, int* value_ref); -synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value_ref); -synctex_status_t _synctex_scan_input(synctex_scanner_t scanner); -synctex_status_t _synctex_scan_preamble(synctex_scanner_t scanner); -synctex_status_t _synctex_scan_float_and_dimension(synctex_scanner_t scanner, float * value_ref); -synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_t scanner); -int _synctex_scan_postamble(synctex_scanner_t scanner); -synctex_status_t _synctex_setup_visible_box(synctex_node_t box); -synctex_status_t _synctex_hbox_setup_visible(synctex_node_t node,int h, int v); -synctex_status_t _synctex_scan_sheet(synctex_scanner_t scanner, synctex_node_t parent); -synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner); -synctex_status_t _synctex_scan_content(synctex_scanner_t scanner); -int synctex_scanner_pre_x_offset(synctex_scanner_t scanner); -int synctex_scanner_pre_y_offset(synctex_scanner_t scanner); -const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner); -int _synctex_node_is_box(synctex_node_t node); -int _synctex_bail(void); - -/* Try to ensure that the buffer contains at least size bytes. - * Passing a huge size argument means the whole buffer length. - * Passing a null size argument means return the available buffer length, without reading the file. - * In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL, - * in which case, SYNCTEX_STATUS_BAD_ARGUMENT is returned. - * The value returned in size_ptr is the number of bytes now available in the buffer. - * This is a nonnegative integer, it may take the value 0. - * It is the responsibility of the caller to test whether this size is conforming to its needs. - * Negative values may return in case of error, actually - * when there was an error reading the synctex file. */ -synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, size_t * size_ptr) { - size_t available = 0; - if (NULL == scanner || NULL == size_ptr) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } -# define size (* size_ptr) - if (size>SYNCTEX_BUFFER_SIZE){ - size = SYNCTEX_BUFFER_SIZE; - } - available = SYNCTEX_END - SYNCTEX_CUR; /* available is the number of unparsed chars in the buffer */ - if (size<=available) { - /* There are already sufficiently many characters in the buffer */ - size = available; - return SYNCTEX_STATUS_OK; - } - if (SYNCTEX_FILE) { - /* Copy the remaining part of the buffer to the beginning, - * then read the next part of the file */ - int already_read = 0; -# if defined(SYNCTEX_USE_CHARINDEX) - scanner->charindex_offset += SYNCTEX_CUR - SYNCTEX_START; -# endif - if (available) { - memmove(SYNCTEX_START, SYNCTEX_CUR, available); - } - SYNCTEX_CUR = SYNCTEX_START + available; /* the next character after the move, will change. */ - /* Fill the buffer up to its end */ - already_read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,SYNCTEX_BUFFER_SIZE - available); - if (already_read>0) { - /* We assume that 0already_read) { - /* There is a possible error in reading the file */ - int errnum = 0; - const char * error_string = gzerror(SYNCTEX_FILE, &errnum); - if (Z_ERRNO == errnum) { - /* There is an error in zlib caused by the file system */ - _synctex_error("gzread error from the file system (%i)",errno); - return SYNCTEX_STATUS_ERROR; - } else if (errnum) { - _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string); - return SYNCTEX_STATUS_ERROR; - } - } - /* Nothing was read, we are at the end of the file. */ - gzclose(SYNCTEX_FILE); - SYNCTEX_FILE = NULL; - SYNCTEX_END = SYNCTEX_CUR; - SYNCTEX_CUR = SYNCTEX_START; - * SYNCTEX_END = '\0';/* Terminate the string properly.*/ - size = SYNCTEX_END - SYNCTEX_CUR; - return SYNCTEX_STATUS_EOF; /* there might be a bit of text left */ - } - /* We cannot enlarge the buffer because the end of the file was reached. */ - size = available; - return SYNCTEX_STATUS_EOF; -# undef size -} - -/* Used when parsing the synctex file. - * Advance to the next character starting a line. - * Actually, only '\n' is recognized as end of line marker. - * On normal completion, the returned value is the number of unparsed characters available in the buffer. - * In general, it is a positive value, 0 meaning that the end of file was reached. - * -1 is returned in case of error, actually because there was an error while feeding the buffer. - * When the function returns with no error, SYNCTEX_CUR points to the first character of the next line, if any. - * J. Laurens: Sat May 10 07:52:31 UTC 2008 - */ -synctex_status_t _synctex_next_line(synctex_scanner_t scanner) { - synctex_status_t status = SYNCTEX_STATUS_OK; - size_t available = 0; - if (NULL == scanner) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } -infinite_loop: - while(SYNCTEX_CUR=remaining_len) { - /* The buffer is sufficiently big to hold the expected number of characters. */ - if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) { - return SYNCTEX_STATUS_NOT_OK; - } -return_OK: - /* Advance SYNCTEX_CUR to the next character after the_string. */ - SYNCTEX_CUR += remaining_len; - return SYNCTEX_STATUS_OK; - } else if (strncmp((char *)SYNCTEX_CUR,the_string,available)) { - /* No need to go further, this is not the expected string in the buffer. */ - return SYNCTEX_STATUS_NOT_OK; - } else if (SYNCTEX_FILE) { - /* The buffer was too small to contain remaining_len characters. - * We have to cut the string into pieces. */ - z_off_t offset = 0L; - /* the first part of the string is found, advance the_string to the next untested character. */ - the_string += available; - /* update the remaining length and the parsed length. */ - remaining_len -= available; - tested_len += available; - SYNCTEX_CUR += available; /* We validate the tested characters. */ - if (0 == remaining_len) { - /* Nothing left to test, we have found the given string, we return the length. */ - return tested_len; - } - /* We also have to record the current state of the file cursor because - * if the_string does not match, all this should be a totally blank operation, - * for which the file and buffer states should not be modified at all. - * In fact, the states of the buffer before and after this function are in general different - * but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR - * can be safely discarded. */ - offset = gztell(SYNCTEX_FILE); - /* offset now corresponds to the first character of the file that was not buffered. */ - available = SYNCTEX_CUR - SYNCTEX_START; /* available can be used as temporary placeholder. */ - /* available now corresponds to the number of chars that where already buffered and - * that match the head of the_string. If in fine the_string does not match, all these chars must be recovered - * because the buffer contents is completely replaced by _synctex_buffer_get_available_size. - * They were buffered from offset-len location in the file. */ - offset -= available; -more_characters: - /* There is still some work to be done, so read another bunch of file. - * This is the second call to _synctex_buffer_get_available_size, - * which means that the actual contents of the buffer will be discarded. - * We will definitely have to recover the previous state in case we do not find the expected string. */ - available = remaining_len; - status = _synctex_buffer_get_available_size(scanner,&available); - if (statusptr) { - SYNCTEX_CUR = end; - if (value_ref) { - * value_ref = result; - } - return SYNCTEX_STATUS_OK;/* Successfully scanned an int */ - } - return SYNCTEX_STATUS_NOT_OK;/* Could not scan an int */ -} - -/* The purpose of this function is to read a string. - * A string is an array of characters from the current parser location - * and before the next '\n' character. - * If a string was properly decoded, it is returned in value_ref and - * the cursor points to the new line marker. - * The returned string was alloced on the heap, the caller is the owner and - * is responsible to free it in due time. - * If no string is parsed, * value_ref is undefined. - * The maximum length of a string that a scanner can decode is platform dependent, namely UINT_MAX. - * If you just want to blindly parse the file up to the end of the current line, - * use _synctex_next_line instead. - * On return, the scanner cursor is unchanged if a string could not be scanned or - * points to the terminating '\n' character otherwise. As a consequence, - * _synctex_next_line is necessary after. - * If either scanner or value_ref is NULL, it is considered as an error and - * SYNCTEX_STATUS_BAD_ARGUMENT is returned. - */ -synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value_ref) { - char * end = NULL; - size_t current_size = 0; - size_t new_size = 0; - size_t len = 0;/* The number of bytes to copy */ - size_t available = 0; - synctex_status_t status = 0; - if (NULL == scanner || NULL == value_ref) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - /* The buffer must at least contain one character: the '\n' end of line marker */ - if (SYNCTEX_CUR>=SYNCTEX_END) { - available = 1; - status = _synctex_buffer_get_available_size(scanner,&available); - if (status < 0) { - return status; - } - if (0 == available) { - return SYNCTEX_STATUS_EOF; - } - } - /* Now we are sure that there is at least one available character, either because - * SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */ - /* end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */ - end = SYNCTEX_CUR; - * value_ref = NULL;/* Initialize, it will be realloc'ed */ - /* We scan all the characters up to the next '\n' */ -next_character: - if (endUINT_MAX-len-1) { - /* But we have reached the limit: we do not have current_size+len+1>UINT_MAX. - * We return the missing amount of memory. - * This will never occur in practice. */ - return UINT_MAX-len-1 - current_size; - } - new_size = current_size+len; - /* We have current_size+len+1<=UINT_MAX - * or equivalently new_sizeUINT_MAX-len-1) { - /* We have reached the limit. */ - _synctex_error("limit reached (missing %i).",current_size-(UINT_MAX-len-1)); - return SYNCTEX_STATUS_ERROR; - } - new_size = current_size+len; - if ((* value_ref = realloc(* value_ref,new_size+1)) != NULL) { - if (memcpy((*value_ref)+current_size,SYNCTEX_CUR,len)) { - (* value_ref)[new_size]='\0'; /* Terminate the string */ - SYNCTEX_CUR = SYNCTEX_END;/* Advance the cursor to the end of the bufer */ - return SYNCTEX_STATUS_OK; - } - free(* value_ref); - * value_ref = NULL; - _synctex_error("could not copy memory (2)."); - return SYNCTEX_STATUS_ERROR; - } - /* Huge memory problem */ - _synctex_error("could not allocate memory (2)."); - return SYNCTEX_STATUS_ERROR; - } -} - -/* Used when parsing the synctex file. - * Read an Input record. - */ -synctex_status_t _synctex_scan_input(synctex_scanner_t scanner) { - synctex_status_t status = 0; - size_t available = 0; - synctex_node_t input = NULL; - if (NULL == scanner) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - status = _synctex_match_string(scanner,SYNCTEX_INPUT_MARK); - if (statusinput); - scanner->input = input; -# if SYNCTEX_VERBOSE - synctex_node_log(input); -# endif - return _synctex_next_line(scanner);/* read the line termination character, if any */ - /* Now, set up the path */ -} - -typedef synctex_status_t (*synctex_decoder_t)(synctex_scanner_t,void *); - -synctex_status_t _synctex_scan_named(synctex_scanner_t scanner,const char * name,void * value_ref,synctex_decoder_t decoder); - -/* Used when parsing the synctex file. - * Read one of the settings. - * On normal completion, returns SYNCTEX_STATUS_OK. - * On error, returns SYNCTEX_STATUS_ERROR. - * Both arguments must not be NULL. - * On return, the scanner points to the next character after the decoded object whatever it is. - * It is the responsibility of the caller to prepare the scanner for the next line. - */ -synctex_status_t _synctex_scan_named(synctex_scanner_t scanner,const char * name,void * value_ref,synctex_decoder_t decoder) { - synctex_status_t status = 0; - if (NULL == scanner || NULL == name || NULL == value_ref || NULL == decoder) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } -not_found: - status = _synctex_match_string(scanner,name); - if (statusversion),(synctex_decoder_t)&_synctex_decode_int); - if (statusoutput_fmt),(synctex_decoder_t)&_synctex_decode_string); - if (statuspre_magnification),(synctex_decoder_t)&_synctex_decode_int); - if (statuspre_unit),(synctex_decoder_t)&_synctex_decode_int); - if (statuspre_x_offset),(synctex_decoder_t)&_synctex_decode_int); - if (statuspre_y_offset),(synctex_decoder_t)&_synctex_decode_int); - if (status= SYNCTEX_STATUS_OK) { - f *= 72.27f*65536; - } else if (status= SYNCTEX_STATUS_OK) { - f *= 72.27f*65536/2.54f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"mm")) >= SYNCTEX_STATUS_OK) { - f *= 72.27f*65536/25.4f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"pt")) >= SYNCTEX_STATUS_OK) { - f *= 65536.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"bp")) >= SYNCTEX_STATUS_OK) { - f *= 72.27f/72*65536.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"pc")) >= SYNCTEX_STATUS_OK) { - f *= 12.0*65536.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"sp")) >= SYNCTEX_STATUS_OK) { - f *= 1.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"dd")) >= SYNCTEX_STATUS_OK) { - f *= 1238.0f/1157*65536.0f; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"cc")) >= SYNCTEX_STATUS_OK) { - f *= 14856.0f/1157*65536; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"nd")) >= SYNCTEX_STATUS_OK) { - f *= 685.0f/642*65536; - } else if (status<0) { - goto report_unit_error; - } else if ((status = _synctex_match_string(scanner,"nc")) >= SYNCTEX_STATUS_OK) { - f *= 1370.0f/107*65536; - } else if (status<0) { - goto report_unit_error; - } - *value_ref = f; - return SYNCTEX_STATUS_OK; -} - -/* parse the post scriptum - * SYNCTEX_STATUS_OK is returned on completion - * a negative error is returned otherwise */ -synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_t scanner) { - synctex_status_t status = 0; - char * endptr = NULL; -#ifdef HAVE_SETLOCALE - char * loc = setlocale(LC_NUMERIC, NULL); -#endif - if (NULL == scanner) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - /* Scan the file until a post scriptum line is found */ -post_scriptum_not_found: - status = _synctex_match_string(scanner,"Post scriptum:"); - if (statusunit = strtod(SYNCTEX_CUR,&endptr); -#ifdef HAVE_SETLOCALE - setlocale(LC_NUMERIC, loc); -#endif - if (endptr == SYNCTEX_CUR) { - _synctex_error("bad magnification in the post scriptum, a float was expected."); - return SYNCTEX_STATUS_ERROR; - } - if (scanner->unit<=0) { - _synctex_error("bad magnification in the post scriptum, a positive float was expected."); - return SYNCTEX_STATUS_ERROR; - } - SYNCTEX_CUR = endptr; - goto next_line; - } - if (statusx_offset)); - if (statusy_offset)); - if (statuscount),(synctex_decoder_t)&_synctex_decode_int); - if (status < SYNCTEX_STATUS_EOF) { - return status; /* forward the error */ - } else if (status < SYNCTEX_STATUS_OK) { /* No Count record found */ - status = _synctex_next_line(scanner); /* Advance one more line */ - if (statusclass->type) { - case synctex_node_type_hbox: - if (SYNCTEX_INFO(box) != NULL) { - SYNCTEX_HORIZ_V(box) = SYNCTEX_HORIZ(box); - SYNCTEX_VERT_V(box) = SYNCTEX_VERT(box); - SYNCTEX_WIDTH_V(box) = SYNCTEX_WIDTH(box); - SYNCTEX_HEIGHT_V(box) = SYNCTEX_HEIGHT(box); - SYNCTEX_DEPTH_V(box) = SYNCTEX_DEPTH(box); - return SYNCTEX_STATUS_OK; - } - return SYNCTEX_STATUS_ERROR; - } - } - return SYNCTEX_STATUS_BAD_ARGUMENT; -} - -/* This method is sent to an horizontal box to setup the visible size - * Some box have 0 width but do contain text material. - * With this method, one can enlarge the box to contain the given point (h,v). - */ -synctex_status_t _synctex_hbox_setup_visible(synctex_node_t node,int h, int v) { -# ifdef __DARWIN_UNIX03 -# pragma unused(v) -# endif - int itsBtm, itsTop; - if (NULL == node || node->class->type != synctex_node_type_hbox) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - if (SYNCTEX_WIDTH_V(node)<0) { - itsBtm = SYNCTEX_HORIZ_V(node); - itsTop = SYNCTEX_HORIZ_V(node)-SYNCTEX_WIDTH_V(node); - if (hitsTop) { - SYNCTEX_WIDTH_V(node) = SYNCTEX_HORIZ_V(node) - h; - } - } else { - itsBtm = SYNCTEX_HORIZ_V(node); - itsTop = SYNCTEX_HORIZ_V(node)+SYNCTEX_WIDTH_V(node); - if (hitsTop) { - SYNCTEX_WIDTH_V(node) = h - SYNCTEX_HORIZ_V(node); - } - } - return SYNCTEX_STATUS_OK; -} - -/* Here are the control characters that strat each line of the synctex output file. - * Their values define the meaning of the line. - */ -# define SYNCTEX_CHAR_BEGIN_SHEET '{' -# define SYNCTEX_CHAR_END_SHEET '}' -# define SYNCTEX_CHAR_BEGIN_VBOX '[' -# define SYNCTEX_CHAR_END_VBOX ']' -# define SYNCTEX_CHAR_BEGIN_HBOX '(' -# define SYNCTEX_CHAR_END_HBOX ')' -# define SYNCTEX_CHAR_ANCHOR '!' -# define SYNCTEX_CHAR_VOID_VBOX 'v' -# define SYNCTEX_CHAR_VOID_HBOX 'h' -# define SYNCTEX_CHAR_KERN 'k' -# define SYNCTEX_CHAR_GLUE 'g' -# define SYNCTEX_CHAR_MATH '$' -# define SYNCTEX_CHAR_BOUNDARY 'x' - -# define SYNCTEX_RETURN(STATUS) return STATUS; - -/* Used when parsing the synctex file. A '{' character has just been parsed. - * The purpose is to gobble everything until the closing '}'. - * Actually only one nesting depth has been observed when using the clip option - * of \includegraphics option. Here we use arbitrary level of depth. - */ -synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner) { - unsigned int depth = 0; -deeper: - ++depth; - if (_synctex_next_line(scanner)0) { - goto scan_next_line; - } else { - SYNCTEX_RETURN(SYNCTEX_STATUS_OK); - } - } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) { - ++SYNCTEX_CUR; - goto deeper; - - } else if (_synctex_next_line(scanner)class->type != synctex_node_type_sheet - || _synctex_next_line(scanner)0){ - _synctex_error("Uncomplete sheet(0)"); - SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); - } - goto prepare_loop; - } - _synctex_bail(); -/* The child loop means that we go down one level, when we just created a box node, - * the next node created is a child of this box. */ -child_loop: - if (SYNCTEX_CURclass->type == synctex_node_type_vbox) { - #define SYNCTEX_UPDATE_BOX_FRIEND(NODE)\ - friend_index = ((SYNCTEX_INFO(NODE))[SYNCTEX_TAG_IDX].INT+(SYNCTEX_INFO(NODE))[SYNCTEX_LINE_IDX].INT)%(scanner->number_of_lists);\ - SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\ - (scanner->lists_of_friends)[friend_index] = NODE; - if (NULL == SYNCTEX_CHILD(parent)) { - /* only void boxes are friends */ - SYNCTEX_UPDATE_BOX_FRIEND(parent); - } - child = parent; - parent = SYNCTEX_PARENT(child); - } else { - _synctex_error("Unexpected end of vbox, ignored."); - } - if (_synctex_next_line(scanner)class->type == synctex_node_type_hbox) { - /* Update the mean line number */ - synctex_node_t node = SYNCTEX_CHILD(parent); - if (node) { - unsigned int node_weight = 0; - unsigned int cumulated_line_numbers = 0; - do { - if (synctex_node_type(node)==synctex_node_type_hbox) { - if (SYNCTEX_NODE_WEIGHT(node)) { - node_weight += SYNCTEX_NODE_WEIGHT(node); - cumulated_line_numbers += SYNCTEX_MEAN_LINE(node)*SYNCTEX_NODE_WEIGHT(node); - } else { - ++node_weight; - cumulated_line_numbers += SYNCTEX_MEAN_LINE(node); - } - } else { - ++node_weight; - cumulated_line_numbers += SYNCTEX_LINE(node); - } - } while ((node = SYNCTEX_SIBLING(node))); - SYNCTEX_MEAN_LINE(parent)=(cumulated_line_numbers + node_weight/2)/node_weight; - SYNCTEX_NODE_WEIGHT(parent)=node_weight; - } else { - SYNCTEX_MEAN_LINE(parent)=SYNCTEX_LINE(parent); - SYNCTEX_NODE_WEIGHT(parent)=1; - } - if (NULL == child) { - /* Only boxes with no children are friends, - * boxes with children are indirectly friends through one of their contained nodes. */ - SYNCTEX_UPDATE_BOX_FRIEND(parent); - } - /* setting the next horizontal box at the end ensures that a child is recorded before any of its ancestors. */ - SYNCTEX_SET_NEXT_hbox(box,parent); - box = parent; - child = parent; - parent = SYNCTEX_PARENT(child); - } else { - _synctex_error("Unexpected end of hbox, ignored."); - } - if (_synctex_next_line(scanner)number_of_lists);\ - SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\ - (scanner->lists_of_friends)[friend_index] = NODE; - SYNCTEX_UPDATE_FRIEND(child); -# if SYNCTEX_VERBOSE - synctex_node_log(child); -# endif - goto sibling_loop; - } else { - _synctex_error("Can't create vbox record."); - SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); - } - } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_HBOX) { - if (NULL != (child = _synctex_new_void_hbox(scanner)) - && NULL != (info = SYNCTEX_INFO(child))) { - if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX) - || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX) - || _synctex_next_line(scanner)0){ - _synctex_error("Uncomplete sheet(0)"); - SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); - } else { - goto child_loop; - } - } - _synctex_bail(); -/* The vertical loop means that we are on the same level, for example when we just ended a box. - * If a node is created now, it will be a sibling of the current node, sharing the same parent. */ -sibling_loop: - if (SYNCTEX_CUR0){ - goto sibling_loop; - } else { - _synctex_error("Uncomplete sheet(2)"); - SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); - } - } -# undef SYNCTEX_DECODE_FAILED -} - -# define SYNCTEX_APPEND_SHEET(SCANNER,SHEET) if (SCANNER->sheet) {\ - synctex_node_t last_sheet = SCANNER->sheet;\ - synctex_node_t next_sheet = NULL;\ - while ((next_sheet = SYNCTEX_SIBLING(last_sheet))) {\ - last_sheet = next_sheet;\ - }\ - SYNCTEX_SET_SIBLING(last_sheet,SHEET);\ - } else {\ - SCANNER->sheet = SHEET;\ - } - -/* Used when parsing the synctex file - */ -synctex_status_t _synctex_scan_content(synctex_scanner_t scanner) { - synctex_node_t sheet = NULL; - synctex_status_t status = 0; - if (NULL == scanner) { - return SYNCTEX_STATUS_BAD_ARGUMENT; - } - /* set up the lists of friends */ - if (NULL == scanner->lists_of_friends) { - scanner->number_of_lists = 1024; - scanner->lists_of_friends = (synctex_node_t *)_synctex_malloc(scanner->number_of_lists*sizeof(synctex_node_t)); - if (NULL == scanner->lists_of_friends) { - _synctex_error("malloc:2"); - return SYNCTEX_STATUS_ERROR; - } - } - /* Find where this section starts */ -content_not_found: - status = _synctex_match_string(scanner,"Content:"); - if (status= SYNCTEX_STATUS_OK); - goto next_sheet; -} - -int _synctex_open(const char * output, const char * build_directory, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_modeRef); - -/* Where the synctex scanner is created. */ -synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) { - gzFile file = NULL; - char * synctex = NULL; - synctex_scanner_t scanner = NULL; - synctex_io_mode_t io_mode = 0; - /* Here we assume that int are smaller than void * */ - if (sizeof(int)>sizeof(void*)) { - _synctex_error("INTERNAL INCONSISTENCY: int's are unexpectedly bigger than pointers, bailing out."); - return NULL; - } - /* We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */ - if (SYNCTEX_BUFFER_SIZE >= UINT_MAX) { - _synctex_error("Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (1)"); - return NULL; - } - /* for integers: */ - if (SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE) { - _synctex_error("Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (2)"); - return NULL; - } - /* now open the synctex file */ - if (_synctex_open(output,build_directory,&synctex,&file,synctex_ADD_QUOTES,&io_mode) || !file) { - if (_synctex_open(output,build_directory,&synctex,&file,synctex_DONT_ADD_QUOTES,&io_mode) || !file) { - return NULL; - } - } - scanner = (synctex_scanner_t)_synctex_malloc(sizeof(_synctex_scanner_t)); - if (NULL == scanner) { - _synctex_error("malloc problem"); - free(synctex); - gzclose(file); - return NULL; - } - /* make a private copy of output for the scanner */ - if (NULL == (scanner->output = (char *)malloc(strlen(output)+1))){ - _synctex_error("! synctex_scanner_new_with_output_file: Memory problem (2), scanner's output is not reliable."); - } else if (scanner->output != strcpy(scanner->output,output)) { - _synctex_error("! synctex_scanner_new_with_output_file: Copy problem, scanner's output is not reliable."); - } - scanner->synctex = synctex;/* Now the scanner owns synctex */ - SYNCTEX_FILE = file; - return parse? synctex_scanner_parse(scanner):scanner; -} - -/* This functions opens the file at the "output" given location. - * It manages the problem of quoted filenames that appear with pdftex and filenames containing the space character. - * In TeXLive 2008, the synctex file created with pdftex did contain unexpected quotes. - * This function will remove them if possible. - * All the reference arguments will take a value on return. They must be non NULL. - * 0 on success, non 0 on error. */ -static int __synctex_open(const char * output, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_mode_ref) { - if (synctex_name_ref && file_ref && io_mode_ref) { - /* 1 local variables that uses dynamic memory */ - char * synctex_name = NULL; - gzFile the_file = NULL; - char * quoteless_synctex_name = NULL; - size_t size = 0; - synctex_io_mode_t io_mode = *io_mode_ref; - const char * mode = _synctex_get_io_mode_name(io_mode); - /* now create the synctex file name */ - size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1; - synctex_name = (char *)malloc(size); - if (NULL == synctex_name) { - _synctex_error("! __synctex_open: Memory problem (1)\n"); - return 1; - } - /* we have reserved for synctex enough memory to copy output (including its 2 eventual quotes), both suffices, - * including the terminating character. size is free now. */ - if (synctex_name != strcpy(synctex_name,output)) { - _synctex_error("! __synctex_open: Copy problem\n"); -return_on_error: - free(synctex_name); - free(quoteless_synctex_name); - return 2; - } - /* remove the last path extension if any */ - _synctex_strip_last_path_extension(synctex_name); - if (!strlen(synctex_name)) { - goto return_on_error; - } - /* now insert quotes. */ - if (add_quotes) { - char * quoted = NULL; - if (_synctex_copy_with_quoting_last_path_component(synctex_name,"ed,size) || (NULL == quoted)) { - /* There was an error or quoting does not make sense: */ - goto return_on_error; - } - quoteless_synctex_name = synctex_name; - synctex_name = quoted; - } - /* Now add to synctex_name the first path extension. */ - if (synctex_name != strcat(synctex_name,synctex_suffix)){ - _synctex_error("! __synctex_open: Concatenation problem (can't add suffix '%s')\n",synctex_suffix); - goto return_on_error; - } - /* Add to quoteless_synctex_name as well, if relevant. */ - if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix))){ - free(quoteless_synctex_name); - quoteless_synctex_name = NULL; - } - if (NULL == (the_file = gzopen(synctex_name,mode))) { - /* Could not open this file */ - if (errno != ENOENT) { - /* The file does exist, this is a lower level error, I can't do anything. */ - _synctex_error("could not open %s, error %i\n",synctex_name,errno); - goto return_on_error; - } - /* Apparently, there is no uncompressed synctex file. Try the compressed version */ - if (synctex_name != strcat(synctex_name,synctex_suffix_gz)){ - _synctex_error("! __synctex_open: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz); - goto return_on_error; - } - io_mode |= synctex_io_gz_mask; - mode = _synctex_get_io_mode_name(io_mode); /* the file is a compressed and is a binary file, this caused errors on Windows */ - /* Add the suffix to the quoteless_synctex_name as well. */ - if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix_gz))){ - free(quoteless_synctex_name); - quoteless_synctex_name = NULL; - } - if (NULL == (the_file = gzopen(synctex_name,mode))) { - /* Could not open this file */ - if (errno != ENOENT) { - /* The file does exist, this is a lower level error, I can't do anything. */ - _synctex_error("Could not open %s, error %i\n",synctex_name,errno); - } - goto return_on_error; - } - } - /* At this point, the file is properly open. - * If we are in the add_quotes mode, we change the file name by removing the quotes. */ - if (quoteless_synctex_name) { - gzclose(the_file); - if (rename(synctex_name,quoteless_synctex_name)) { - _synctex_error("Could not rename %s to %s, error %i\n",synctex_name,quoteless_synctex_name,errno); - /* We could not rename, reopen the file with the quoted name. */ - if (NULL == (the_file = gzopen(synctex_name,mode))) { - /* No luck, could not re open this file, something has happened meanwhile */ - if (errno != ENOENT) { - /* The file does not exist any more, it has certainly be removed somehow - * this is a lower level error, I can't do anything. */ - _synctex_error("Could not open again %s, error %i\n",synctex_name,errno); - } - goto return_on_error; - } - } else { - /* The file has been successfully renamed */ - if (NULL == (the_file = gzopen(quoteless_synctex_name,mode))) { - /* Could not open this file */ - if (errno != ENOENT) { - /* The file does exist, this is a lower level error, I can't do anything. */ - _synctex_error("Could not open renamed %s, error %i\n",quoteless_synctex_name,errno); - } - goto return_on_error; - } - /* The quote free file name should replace the old one:*/ - free(synctex_name); - synctex_name = quoteless_synctex_name; - quoteless_synctex_name = NULL; - } - } - /* The operation is successfull, return the arguments by value. */ - * file_ref = the_file; - * io_mode_ref = io_mode; - * synctex_name_ref = synctex_name; - return 0; - } - return 3; /* Bad parameter. */ -} - -/* Opens the ouput file, taking into account the eventual build_directory. - * 0 on success, non 0 on error. */ -int _synctex_open(const char * output, const char * build_directory, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_mode_ref) { -# define synctex_name (*synctex_name_ref) -# define the_file (*file_ref) - int result = __synctex_open(output,synctex_name_ref,file_ref,add_quotes,io_mode_ref); - if ((result || !*file_ref) && build_directory && strlen(build_directory)) { - char * build_output; - const char *lpc; - size_t size; - synctex_bool_t is_absolute; - build_output = NULL; - lpc = _synctex_last_path_component(output); - size = strlen(build_directory)+strlen(lpc)+2; /* One for the '/' and one for the '\0'. */ - is_absolute = _synctex_path_is_absolute(build_directory); - if (!is_absolute) { - size += strlen(output); - } - if ((build_output = (char *)malloc(size))) { - if (is_absolute) { - build_output[0] = '\0'; - } else { - if (build_output != strcpy(build_output,output)) { - free(build_output); - return -4; - } - build_output[lpc-output]='\0'; - } - if (build_output == strcat(build_output,build_directory)) { - /* Append a path separator if necessary. */ - if (!SYNCTEX_IS_PATH_SEPARATOR(build_output[strlen(build_directory)-1])) { - if (build_output != strcat(build_output,"/")) { - free(build_output); - return -2; - } - } - /* Append the last path component of the output. */ - if (build_output != strcat(build_output,lpc)) { - free(build_output); - return -3; - } - result = __synctex_open(build_output,synctex_name_ref,file_ref,add_quotes,io_mode_ref); - free(build_output); - return result; - } - free(build_output); - } - return -1; - } - return result; -# undef synctex_name -# undef the_file -} - -/* The scanner destructor - */ -void synctex_scanner_free(synctex_scanner_t scanner) { - if (NULL == scanner) { - return; - } - if (SYNCTEX_FILE) { - gzclose(SYNCTEX_FILE); - SYNCTEX_FILE = NULL; - } - SYNCTEX_FREE(scanner->sheet); - SYNCTEX_FREE(scanner->input); - free(SYNCTEX_START); - free(scanner->output_fmt); - free(scanner->output); - free(scanner->synctex); - free(scanner->lists_of_friends); - free(scanner); -} - -/* Where the synctex scanner parses the contents of the file. */ -synctex_scanner_t synctex_scanner_parse(synctex_scanner_t scanner) { - synctex_status_t status = 0; - if (!scanner || scanner->flags.has_parsed) { - return scanner; - } - scanner->flags.has_parsed=1; - scanner->pre_magnification = 1000; - scanner->pre_unit = 8192; - scanner->pre_x_offset = scanner->pre_y_offset = 578; - /* initialize the offset with a fake unprobable value, - * If there is a post scriptum section, this value will be overriden by the real life value */ - scanner->x_offset = scanner->y_offset = 6.027e23f; -# define DEFINE_synctex_scanner_class(NAME)\ - scanner->class[synctex_node_type_##NAME] = synctex_class_##NAME;\ - (scanner->class[synctex_node_type_##NAME]).scanner = scanner - DEFINE_synctex_scanner_class(sheet); - DEFINE_synctex_scanner_class(input); - DEFINE_synctex_scanner_class(hbox); - DEFINE_synctex_scanner_class(void_hbox); - DEFINE_synctex_scanner_class(vbox); - DEFINE_synctex_scanner_class(void_vbox); - DEFINE_synctex_scanner_class(kern); - DEFINE_synctex_scanner_class(glue); - DEFINE_synctex_scanner_class(math); - DEFINE_synctex_scanner_class(boundary); - SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE+1); /* one more character for null termination */ - if (NULL == SYNCTEX_START) { - _synctex_error("malloc error"); - synctex_scanner_free(scanner); - return NULL; - } - SYNCTEX_END = SYNCTEX_START+SYNCTEX_BUFFER_SIZE; - /* SYNCTEX_END always points to a null terminating character. - * Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1. - * At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */ - *SYNCTEX_END = '\0'; - SYNCTEX_CUR = SYNCTEX_END; -# if defined(SYNCTEX_USE_CHARINDEX) - scanner->charindex_offset = -SYNCTEX_BUFFER_SIZE; -# endif - status = _synctex_scan_preamble(scanner); - if (statuspre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp - * 1 pt = 65536 sp */ - if (scanner->pre_unit<=0) { - scanner->pre_unit = 8192; - } - if (scanner->pre_magnification<=0) { - scanner->pre_magnification = 1000; - } - if (scanner->unit <= 0) { - /* no post magnification */ - scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/ - } else { - /* post magnification */ - scanner->unit *= scanner->pre_unit / 65781.76; - } - scanner->unit *= scanner->pre_magnification / 1000.0; - if (scanner->x_offset > 6e23) { - /* no post offset */ - scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76); - scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76); - } else { - /* post offset */ - scanner->x_offset /= 65781.76f; - scanner->y_offset /= 65781.76f; - } - return scanner; - #undef SYNCTEX_FILE -} - -/* Scanner accessors. - */ -int synctex_scanner_pre_x_offset(synctex_scanner_t scanner){ - return scanner?scanner->pre_x_offset:0; -} -int synctex_scanner_pre_y_offset(synctex_scanner_t scanner){ - return scanner?scanner->pre_y_offset:0; -} -int synctex_scanner_x_offset(synctex_scanner_t scanner){ - return scanner?scanner->x_offset:0; -} -int synctex_scanner_y_offset(synctex_scanner_t scanner){ - return scanner?scanner->y_offset:0; -} -float synctex_scanner_magnification(synctex_scanner_t scanner){ - return scanner?scanner->unit:1; -} -void synctex_scanner_display(synctex_scanner_t scanner) { - if (NULL == scanner) { - return; - } - printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n",scanner->output,scanner->output_fmt,scanner->version); - printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n",scanner->pre_unit,scanner->pre_x_offset,scanner->pre_y_offset); - printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n", - scanner->count,scanner->unit,scanner->x_offset,scanner->y_offset); - printf("The input:\n"); - SYNCTEX_DISPLAY(scanner->input); - if (scanner->count<1000) { - printf("The sheets:\n"); - SYNCTEX_DISPLAY(scanner->sheet); - printf("The friends:\n"); - if (scanner->lists_of_friends) { - int i = scanner->number_of_lists; - synctex_node_t node; - while(i--) { - printf("Friend index:%i\n",i); - node = (scanner->lists_of_friends)[i]; - while(node) { - printf("%s:%i,%i\n", - synctex_node_isa(node), - SYNCTEX_TAG(node), - SYNCTEX_LINE(node) - ); - node = SYNCTEX_FRIEND(node); - } - } - } - } else { - printf("SyncTeX Warning: Too many objects\n"); - } -} -/* Public*/ -const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag) { - synctex_node_t input = NULL; - if (NULL == scanner) { - return NULL; - } - input = scanner->input; - do { - if (tag == SYNCTEX_TAG(input)) { - return (SYNCTEX_NAME(input)); - } - } while((input = SYNCTEX_SIBLING(input)) != NULL); - return NULL; -} - -int _synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name); -int _synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name) { - synctex_node_t input = NULL; - if (NULL == scanner) { - return 0; - } - input = scanner->input; - do { - if (_synctex_is_equivalent_file_name(name,(SYNCTEX_NAME(input)))) { - return SYNCTEX_TAG(input); - } - } while((input = SYNCTEX_SIBLING(input)) != NULL); - // 2011 version - name = _synctex_base_name(name); - input = scanner->input; - do { - if (_synctex_is_equivalent_file_name(name,_synctex_base_name(SYNCTEX_NAME(input)))) { - synctex_node_t other_input = input; - while((other_input = SYNCTEX_SIBLING(other_input)) != NULL) { - if (_synctex_is_equivalent_file_name(name,_synctex_base_name(SYNCTEX_NAME(other_input))) - && (strlen(SYNCTEX_NAME(input))!=strlen(SYNCTEX_NAME(other_input)) - || strncmp(SYNCTEX_NAME(other_input),SYNCTEX_NAME(input),strlen(SYNCTEX_NAME(input))))) { - // There is a second possible candidate - return 0; - } - } - return SYNCTEX_TAG(input); - } - } while((input = SYNCTEX_SIBLING(input)) != NULL); - return 0; -} - -int synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name) { - size_t char_index = strlen(name); - if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) { - /* the name is not void */ - char_index -= 1; - if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) { - /* the last character of name is not a path separator */ - int result = _synctex_scanner_get_tag(scanner,name); - if (result) { - return result; - } else { - /* the given name was not the one known by TeX - * try a name relative to the enclosing directory of the scanner->output file */ - const char * relative = name; - const char * ptr = scanner->output; - while((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr)) - { - relative += 1; - ptr += 1; - } - /* Find the last path separator before relative */ - while(relative > name) { - if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) { - break; - } - relative -= 1; - } - if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) { - return result; - } - if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) { - /* No tag found for the given absolute name, - * Try each relative path starting from the shortest one */ - while(0input:NULL; -} -const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner) { - return NULL != scanner && scanner->output_fmt?scanner->output_fmt:""; -} -const char * synctex_scanner_get_output(synctex_scanner_t scanner) { - return NULL != scanner && scanner->output?scanner->output:""; -} -const char * synctex_scanner_get_synctex(synctex_scanner_t scanner) { - return NULL != scanner && scanner->synctex?scanner->synctex:""; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Public node attributes -# endif -int synctex_node_h(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_HORIZ(node); -} -int synctex_node_v(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_VERT(node); -} -int synctex_node_width(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_WIDTH(node); -} -int synctex_node_box_h(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_HORIZ(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -int synctex_node_box_v(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_VERT(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -int synctex_node_box_width(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_WIDTH(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -int synctex_node_box_height(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_HEIGHT(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -int synctex_node_box_depth(synctex_node_t node){ - if (!node) { - return 0; - } - if (SYNCTEX_IS_BOX(node)) { -result: - return SYNCTEX_DEPTH(node); - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Public node visible attributes -# endif -float synctex_node_visible_h(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset; -} -float synctex_node_visible_v(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset; -} -float synctex_node_visible_width(synctex_node_t node){ - if (!node) { - return 0; - } - return SYNCTEX_WIDTH(node)*node->class->scanner->unit; -} -float synctex_node_box_visible_h(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset; - case synctex_node_type_hbox: -result: - return SYNCTEX_HORIZ_V(node)*node->class->scanner->unit+node->class->scanner->x_offset; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -float synctex_node_box_visible_v(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset; - case synctex_node_type_hbox: -result: - return SYNCTEX_VERT_V(node)*node->class->scanner->unit+node->class->scanner->y_offset; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -float synctex_node_box_visible_width(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_WIDTH(node)*node->class->scanner->unit; - case synctex_node_type_hbox: -result: - return SYNCTEX_WIDTH_V(node)*node->class->scanner->unit; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -float synctex_node_box_visible_height(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_HEIGHT(node)*node->class->scanner->unit; - case synctex_node_type_hbox: -result: - return SYNCTEX_HEIGHT_V(node)*node->class->scanner->unit; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -float synctex_node_box_visible_depth(synctex_node_t node){ - if (!node) { - return 0; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - return SYNCTEX_DEPTH(node)*node->class->scanner->unit; - case synctex_node_type_hbox: -result: - return SYNCTEX_DEPTH_V(node)*node->class->scanner->unit; - } - if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) { - goto result; - } - return 0; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Other public node attributes -# endif - -int synctex_node_page(synctex_node_t node){ - synctex_node_t parent = NULL; - if (!node) { - return -1; - } - parent = SYNCTEX_PARENT(node); - while(parent) { - node = parent; - parent = SYNCTEX_PARENT(node); - } - if (node->class->type == synctex_node_type_sheet) { - return SYNCTEX_PAGE(node); - } - return -1; -} -synctex_charindex_t synctex_node_charindex(synctex_node_t node) { - return node?SYNCTEX_CHARINDEX(node):0; -} -int synctex_node_tag(synctex_node_t node) { - return node?SYNCTEX_TAG(node):-1; -} -int synctex_node_line(synctex_node_t node) { - return node?SYNCTEX_LINE(node):-1; -} -int synctex_node_mean_line(synctex_node_t node) { - return node?(node->class->type==synctex_node_type_hbox?SYNCTEX_MEAN_LINE(node):SYNCTEX_LINE(node)):-1; -} -int synctex_node_child_count(synctex_node_t node) { - return node?(node->class->type==synctex_node_type_hbox?SYNCTEX_NODE_WEIGHT(node):0):-1; -} -int synctex_node_column(synctex_node_t node) { -# ifdef __DARWIN_UNIX03 -# pragma unused(node) -# endif - return -1; -} -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Sheet -# endif - -synctex_node_t synctex_sheet(synctex_scanner_t scanner,int page) { - if (scanner) { - synctex_node_t sheet = scanner->sheet; - while(sheet) { - if (page == SYNCTEX_PAGE(sheet)) { - return sheet; - } - sheet = SYNCTEX_SIBLING(sheet); - } - } - return NULL; -} - -synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page) { - if (scanner) { - return SYNCTEX_CHILD(synctex_sheet(scanner,page)); - } - return NULL; -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Query -# endif - -int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column) { -# ifdef __DARWIN_UNIX03 -# pragma unused(column) -# endif - int tag = synctex_scanner_get_tag(scanner,name); - size_t size = 0; - int friend_index = 0; - int max_line = 0; - synctex_node_t node = NULL; - if (tag == 0) { - printf("SyncTeX Warning: No tag for %s\n",name); - return -1; - } - free(SYNCTEX_START); - SYNCTEX_CUR = SYNCTEX_END = SYNCTEX_START = NULL; - max_line = line < INT_MAX-scanner->number_of_lists ? line+scanner->number_of_lists:INT_MAX; - while(linenumber_of_lists); - if ((node = (scanner->lists_of_friends)[friend_index])) { - do { - if ((synctex_node_type(node)>=synctex_node_type_boundary) - && (tag == SYNCTEX_TAG(node)) - && (line == SYNCTEX_LINE(node))) { - if (SYNCTEX_CUR == SYNCTEX_END) { - size += 16; - SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *)); - SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START; - SYNCTEX_START = SYNCTEX_END; - SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *); - } - *(synctex_node_t *)SYNCTEX_CUR = node; - SYNCTEX_CUR += sizeof(synctex_node_t); - } - } while ((node = SYNCTEX_FRIEND(node))); - if (SYNCTEX_START == NULL) { - /* We did not find any matching boundary, retry with glue or kern */ - node = (scanner->lists_of_friends)[friend_index];/* no need to test it again, already done */ - do { - if ((synctex_node_type(node)>=synctex_node_type_kern) - && (tag == SYNCTEX_TAG(node)) - && (line == SYNCTEX_LINE(node))) { - if (SYNCTEX_CUR == SYNCTEX_END) { - size += 16; - SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *)); - SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START; - SYNCTEX_START = SYNCTEX_END; - SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *); - } - *(synctex_node_t *)SYNCTEX_CUR = node; - SYNCTEX_CUR += sizeof(synctex_node_t); - } - } while ((node = SYNCTEX_FRIEND(node))); - if (SYNCTEX_START == NULL) { - /* We did not find any matching glue or kern, retry with boxes */ - node = (scanner->lists_of_friends)[friend_index];/* no need to test it again, already done */ - do { - if ((tag == SYNCTEX_TAG(node)) - && (line == SYNCTEX_LINE(node))) { - if (SYNCTEX_CUR == SYNCTEX_END) { - size += 16; - SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *)); - SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START; - SYNCTEX_START = SYNCTEX_END; - SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *); - } - *(synctex_node_t *)SYNCTEX_CUR = node; - SYNCTEX_CUR += sizeof(synctex_node_t); - } - } while((node = SYNCTEX_FRIEND(node))); - } - } - SYNCTEX_END = SYNCTEX_CUR; - /* Now reverse the order to have nodes in display order, and then keep just a few nodes. - * Order first the best node. */ - if ((SYNCTEX_START) && (SYNCTEX_END)) { - unsigned int best_match = -1; - unsigned int next_match = -1; - unsigned int best_weight = 0; - synctex_node_t * best_ref = NULL; - synctex_node_t * start_ref = (synctex_node_t *)SYNCTEX_START; - synctex_node_t * end_ref = (synctex_node_t *)SYNCTEX_END; - --end_ref; - while (start_ref < end_ref) { - node = *start_ref; - *start_ref = *end_ref; - *end_ref = node; - ++start_ref; - --end_ref; - } - /* Now reorder the nodes to put first the one which fits best. - * The idea is to walk along the list of nodes and pick up the first one - * which line info is exactly the mean line of its parent, or at least very close. - * Then we choose among all such node the one with the maximum number of child nodes. - * Then we switch with the first node. - */ - best_ref = start_ref = (synctex_node_t *)SYNCTEX_START; - node = *start_ref; - best_match = abs(SYNCTEX_LINE(node)-SYNCTEX_MEAN_LINE(SYNCTEX_PARENT(node))); - end_ref = (synctex_node_t *)SYNCTEX_END; - while (++start_refbest_weight)) { - best_match = next_match; - best_ref = start_ref; - best_weight = SYNCTEX_NODE_WEIGHT(parent); - } - } - node = *best_ref; - *best_ref = *(synctex_node_t *)SYNCTEX_START; - *(synctex_node_t *)SYNCTEX_START = node; - /* Basically, we keep the first node for each parent. - * More precisely, we keep only nodes that are not children of - * their predecessor's parent. */ - start_ref = (synctex_node_t *)SYNCTEX_START; - end_ref = (synctex_node_t *)SYNCTEX_START; -next_end: - end_ref += 1; /* we allways have start_ref<= end_ref*/ - if (end_ref < (synctex_node_t *)SYNCTEX_END) { - node = *end_ref; - while ((node = SYNCTEX_PARENT(node))) { - if (SYNCTEX_PARENT(*start_ref) == node) { - goto next_end; - } - } - start_ref += 1; - *start_ref = *end_ref; - goto next_end; - } - start_ref += 1; - SYNCTEX_END = (char *)start_ref; - SYNCTEX_CUR = NULL;// added on behalf of Jose Alliste - return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);// added on behalf Jan Sundermeyer - } - SYNCTEX_CUR = NULL; - // return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); removed on behalf Jan Sundermeyer - } -# if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__) - break; -# else - ++line; -# endif - } - return 0; -} - -synctex_node_t synctex_next_result(synctex_scanner_t scanner) { - if (NULL == SYNCTEX_CUR) { - SYNCTEX_CUR = SYNCTEX_START; - } else { - SYNCTEX_CUR+=sizeof(synctex_node_t); - } - if (SYNCTEX_CUR= scanner->unit) {/* scanner->unit must be >0 */ - return 0; - } - /* Convert the given point to scanner integer coordinates */ - hitPoint.h = (h-scanner->x_offset)/scanner->unit; - hitPoint.v = (v-scanner->y_offset)/scanner->unit; - /* We will store in the scanner's buffer the result of the query. */ - free(SYNCTEX_START); - SYNCTEX_START = SYNCTEX_END = SYNCTEX_CUR = NULL; - /* Find the proper sheet */ - sheet = scanner->sheet; - while((sheet) && SYNCTEX_PAGE(sheet) != page) { - sheet = SYNCTEX_SIBLING(sheet); - } - if (NULL == sheet) { - return -1; - } - /* Now sheet points to the sheet node with proper page number */ - /* Here is how we work: - * At first we do not consider the visible box dimensions. This will cover the most frequent cases. - * Then we try with the visible box dimensions. - * We try to find a non void box containing the hit point. - * We browse all the horizontal boxes until we find one containing the hit point. */ - if ((node = SYNCTEX_NEXT_hbox(sheet))) { - do { - if (_synctex_point_in_box(hitPoint,node,synctex_YES)) { - /* Maybe the hitPoint belongs to a contained vertical box. */ -end: - /* This trick is for catching overlapping boxes */ - if ((other_node = SYNCTEX_NEXT_hbox(node))) { - do { - if (_synctex_point_in_box(hitPoint,other_node,synctex_YES)) { - node = _synctex_smallest_container(other_node,node); - } - } while((other_node = SYNCTEX_NEXT_hbox(other_node))); - } - /* node is the smallest horizontal box that contains hitPoint. */ - if ((bestContainer = _synctex_eq_deepest_container(hitPoint,node,synctex_YES))) { - node = bestContainer; - } - _synctex_eq_get_closest_children_in_box(hitPoint,node,&bestNodes,&bestDistances,synctex_YES); - if (bestNodes.right && bestNodes.left) { - if ((SYNCTEX_TAG(bestNodes.right)!=SYNCTEX_TAG(bestNodes.left)) - || (SYNCTEX_LINE(bestNodes.right)!=SYNCTEX_LINE(bestNodes.left)) - || (SYNCTEX_COLUMN(bestNodes.right)!=SYNCTEX_COLUMN(bestNodes.left))) { - if ((SYNCTEX_START = malloc(2*sizeof(synctex_node_t)))) { - if (bestDistances.left>bestDistances.right) { - ((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.right; - ((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.left; - } else { - ((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.left; - ((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.right; - } - SYNCTEX_END = SYNCTEX_START + 2*sizeof(synctex_node_t); - SYNCTEX_CUR = NULL; - return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); - } - return SYNCTEX_STATUS_ERROR; - } - /* both nodes have the same input coordinates - * We choose the one closest to the hit point */ - if (bestDistances.left>bestDistances.right) { - bestNodes.left = bestNodes.right; - } - bestNodes.right = NULL; - } else if (bestNodes.right) { - bestNodes.left = bestNodes.right; - } else if (!bestNodes.left){ - bestNodes.left = node; - } - if ((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) { - * (synctex_node_t *)SYNCTEX_START = bestNodes.left; - SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t); - SYNCTEX_CUR = NULL; - return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); - } - return SYNCTEX_STATUS_ERROR; - } - } while ((node = SYNCTEX_NEXT_hbox(node))); - /* All the horizontal boxes have been tested, - * None of them contains the hit point. - */ - } - /* We are not lucky */ - if ((node = SYNCTEX_CHILD(sheet))) { - goto end; - } - return 0; -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Utilities -# endif - -int _synctex_bail(void) { - _synctex_error("SyncTeX ERROR\n"); - return -1; -} -/* Rougly speaking, this is: - * node's h coordinate - hitPoint's h coordinate. - * If node is to the right of the hit point, then this distance is positive, - * if node is to the left of the hit point, this distance is negative.*/ -int _synctex_point_h_distance(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible); -int _synctex_point_h_distance(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) { - if (node) { - int min,med,max; - switch(node->class->type) { - /* The distance between a point and a box is special. - * It is not the euclidian distance, nor something similar. - * We have to take into account the particular layout, - * and the box hierarchy. - * Given a box, there are 9 regions delimited by the lines of the edges of the box. - * The origin being at the top left corner of the page, - * we also give names to the vertices of the box. - * - * 1 | 2 | 3 - * ---A---B---> - * 4 | 5 | 6 - * ---C---D---> - * 7 | 8 | 9 - * v v - */ - case synctex_node_type_hbox: - /* getting the box bounds, taking into account negative width, height and depth. */ - min = visible?SYNCTEX_HORIZ_V(node):SYNCTEX_HORIZ(node); - max = min + (visible?SYNCTEX_ABS_WIDTH_V(node):SYNCTEX_ABS_WIDTH(node)); - /* We allways have min <= max */ - if (hitPoint.h 0 */ - } else if (hitPoint.h>max) { - return max - hitPoint.h; /* regions 3+6+9, result is < 0 */ - } else { - return 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ - } - break; - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - /* getting the box bounds, taking into account negative width, height and depth. - * For these boxes, no visible dimension available */ - min = SYNCTEX_HORIZ(node); - max = min + SYNCTEX_ABS_WIDTH(node); - /* We allways have min <= max */ - if (hitPoint.h 0 */ - } else if (hitPoint.h>max) { - return max - hitPoint.h; /* regions 3+6+9, result is < 0 */ - } else { - return 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ - } - break; - case synctex_node_type_kern: - /* IMPORTANT NOTICE: the location of the kern is recorded AFTER the move. - * The distance to the kern is very special, - * in general, there is no text material in the kern, - * this is why we compute the offset relative to the closest edge of the kern.*/ - max = SYNCTEX_WIDTH(node); - if (max<0) { - min = SYNCTEX_HORIZ(node); - max = min - max; - } else { - min = -max; - max = SYNCTEX_HORIZ(node); - min += max; - } - med = (min+max)/2; - /* positive kern: '.' means text, '>' means kern offset - * ............. - * min>>>>med>>>>max - * ............... - * negative kern: '.' means text, '<' means kern offset - * ............................ - * min<<<max) { - return max - hitPoint.h - 1; /* same kind of penalty */ - } else if (hitPoint.h>med) { - /* do things like if the node had 0 width and was placed at the max edge + 1*/ - return max - hitPoint.h + 1; /* positive, the kern is to the right of the hitPoint */ - } else { - return min - hitPoint.h - 1; /* negative, the kern is to the left of the hitPoint */ - } - case synctex_node_type_glue: - case synctex_node_type_math: - return SYNCTEX_HORIZ(node) - hitPoint.h; - } - } - return INT_MAX;/* We always assume that the node is faraway to the right*/ -} -/* Rougly speaking, this is: - * node's v coordinate - hitPoint's v coordinate. - * If node is at the top of the hit point, then this distance is positive, - * if node is at the bottom of the hit point, this distance is negative.*/ -int _synctex_point_v_distance(synctex_point_t hitPoint, synctex_node_t node,synctex_bool_t visible); -int _synctex_point_v_distance(synctex_point_t hitPoint, synctex_node_t node,synctex_bool_t visible) { -# ifdef __DARWIN_UNIX03 -# pragma unused(visible) -# endif - if (node) { - int min,max; - switch(node->class->type) { - /* The distance between a point and a box is special. - * It is not the euclidian distance, nor something similar. - * We have to take into account the particular layout, - * and the box hierarchy. - * Given a box, there are 9 regions delimited by the lines of the edges of the box. - * The origin being at the top left corner of the page, - * we also give names to the vertices of the box. - * - * 1 | 2 | 3 - * ---A---B---> - * 4 | 5 | 6 - * ---C---D---> - * 7 | 8 | 9 - * v v - */ - case synctex_node_type_hbox: - /* getting the box bounds, taking into account negative width, height and depth. */ - min = SYNCTEX_VERT_V(node); - max = min + SYNCTEX_ABS_DEPTH_V(node); - min -= SYNCTEX_ABS_HEIGHT_V(node); - /* We allways have min <= max */ - if (hitPoint.v 0 */ - } else if (hitPoint.v>max) { - return max - hitPoint.v; /* regions 7+8+9, result is < 0 */ - } else { - return 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ - } - break; - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_void_hbox: - /* getting the box bounds, taking into account negative width, height and depth. */ - min = SYNCTEX_VERT(node); - max = min + SYNCTEX_ABS_DEPTH(node); - min -= SYNCTEX_ABS_HEIGHT(node); - /* We allways have min <= max */ - if (hitPoint.v 0 */ - } else if (hitPoint.v>max) { - return max - hitPoint.v; /* regions 7+8+9, result is < 0 */ - } else { - return 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ - } - break; - case synctex_node_type_kern: - case synctex_node_type_glue: - case synctex_node_type_math: - return SYNCTEX_VERT(node) - hitPoint.v; - } - } - return INT_MAX;/* We always assume that the node is faraway to the top*/ -} - -SYNCTEX_INLINE static synctex_node_t _synctex_smallest_container(synctex_node_t node, synctex_node_t other_node) { - float height, other_height; - if (SYNCTEX_ABS_WIDTH(node)SYNCTEX_ABS_WIDTH(other_node)) { - return other_node; - } - height = SYNCTEX_ABS_DEPTH(node) + SYNCTEX_ABS_HEIGHT(node); - other_height = SYNCTEX_ABS_DEPTH(other_node) + SYNCTEX_ABS_HEIGHT(other_node); - if (heightother_height) { - return other_node; - } - return node; -} - -synctex_bool_t _synctex_point_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) { - if (node) { - if (0 == _synctex_point_h_distance(hitPoint,node,visible) - && 0 == _synctex_point_v_distance(hitPoint,node,visible)) { - return synctex_YES; - } - } - return synctex_NO; -} - -int _synctex_node_distance_to_point(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) { -# ifdef __DARWIN_UNIX03 -# pragma unused(visible) -# endif - int result = INT_MAX; /* when the distance is meaning less (sheet, input...) */ - if (node) { - int minH,maxH,minV,maxV; - switch(node->class->type) { - /* The distance between a point and a box is special. - * It is not the euclidian distance, nor something similar. - * We have to take into account the particular layout, - * and the box hierarchy. - * Given a box, there are 9 regions delimited by the lines of the edges of the box. - * The origin being at the top left corner of the page, - * we also give names to the vertices of the box. - * - * 1 | 2 | 3 - * ---A---B---> - * 4 | 5 | 6 - * ---C---D---> - * 7 | 8 | 9 - * v v - * In each region, there is a different formula. - * In the end we have a continuous distance which may not be a mathematical distance but who cares. */ - case synctex_node_type_vbox: - case synctex_node_type_void_vbox: - case synctex_node_type_hbox: - case synctex_node_type_void_hbox: - /* getting the box bounds, taking into account negative widths. */ - minH = SYNCTEX_HORIZ(node); - maxH = minH + SYNCTEX_ABS_WIDTH(node); - minV = SYNCTEX_VERT(node); - maxV = minV + SYNCTEX_ABS_DEPTH(node); - minV -= SYNCTEX_ABS_HEIGHT(node); - /* In what region is the point hitPoint=(H,V) ? */ - if (hitPoint.vminV) { - result = hitPoint.v - minV + minH - hitPoint.h; - } else { - result = minV - hitPoint.v + minH - hitPoint.h; - } - } else if (hitPoint.h>maxH) { - if (hitPoint.v>minV) { - result = hitPoint.v - minV + hitPoint.h - maxH; - } else { - result = minV - hitPoint.v + hitPoint.h - maxH; - } - } else if (hitPoint.v>minV) { - result = hitPoint.v - minV; - } else { - result = minV - hitPoint.v; - } - break; - case synctex_node_type_glue: - case synctex_node_type_math: - minH = SYNCTEX_HORIZ(node); - minV = SYNCTEX_VERT(node); - if (hitPoint.hminV) { - result = hitPoint.v - minV + minH - hitPoint.h; - } else { - result = minV - hitPoint.v + minH - hitPoint.h; - } - } else if (hitPoint.v>minV) { - result = hitPoint.v - minV + hitPoint.h - minH; - } else { - result = minV - hitPoint.v + hitPoint.h - minH; - } - break; - } - } - return result; -} - -static synctex_node_t _synctex_eq_deepest_container(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) { - if (node) { - synctex_node_t result = NULL; - synctex_node_t child = NULL; - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_hbox: - /* test the deep nodes first */ - if ((child = SYNCTEX_CHILD(node))) { - do { - if ((result = _synctex_eq_deepest_container(hitPoint,child,visible))) { - return result; - } - } while((child = SYNCTEX_SIBLING(child))); - } - /* is the hit point inside the box? */ - if (_synctex_point_in_box(hitPoint,node,visible)) { - /* for vboxes we try to use some node inside. - * Walk through the list of siblings until we find the closest one. - * Only consider siblings with children. */ - if ((node->class->type == synctex_node_type_vbox) && (child = SYNCTEX_CHILD(node))) { - int bestDistance = INT_MAX; - do { - if (SYNCTEX_CHILD(child)) { - int distance = _synctex_node_distance_to_point(hitPoint,child,visible); - if (distance < bestDistance) { - bestDistance = distance; - node = child; - } - } - } while((child = SYNCTEX_SIBLING(child))); - } - return node; - } - } - } - return NULL; -} - -/* Compares the locations of the hitPoint with the locations of the various nodes contained in the box. - * As it is an horizontal box, we only compare horizontal coordinates. */ -SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_hbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef, synctex_bool_t visible); -SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_hbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef, synctex_bool_t visible) { - int result = 0; - if ((node = SYNCTEX_CHILD(node))) { - do { - int off7 = _synctex_point_h_distance(hitPoint,node,visible); - if (off7 > 0) { - /* node is to the right of the hit point. - * We compare node and the previously recorded one, through the recorded distance. - * If the nodes have the same tag, prefer the one with the smallest line number, - * if the nodes also have the same line number, prefer the one with the smallest column. */ - if (bestDistancesRef->right > off7) { - bestDistancesRef->right = off7; - bestNodesRef->right = node; - result |= SYNCTEX_MASK_RIGHT; - } else if (bestDistancesRef->right == off7 && bestNodesRef->right) { - if (SYNCTEX_TAG(bestNodesRef->right) == SYNCTEX_TAG(node) - && (SYNCTEX_LINE(bestNodesRef->right) > SYNCTEX_LINE(node) - || (SYNCTEX_LINE(bestNodesRef->right) == SYNCTEX_LINE(node) - && SYNCTEX_COLUMN(bestNodesRef->right) > SYNCTEX_COLUMN(node)))) { - bestNodesRef->right = node; - result |= SYNCTEX_MASK_RIGHT; - } - } - } else if (off7 == 0) { - /* hitPoint is inside node. */ - bestDistancesRef->left = bestDistancesRef->right = 0; - bestNodesRef->left = node; - bestNodesRef->right = NULL; - result |= SYNCTEX_MASK_LEFT; - } else { /* here off7 < 0, hitPoint is to the right of node */ - off7 = -off7; - if (bestDistancesRef->left > off7) { - bestDistancesRef->left = off7; - bestNodesRef->left = node; - result |= SYNCTEX_MASK_LEFT; - } else if (bestDistancesRef->left == off7 && bestNodesRef->left) { - if (SYNCTEX_TAG(bestNodesRef->left) == SYNCTEX_TAG(node) - && (SYNCTEX_LINE(bestNodesRef->left) > SYNCTEX_LINE(node) - || (SYNCTEX_LINE(bestNodesRef->left) == SYNCTEX_LINE(node) - && SYNCTEX_COLUMN(bestNodesRef->left) > SYNCTEX_COLUMN(node)))) { - bestNodesRef->left = node; - result |= SYNCTEX_MASK_LEFT; - } - } - } - } while((node = SYNCTEX_SIBLING(node))); - if (result & SYNCTEX_MASK_LEFT) { - /* the left node is new, try to narrow the result */ - if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->left,visible))) { - bestNodesRef->left = node; - } - if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) { - bestNodesRef->left = node; - } - } - if (result & SYNCTEX_MASK_RIGHT) { - /* the right node is new, try to narrow the result */ - if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->right,visible))) { - bestNodesRef->right = node; - } - if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) { - bestNodesRef->right = node; - } - } - } - return result; -} -SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_vbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef,synctex_bool_t visible); -SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_vbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef,synctex_bool_t visible) { - int result = 0; - if ((node = SYNCTEX_CHILD(node))) { - do { - int off7 = _synctex_point_v_distance(hitPoint,node,visible);/* this is what makes the difference with the h version above */ - if (off7 > 0) { - /* node is to the top of the hit point (below because TeX is oriented from top to bottom. - * We compare node and the previously recorded one, through the recorded distance. - * If the nodes have the same tag, prefer the one with the smallest line number, - * if the nodes also have the same line number, prefer the one with the smallest column. */ - if (bestDistancesRef->right > off7) { - bestDistancesRef->right = off7; - bestNodesRef->right = node; - result |= SYNCTEX_MASK_RIGHT; - } else if (bestDistancesRef->right == off7 && bestNodesRef->right) { - if (SYNCTEX_TAG(bestNodesRef->right) == SYNCTEX_TAG(node) - && (SYNCTEX_LINE(bestNodesRef->right) > SYNCTEX_LINE(node) - || (SYNCTEX_LINE(bestNodesRef->right) == SYNCTEX_LINE(node) - && SYNCTEX_COLUMN(bestNodesRef->right) > SYNCTEX_COLUMN(node)))) { - bestNodesRef->right = node; - result |= SYNCTEX_MASK_RIGHT; - } - } - } else if (off7 == 0) { - bestDistancesRef->left = bestDistancesRef->right = 0; - bestNodesRef->left = node; - bestNodesRef->right = NULL; - result |= SYNCTEX_MASK_LEFT; - } else { /* here off7 < 0 */ - off7 = -off7; - if (bestDistancesRef->left > off7) { - bestDistancesRef->left = off7; - bestNodesRef->left = node; - result |= SYNCTEX_MASK_LEFT; - } else if (bestDistancesRef->left == off7 && bestNodesRef->left) { - if (SYNCTEX_TAG(bestNodesRef->left) == SYNCTEX_TAG(node) - && (SYNCTEX_LINE(bestNodesRef->left) > SYNCTEX_LINE(node) - || (SYNCTEX_LINE(bestNodesRef->left) == SYNCTEX_LINE(node) - && SYNCTEX_COLUMN(bestNodesRef->left) > SYNCTEX_COLUMN(node)))) { - bestNodesRef->left = node; - result |= SYNCTEX_MASK_LEFT; - } - } - } - } while((node = SYNCTEX_SIBLING(node))); - if (result & SYNCTEX_MASK_LEFT) { - /* the left node is new, try to narrow the result */ - if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->left,visible))) { - bestNodesRef->left = node; - } - if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) { - bestNodesRef->left = node; - } - } - if (result & SYNCTEX_MASK_RIGHT) { - /* the right node is new, try to narrow the result */ - if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->right,visible))) { - bestNodesRef->right = node; - } - if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) { - bestNodesRef->right = node; - } - } - } - return result; -} -SYNCTEX_INLINE static int _synctex_eq_get_closest_children_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t* bestNodesRef,synctex_distances_t* bestDistancesRef,synctex_bool_t visible) { - if (node) { - switch(node->class->type) { - case synctex_node_type_hbox: - return __synctex_eq_get_closest_children_in_hbox(hitPoint, node, bestNodesRef, bestDistancesRef,visible); - case synctex_node_type_vbox: - return __synctex_eq_get_closest_children_in_vbox(hitPoint, node, bestNodesRef, bestDistancesRef,visible); - } - } - return 0; -} - -SYNCTEX_INLINE static synctex_node_t __synctex_eq_closest_child(synctex_point_t hitPoint, synctex_node_t node,int* distanceRef, synctex_bool_t visible); -SYNCTEX_INLINE static synctex_node_t __synctex_eq_closest_child(synctex_point_t hitPoint, synctex_node_t node,int* distanceRef, synctex_bool_t visible) { - synctex_node_t best_node = NULL; - if ((node = SYNCTEX_CHILD(node))) { - do { - int distance = _synctex_node_distance_to_point(hitPoint,node,visible); - synctex_node_t candidate = NULL; - if (distance<=*distanceRef) { - *distanceRef = distance; - best_node = node; - } - switch(node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_hbox: - if ((candidate = __synctex_eq_closest_child(hitPoint,node,distanceRef,visible))) { - best_node = candidate; - } - } - } while((node = SYNCTEX_SIBLING(node))); - } - return best_node; -} -SYNCTEX_INLINE static synctex_node_t _synctex_eq_closest_child(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) { - if (node) { - switch(node->class->type) { - case synctex_node_type_hbox: - case synctex_node_type_vbox: - { - int best_distance = INT_MAX; - synctex_node_t best_node = __synctex_eq_closest_child(hitPoint,node,&best_distance,visible); - if ((best_node)) { - synctex_node_t child = NULL; - switch(best_node->class->type) { - case synctex_node_type_vbox: - case synctex_node_type_hbox: - if ((child = SYNCTEX_CHILD(best_node))) { - best_distance = _synctex_node_distance_to_point(hitPoint,child,visible); - while((child = SYNCTEX_SIBLING(child))) { - int distance = _synctex_node_distance_to_point(hitPoint,child,visible); - if (distance<=best_distance) { - best_distance = distance; - best_node = child; - } - } - } - } - } - return best_node; - } - } - } - return NULL; -} - -# ifdef SYNCTEX_NOTHING -# pragma mark - -# pragma mark Updater -# endif - -typedef int (*synctex_fprintf_t)(void *, const char * , ...); /* print formatted to either FILE * or gzFile */ - -# define SYNCTEX_BITS_PER_BYTE 8 - -struct __synctex_updater_t { - gzFile file; /* the foo.synctex or foo.synctex.gz I/O identifier */ - synctex_fprintf_t fprintf; /* either fprintf or gzprintf */ - int length; /* the number of chars appended */ - struct _flags { - unsigned int no_gz:1; /* Whether zlib is used or not */ - unsigned int reserved:SYNCTEX_BITS_PER_BYTE*sizeof(int)-1; /* Align */ - } flags; -}; -# define SYNCTEX_FILE updater->file -# define SYNCTEX_NO_GZ ((updater->flags).no_gz) -# define SYNCTEX_fprintf (*(updater->fprintf)) - -synctex_updater_t synctex_updater_new_with_output_file(const char * output, const char * build_directory) { - synctex_updater_t updater = NULL; - char * synctex = NULL; - synctex_io_mode_t io_mode = 0; - const char * mode = NULL; - /* prepare the updater, the memory is the only one dynamically allocated */ - updater = (synctex_updater_t)_synctex_malloc(sizeof(synctex_updater_t)); - if (NULL == updater) { - _synctex_error("! synctex_updater_new_with_file: malloc problem"); - return NULL; - } - if (_synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_ADD_QUOTES,&io_mode) - && _synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_DONT_ADD_QUOTES,&io_mode)) { -return_on_error: - free(updater); - updater = NULL; - return NULL; - } - /* OK, the file exists, we close it and reopen it with the correct mode. - * The receiver is now the owner of the "synctex" variable. */ - gzclose(SYNCTEX_FILE); - SYNCTEX_FILE = NULL; - SYNCTEX_NO_GZ = (io_mode&synctex_io_gz_mask)?synctex_NO:synctex_YES; - mode = _synctex_get_io_mode_name(io_mode|synctex_io_append_mask);/* either "a" or "ab", depending on the file extension */ - if (SYNCTEX_NO_GZ) { - if (NULL == (SYNCTEX_FILE = (void *)fopen(synctex,mode))) { -no_write_error: - _synctex_error("! synctex_updater_new_with_file: Can't append to %s",synctex); - free(synctex); - goto return_on_error; - } - updater->fprintf = (synctex_fprintf_t)(&fprintf); - } else { - if (NULL == (SYNCTEX_FILE = (void *)gzopen(synctex,mode))) { - goto no_write_error; - } - updater->fprintf = (synctex_fprintf_t)(&gzprintf); - } - printf("SyncTeX: updating %s...",synctex); - free(synctex); - return updater; -} - - -void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification){ - if (NULL==updater) { - return; - } - if (magnification && strlen(magnification)) { - updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Magnification:%s\n",magnification); - } -} - -void synctex_updater_append_x_offset(synctex_updater_t updater, char * x_offset){ - if (NULL==updater) { - return; - } - if (x_offset && strlen(x_offset)) { - updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"X Offset:%s\n",x_offset); - } -} - -void synctex_updater_append_y_offset(synctex_updater_t updater, char * y_offset){ - if (NULL==updater) { - return; - } - if (y_offset && strlen(y_offset)) { - updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Y Offset:%s\n",y_offset); - } -} - -void synctex_updater_free(synctex_updater_t updater){ - if (NULL==updater) { - return; - } - if (updater->length>0) { - SYNCTEX_fprintf(SYNCTEX_FILE,"!%i\n",updater->length); - } - if (SYNCTEX_NO_GZ) { - fclose((FILE *)SYNCTEX_FILE); - } else { - gzclose((gzFile)SYNCTEX_FILE); - } - free(updater); - printf("... done.\n"); - return; -} diff --git a/zathura/synctex/synctex_parser.h b/zathura/synctex/synctex_parser.h deleted file mode 100644 index 3151707..0000000 --- a/zathura/synctex/synctex_parser.h +++ /dev/null @@ -1,360 +0,0 @@ -/* -Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr - -This file is part of the SyncTeX package. - -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 - -Version: 1.17 - -See synctex_parser_readme.txt for more details - -License: --------- -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE - -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written -authorization from the copyright holder. - -Acknowledgments: ----------------- -The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh, -and significant help from XeTeX developer Jonathan Kew - -Nota Bene: ----------- -If you include or use a significant part of the synctex package into a software, -I would appreciate to be listed as contributor and see "SyncTeX" highlighted. - -Version 1 -Thu Jun 19 09:39:21 UTC 2008 - -*/ - -#ifndef __SYNCTEX_PARSER__ -# define __SYNCTEX_PARSER__ - -#ifdef __cplusplus -extern "C" { -#endif - -/* synctex_node_t is the type for all synctex nodes. - * The synctex file is parsed into a tree of nodes, either sheet, boxes, math nodes... */ -typedef struct _synctex_node * synctex_node_t; - -/* The main synctex object is a scanner - * Its implementation is considered private. - * The basic workflow is - * - create a "synctex scanner" with the contents of a file - * - perform actions on that scanner like display or edit queries - * - free the scanner when the work is done - */ -typedef struct __synctex_scanner_t _synctex_scanner_t; -typedef _synctex_scanner_t * synctex_scanner_t; - -/* This is the designated method to create a new synctex scanner object. - * output is the pdf/dvi/xdv file associated to the synctex file. - * If necessary, it can be the tex file that originated the synctex file - * but this might cause problems if the \jobname has a custom value. - * Despite this method can accept a relative path in practice, - * you should only pass a full path name. - * The path should be encoded by the underlying file system, - * assuming that it is based on 8 bits characters, including UTF8, - * not 16 bits nor 32 bits. - * The last file extension is removed and replaced by the proper extension. - * Then the private method _synctex_scanner_new_with_contents_of_file is called. - * NULL is returned in case of an error or non existent file. - * Once you have a scanner, use the synctex_display_query and synctex_edit_query below. - * The new "build_directory" argument is available since version 1.5. - * It is the directory where all the auxiliary stuff is created. - * Sometimes, the synctex output file and the pdf, dvi or xdv files are not created in the same directory. - * This is the case in MikTeX (I will include this into TeX Live). - * This directory path can be nil, it will be ignored then. - * It can be either absolute or relative to the directory of the output pdf (dvi or xdv) file. - * If no synctex file is found in the same directory as the output file, then we try to find one in the build directory. - * Please note that this new "build_directory" is provided as a convenient argument but should not be used. - * In fact, this is implempented as a work around of a bug in MikTeX where the synctex file does not follow the pdf file. - * The new "parse" argument is available since version 1.5. In general, use 1. - * Use 0 only if you do not want to parse the content but just check the existence. - */ -synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse); - -/* This is the designated method to delete a synctex scanner object. - * Frees all the memory, you must call it when you are finished with the scanner. - */ -void synctex_scanner_free(synctex_scanner_t scanner); - -/* Send this message to force the scanner to parse the contents of the synctex output file. - * Nothing is performed if the file was already parsed. - * In each query below, this message is sent, but if you need to access information more directly, - * you must be sure that the parsing did occur. - * Usage: - * if((my_scanner = synctex_scanner_parse(my_scanner))) { - * continue with my_scanner... - * } else { - * there was a problem - * } - */ -synctex_scanner_t synctex_scanner_parse(synctex_scanner_t scanner); - -/* The main entry points. - * Given the file name, a line and a column number, synctex_display_query returns the number of nodes - * satisfying the contrain. Use code like - * - * if(synctex_display_query(scanner,name,line,column)>0) { - * synctex_node_t node; - * while((node = synctex_next_result(scanner))) { - * // do something with node - * ... - * } - * } - * - * For example, one can - * - highlight each resulting node in the output, using synctex_node_h and synctex_node_v - * - highlight all the rectangles enclosing those nodes, using synctex_box_... functions - * - highlight just the character using that information - * - * Given the page and the position in the page, synctex_edit_query returns the number of nodes - * satisfying the contrain. Use code like - * - * if(synctex_edit_query(scanner,page,h,v)>0) { - * synctex_node_t node; - * while(node = synctex_next_result(scanner)) { - * // do something with node - * ... - * } - * } - * - * For example, one can - * - highlight each resulting line in the input, - * - highlight just the character using that information - * - * page is 1 based - * h and v are coordinates in 72 dpi unit, relative to the top left corner of the page. - * If you make a new query, the result of the previous one is discarded. - * If one of this function returns a non positive integer, - * it means that an error occurred. - * - * Both methods are conservative, in the sense that matching is weak. - * If the exact column number is not found, there will be an answer with the whole line. - * - * Sumatra-PDF, Skim, iTeXMac2 and Texworks are examples of open source software that use this library. - * You can browse their code for a concrete implementation. - */ -int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column); -int synctex_edit_query(synctex_scanner_t scanner,int page,float h,float v); -synctex_node_t synctex_next_result(synctex_scanner_t scanner); - -/* Display all the information contained in the scanner object. - * If the records are too numerous, only the first ones are displayed. - * This is mainly for informatinal purpose to help developers. - */ -void synctex_scanner_display(synctex_scanner_t scanner); - -/* The x and y offset of the origin in TeX coordinates. The magnification - These are used by pdf viewers that want to display the real box size. - For example, getting the horizontal coordinates of a node would require - synctex_node_box_h(node)*synctex_scanner_magnification(scanner)+synctex_scanner_x_offset(scanner) - Getting its TeX width would simply require - synctex_node_box_width(node)*synctex_scanner_magnification(scanner) - but direct methods are available for that below. - */ -int synctex_scanner_x_offset(synctex_scanner_t scanner); -int synctex_scanner_y_offset(synctex_scanner_t scanner); -float synctex_scanner_magnification(synctex_scanner_t scanner); - -/* Managing the input file names. - * Given a tag, synctex_scanner_get_name will return the corresponding file name. - * Conversely, given a file name, synctex_scanner_get_tag will retur, the corresponding tag. - * The file name must be the very same as understood by TeX. - * For example, if you \input myDir/foo.tex, the file name is myDir/foo.tex. - * No automatic path expansion is performed. - * Finally, synctex_scanner_input is the first input node of the scanner. - * To browse all the input node, use a loop like - * - * if((input_node = synctex_scanner_input(scanner))){ - * do { - * blah - * } while((input_node=synctex_node_sibling(input_node))); - * } - * - * The output is the name that was used to create the scanner. - * The synctex is the real name of the synctex file, - * it was obtained from output by setting the proper file extension. - */ -const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag); -int synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name); -synctex_node_t synctex_scanner_input(synctex_scanner_t scanner); -const char * synctex_scanner_get_output(synctex_scanner_t scanner); -const char * synctex_scanner_get_synctex(synctex_scanner_t scanner); - -/* Browsing the nodes - * parent, child and sibling are standard names for tree nodes. - * The parent is one level higher, the child is one level deeper, - * and the sibling is at the same level. - * The sheet of a node is the first ancestor, it is of type sheet. - * A node and its sibling have the same parent. - * A node is the parent of its child. - * A node is either the child of its parent, - * or belongs to the sibling chain of its parent's child. - * The next node is either the child, the sibling or the parent's sibling, - * unless the parent is a sheet. - * This allows to navigate through all the nodes of a given sheet node: - * - * synctex_node_t node = sheet; - * while((node = synctex_node_next(node))) { - * // do something with node - * } - * - * With synctex_sheet_content, you can retrieve the sheet node given the page. - * The page is 1 based, according to TeX standards. - * Conversely synctex_node_sheet allows to retrieve the sheet containing a given node. - */ -synctex_node_t synctex_node_parent(synctex_node_t node); -synctex_node_t synctex_node_sheet(synctex_node_t node); -synctex_node_t synctex_node_child(synctex_node_t node); -synctex_node_t synctex_node_sibling(synctex_node_t node); -synctex_node_t synctex_node_next(synctex_node_t node); -synctex_node_t synctex_sheet(synctex_scanner_t scanner,int page); -synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page); - -/* These are the types of the synctex nodes */ -typedef enum { - synctex_node_type_error = 0, - synctex_node_type_input, - synctex_node_type_sheet, - synctex_node_type_vbox, - synctex_node_type_void_vbox, - synctex_node_type_hbox, - synctex_node_type_void_hbox, - synctex_node_type_kern, - synctex_node_type_glue, - synctex_node_type_math, - synctex_node_type_boundary, - synctex_node_number_of_types -} synctex_node_type_t; - -/* synctex_node_type gives the type of a given node, - * synctex_node_isa gives the same information as a human readable text. */ -synctex_node_type_t synctex_node_type(synctex_node_t node); -const char * synctex_node_isa(synctex_node_t node); - -/* This is primarily used for debugging purpose. - * The second one logs information for the node and recursively displays information for its next node */ -void synctex_node_log(synctex_node_t node); -void synctex_node_display(synctex_node_t node); - -/* Given a node, access to the location in the synctex file where it is defined. - */ -typedef unsigned int synctex_charindex_t; -synctex_charindex_t synctex_node_charindex(synctex_node_t node); - -/* Given a node, access to its tag, line and column. - * The line and column numbers are 1 based. - * The latter is not yet fully supported in TeX, the default implementation returns 0 which means the whole line. - * When the tag is known, the scanner of the node will give the corresponding file name. - * When the tag is known, the scanner of the node will give the name. - */ -int synctex_node_tag(synctex_node_t node); -int synctex_node_line(synctex_node_t node); -int synctex_node_column(synctex_node_t node); - -/* In order to enhance forward synchronization, - * non void horizontal boxes have supplemental cached information. - * The mean line is the average of the line numbers of the included nodes. - * The child count is the number of chidren. - */ -int synctex_node_mean_line(synctex_node_t node); -int synctex_node_child_count(synctex_node_t node); - -/* This is the page where the node appears. - * This is a 1 based index as given by TeX. - */ -int synctex_node_page(synctex_node_t node); - -/* For quite all nodes, horizontal, vertical coordinates, and width. - * These are expressed in TeX small points coordinates, with origin at the top left corner. - */ -int synctex_node_h(synctex_node_t node); -int synctex_node_v(synctex_node_t node); -int synctex_node_width(synctex_node_t node); - -/* For all nodes, dimensions of the enclosing box. - * These are expressed in TeX small points coordinates, with origin at the top left corner. - * A box is enclosing itself. - */ -int synctex_node_box_h(synctex_node_t node); -int synctex_node_box_v(synctex_node_t node); -int synctex_node_box_width(synctex_node_t node); -int synctex_node_box_height(synctex_node_t node); -int synctex_node_box_depth(synctex_node_t node); - -/* For quite all nodes, horizontal, vertical coordinates, and width. - * The visible dimensions are bigger than real ones to compensate 0 width boxes - * that do contain nodes. - * These are expressed in page coordinates, with origin at the top left corner. - * A box is enclosing itself. - */ -float synctex_node_visible_h(synctex_node_t node); -float synctex_node_visible_v(synctex_node_t node); -float synctex_node_visible_width(synctex_node_t node); -/* For all nodes, visible dimensions of the enclosing box. - * A box is enclosing itself. - * The visible dimensions are bigger than real ones to compensate 0 width boxes - * that do contain nodes. - */ -float synctex_node_box_visible_h(synctex_node_t node); -float synctex_node_box_visible_v(synctex_node_t node); -float synctex_node_box_visible_width(synctex_node_t node); -float synctex_node_box_visible_height(synctex_node_t node); -float synctex_node_box_visible_depth(synctex_node_t node); - -/* The main synctex updater object. - * This object is used to append information to the synctex file. - * Its implementation is considered private. - * It is used by the synctex command line tool to take into account modifications - * that could occur while postprocessing files by dvipdf like filters. - */ -typedef struct __synctex_updater_t _synctex_updater_t; -typedef _synctex_updater_t * synctex_updater_t; - -/* Designated initializer. - * Once you are done with your whole job, - * free the updater */ -synctex_updater_t synctex_updater_new_with_output_file(const char * output, const char * directory); - -/* Use the next functions to append records to the synctex file, - * no consistency tests made on the arguments */ -void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification); -void synctex_updater_append_x_offset(synctex_updater_t updater, char * x_offset); -void synctex_updater_append_y_offset(synctex_updater_t updater, char * y_offset); - -/* You MUST free the updater, once everything is properly appended */ -void synctex_updater_free(synctex_updater_t updater); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/zathura/synctex/synctex_parser_utils.c b/zathura/synctex/synctex_parser_utils.c deleted file mode 100644 index 9061a2c..0000000 --- a/zathura/synctex/synctex_parser_utils.c +++ /dev/null @@ -1,502 +0,0 @@ -/* -Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr - -This file is part of the SyncTeX package. - -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 - -Version: 1.17 - -See synctex_parser_readme.txt for more details - -License: --------- -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE - -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written -authorization from the copyright holder. - -*/ - -/* In this file, we find all the functions that may depend on the operating system. */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#if defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) -#define SYNCTEX_WINDOWS 1 -#endif - -#if defined(__OS2__) -#define SYNCTEX_OS2 1 -#endif - -#ifdef _WIN32_WINNT_WINXP -#define SYNCTEX_RECENT_WINDOWS 1 -#endif - -#ifdef SYNCTEX_WINDOWS -#include -#endif - -void *_synctex_malloc(size_t size) { - void * ptr = malloc(size); - if(ptr) { -/* There used to be a switch to use bzero because it is more secure. JL */ - memset(ptr,0, size); - } - return (void *)ptr; -} - -int _synctex_error(const char * reason,...) { - va_list arg; - int result; - va_start (arg, reason); -# ifdef SYNCTEX_RECENT_WINDOWS - {/* This code is contributed by William Blum. - As it does not work on some older computers, - the _WIN32 conditional here is replaced with a SYNCTEX_RECENT_WINDOWS one. - According to http://msdn.microsoft.com/en-us/library/aa363362(VS.85).aspx - Minimum supported client Windows 2000 Professional - Minimum supported server Windows 2000 Server - People running Windows 2K standard edition will not have OutputDebugStringA. - JL.*/ - char *buff; - size_t len; - OutputDebugStringA("SyncTeX ERROR: "); - len = _vscprintf(reason, arg) + 1; - buff = (char*)malloc( len * sizeof(char) ); - result = vsprintf(buff, reason, arg) +strlen("SyncTeX ERROR: "); - OutputDebugStringA(buff); - OutputDebugStringA("\n"); - free(buff); - } -# else - result = fprintf(stderr,"SyncTeX ERROR: "); - result += vfprintf(stderr, reason, arg); - result += fprintf(stderr,"\n"); -# endif - va_end (arg); - return result; -} - -/* strip the last extension of the given string, this string is modified! */ -void _synctex_strip_last_path_extension(char * string) { - if(NULL != string){ - char * last_component = NULL; - char * last_extension = NULL; - char * next = NULL; - /* first we find the last path component */ - if(NULL == (last_component = strstr(string,"/"))){ - last_component = string; - } else { - ++last_component; - while((next = strstr(last_component,"/"))){ - last_component = next+1; - } - } -# if defined(SYNCTEX_WINDOWS) || defined(SYNCTEX_OS2) - /* On Windows, the '\' is also a path separator. */ - while((next = strstr(last_component,"\\"))){ - last_component = next+1; - } -# endif - /* then we find the last path extension */ - if((last_extension = strstr(last_component,"."))){ - ++last_extension; - while((next = strstr(last_extension,"."))){ - last_extension = next+1; - } - --last_extension;/* back to the "." */ - if(last_extension>last_component){/* filter out paths like ....my/dir/.hidden"*/ - last_extension[0] = '\0'; - } - } - } -} - -synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name_ref) -{ - if (SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])) { - do { - (*name_ref) += 2; - while (SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])) { - ++(*name_ref); - } - } while(SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])); - return synctex_YES; - } - return synctex_NO; -} - -/* The base name is necessary to deal with the 2011 file naming convention... - * path is a '\0' terminated string - * The return value is the trailing part of the argument, - * just following the first occurrence of the regexp pattern "[^|/|\].[\|/]+".*/ -const char * _synctex_base_name(const char *path) { - const char * ptr = path; - do { - if (synctex_ignore_leading_dot_slash_in_path(&ptr)) { - return ptr; - } - do { - if (!*(++ptr)) { - return path; - } - } while (!SYNCTEX_IS_PATH_SEPARATOR(*ptr)); - } while (*(++ptr)); - return path; -} - -/* Compare two file names, windows is sometimes case insensitive... */ -synctex_bool_t _synctex_is_equivalent_file_name(const char *lhs, const char *rhs) { - /* Remove the leading regex '(\./+)*' in both rhs and lhs */ - synctex_ignore_leading_dot_slash_in_path(&lhs); - synctex_ignore_leading_dot_slash_in_path(&rhs); -next_character: - if (SYNCTEX_IS_PATH_SEPARATOR(*lhs)) {/* lhs points to a path separator */ - if (!SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* but not rhs */ - return synctex_NO; - } - ++lhs; - ++rhs; - synctex_ignore_leading_dot_slash_in_path(&lhs); - synctex_ignore_leading_dot_slash_in_path(&rhs); - goto next_character; - } else if (SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* rhs points to a path separator but not lhs */ - return synctex_NO; - } else if (SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(*lhs,*rhs)){/* uppercase do not match */ - return synctex_NO; - } else if (!*lhs) {/* lhs is at the end of the string */ - return *rhs ? synctex_NO : synctex_YES; - } else if(!*rhs) {/* rhs is at the end of the string but not lhs */ - return synctex_NO; - } - ++lhs; - ++rhs; - goto next_character; -} - -synctex_bool_t _synctex_path_is_absolute(const char * name) { - if(!strlen(name)) { - return synctex_NO; - } -# if defined(SYNCTEX_WINDOWS) || defined(SYNCTEX_OS2) - if(strlen(name)>2) { - return (name[1]==':' && SYNCTEX_IS_PATH_SEPARATOR(name[2]))?synctex_YES:synctex_NO; - } - return synctex_NO; -# else - return SYNCTEX_IS_PATH_SEPARATOR(name[0])?synctex_YES:synctex_NO; -# endif -} - -/* We do not take care of UTF-8 */ -const char * _synctex_last_path_component(const char * name) { - const char * c = name+strlen(name); - if(c>name) { - if(!SYNCTEX_IS_PATH_SEPARATOR(*c)) { - do { - --c; - if(SYNCTEX_IS_PATH_SEPARATOR(*c)) { - return c+1; - } - } while(c>name); - } - return c;/* the last path component is the void string*/ - } - return c; -} - -int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size) { - const char * lpc; - if(src && dest_ref) { -# define dest (*dest_ref) - dest = NULL; /* Default behavior: no change and sucess. */ - lpc = _synctex_last_path_component(src); - if(strlen(lpc)) { - if(strchr(lpc,' ') && lpc[0]!='"' && lpc[strlen(lpc)-1]!='"') { - /* We are in the situation where adding the quotes is allowed. */ - /* Time to add the quotes. */ - /* Consistency test: we must have dest+size>dest+strlen(dest)+2 - * or equivalently: strlen(dest)+20) { - char * result = NULL; - ++size; - /* Create the memory storage */ - if(NULL!=(result = (char *)malloc(size))) { - char * dest = result; - va_start (arg, first); - temp = first; - do { - if((size = strlen(temp))>0) { - /* There is something to merge */ - if(dest != strncpy(dest,temp,size)) { - _synctex_error("! _synctex_merge_strings: Copy problem"); - free(result); - result = NULL; - return NULL; - } - dest += size; - } - } while( (temp = va_arg(arg, const char *)) != NULL); - va_end(arg); - dest[0]='\0';/* Terminate the merged string */ - return result; - } - _synctex_error("! _synctex_merge_strings: Memory problem"); - return NULL; - } - return NULL; -} - -/* The purpose of _synctex_get_name is to find the name of the synctex file. - * There is a list of possible filenames from which we return the most recent one and try to remove all the others. - * With two runs of pdftex or xetex we are sure the the synctex file is really the most appropriate. - */ -int _synctex_get_name(const char * output, const char * build_directory, char ** synctex_name_ref, synctex_io_mode_t * io_mode_ref) -{ - if(output && synctex_name_ref && io_mode_ref) { - /* If output is already absolute, we just have to manage the quotes and the compress mode */ - size_t size = 0; - char * synctex_name = NULL; - synctex_io_mode_t io_mode = *io_mode_ref; - const char * base_name = _synctex_last_path_component(output); /* do not free, output is the owner. base name of output*/ - /* Do we have a real base name ? */ - if(strlen(base_name)>0) { - /* Yes, we do. */ - const char * temp = NULL; - char * core_name = NULL; /* base name of output without path extension. */ - char * dir_name = NULL; /* dir name of output */ - char * quoted_core_name = NULL; - char * basic_name = NULL; - char * gz_name = NULL; - char * quoted_name = NULL; - char * quoted_gz_name = NULL; - char * build_name = NULL; - char * build_gz_name = NULL; - char * build_quoted_name = NULL; - char * build_quoted_gz_name = NULL; - struct stat buf; - time_t the_time = 0; - /* Create core_name: let temp point to the dot before the path extension of base_name; - * We start form the \0 terminating character and scan the string upward until we find a dot. - * The leading dot is not accepted. */ - if((temp = strrchr(base_name,'.')) && (size = temp - base_name)>0) { - /* There is a dot and it is not at the leading position */ - if(NULL == (core_name = (char *)malloc(size+1))) { - _synctex_error("! _synctex_get_name: Memory problem 1"); - return -1; - } - if(core_name != strncpy(core_name,base_name,size)) { - _synctex_error("! _synctex_get_name: Copy problem 1"); - free(core_name); - dir_name = NULL; - return -2; - } - core_name[size] = '\0'; - } else { - /* There is no path extension, - * Just make a copy of base_name */ - core_name = _synctex_merge_strings(base_name); - } - /* core_name is properly set up, owned by "self". */ - /* creating dir_name. */ - size = strlen(output)-strlen(base_name); - if(size>0) { - /* output contains more than one path component */ - if(NULL == (dir_name = (char *)malloc(size+1))) { - _synctex_error("! _synctex_get_name: Memory problem"); - free(core_name); - dir_name = NULL; - return -1; - } - if(dir_name != strncpy(dir_name,output,size)) { - _synctex_error("! _synctex_get_name: Copy problem"); - free(dir_name); - dir_name = NULL; - free(core_name); - dir_name = NULL; - return -2; - } - dir_name[size] = '\0'; - } - /* dir_name is properly set up. It ends with a path separator, if non void. */ - /* creating quoted_core_name. */ - if(strchr(core_name,' ')) { - quoted_core_name = _synctex_merge_strings("\"",core_name,"\""); - } - /* quoted_core_name is properly set up. */ - if(dir_name &&strlen(dir_name)>0) { - basic_name = _synctex_merge_strings(dir_name,core_name,synctex_suffix,NULL); - if(quoted_core_name && strlen(quoted_core_name)>0) { - quoted_name = _synctex_merge_strings(dir_name,quoted_core_name,synctex_suffix,NULL); - } - } else { - basic_name = _synctex_merge_strings(core_name,synctex_suffix,NULL); - if(quoted_core_name && strlen(quoted_core_name)>0) { - quoted_name = _synctex_merge_strings(quoted_core_name,synctex_suffix,NULL); - } - } - if(!_synctex_path_is_absolute(output) && build_directory && (size = strlen(build_directory))) { - temp = build_directory + size - 1; - if(_synctex_path_is_absolute(temp)) { - build_name = _synctex_merge_strings(build_directory,basic_name,NULL); - if(quoted_core_name && strlen(quoted_core_name)>0) { - build_quoted_name = _synctex_merge_strings(build_directory,quoted_name,NULL); - } - } else { - build_name = _synctex_merge_strings(build_directory,"/",basic_name,NULL); - if(quoted_core_name && strlen(quoted_core_name)>0) { - build_quoted_name = _synctex_merge_strings(build_directory,"/",quoted_name,NULL); - } - } - } - if(basic_name) { - gz_name = _synctex_merge_strings(basic_name,synctex_suffix_gz,NULL); - } - if(quoted_name) { - quoted_gz_name = _synctex_merge_strings(quoted_name,synctex_suffix_gz,NULL); - } - if(build_name) { - build_gz_name = _synctex_merge_strings(build_name,synctex_suffix_gz,NULL); - } - if(build_quoted_name) { - build_quoted_gz_name = _synctex_merge_strings(build_quoted_name,synctex_suffix_gz,NULL); - } - /* All the others names are properly set up... */ - /* retain the most recently modified file */ -# define TEST(FILENAME,COMPRESS_MODE) \ - if(FILENAME) {\ - if (stat(FILENAME, &buf)) { \ - free(FILENAME);\ - FILENAME = NULL;\ - } else if (buf.st_mtime>the_time) { \ - the_time=buf.st_mtime; \ - synctex_name = FILENAME; \ - if (COMPRESS_MODE) { \ - io_mode |= synctex_io_gz_mask; \ - } else { \ - io_mode &= ~synctex_io_gz_mask; \ - } \ - } \ - } - TEST(basic_name,synctex_DONT_COMPRESS); - TEST(gz_name,synctex_COMPRESS); - TEST(quoted_name,synctex_DONT_COMPRESS); - TEST(quoted_gz_name,synctex_COMPRESS); - TEST(build_name,synctex_DONT_COMPRESS); - TEST(build_gz_name,synctex_COMPRESS); - TEST(build_quoted_name,synctex_DONT_COMPRESS); - TEST(build_quoted_gz_name,synctex_COMPRESS); -# undef TEST - /* Free all the intermediate filenames, except the one that will be used as returned value. */ -# define CLEAN_AND_REMOVE(FILENAME) \ - if(FILENAME && (FILENAME!=synctex_name)) {\ - remove(FILENAME);\ - printf("synctex tool info: %s removed\n",FILENAME);\ - free(FILENAME);\ - FILENAME = NULL;\ - } - CLEAN_AND_REMOVE(basic_name); - CLEAN_AND_REMOVE(gz_name); - CLEAN_AND_REMOVE(quoted_name); - CLEAN_AND_REMOVE(quoted_gz_name); - CLEAN_AND_REMOVE(build_name); - CLEAN_AND_REMOVE(build_gz_name); - CLEAN_AND_REMOVE(build_quoted_name); - CLEAN_AND_REMOVE(build_quoted_gz_name); -# undef CLEAN_AND_REMOVE - /* set up the returned values */ - * synctex_name_ref = synctex_name; - * io_mode_ref = io_mode; - return 0; - } - return -1;/* bad argument */ - } - return -2; -} - -const char * _synctex_get_io_mode_name(synctex_io_mode_t io_mode) { - static const char * synctex_io_modes[4] = {"r","rb","a","ab"}; - unsigned index = ((io_mode & synctex_io_gz_mask)?1:0) + ((io_mode & synctex_io_append_mask)?2:0);// bug pointed out by Jose Alliste - return synctex_io_modes[index]; -} diff --git a/zathura/synctex/synctex_parser_utils.h b/zathura/synctex/synctex_parser_utils.h deleted file mode 100644 index db19b2d..0000000 --- a/zathura/synctex/synctex_parser_utils.h +++ /dev/null @@ -1,152 +0,0 @@ -/* -Copyright (c) 2008, 2009, 2010, 2011 jerome DOT laurens AT u-bourgogne DOT fr - -This file is part of the SyncTeX package. - -Latest Revision: Tue Jun 14 08:23:30 UTC 2011 - -Version: 1.17 - -See synctex_parser_readme.txt for more details - -License: --------- -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without -restriction, including without limitation the rights to use, -copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE - -Except as contained in this notice, the name of the copyright holder -shall not be used in advertising or otherwise to promote the sale, -use or other dealings in this Software without prior written -authorization from the copyright holder. - -*/ - -/* The utilities declared here are subject to conditional implementation. - * All the operating system special stuff goes here. - * The problem mainly comes from file name management: path separator, encoding... - */ - -# define synctex_bool_t int -# define synctex_YES -1 -# define synctex_ADD_QUOTES -1 -# define synctex_COMPRESS -1 -# define synctex_NO 0 -# define synctex_DONT_ADD_QUOTES 0 -# define synctex_DONT_COMPRESS 0 - -#ifndef __SYNCTEX_PARSER_UTILS__ -# define __SYNCTEX_PARSER_UTILS__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -# if defined(_WIN32) || defined(__OS2__) -# define SYNCTEX_CASE_SENSITIVE_PATH 0 -# define SYNCTEX_IS_PATH_SEPARATOR(c) ('/' == c || '\\' == c) -# else -# define SYNCTEX_CASE_SENSITIVE_PATH 1 -# define SYNCTEX_IS_PATH_SEPARATOR(c) ('/' == c) -# endif - -# if defined(_WIN32) || defined(__OS2__) -# define SYNCTEX_IS_DOT(c) ('.' == c) -# else -# define SYNCTEX_IS_DOT(c) ('.' == c) -# endif - -# if SYNCTEX_CASE_SENSITIVE_PATH -# define SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(left,right) (left != right) -# else -# define SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(left,right) (toupper(left) != toupper(right)) -# endif - -/* This custom malloc functions initializes to 0 the newly allocated memory. - * There is no bzero function on windows. */ -void *_synctex_malloc(size_t size); - -/* This is used to log some informational message to the standard error stream. - * On Windows, the stderr stream is not exposed and another method is used. - * The return value is the number of characters printed. */ -int _synctex_error(const char * reason,...); - -/* strip the last extension of the given string, this string is modified! - * This function depends on the OS because the path separator may differ. - * This should be discussed more precisely. */ -void _synctex_strip_last_path_extension(char * string); - -/* Compare two file names, windows is sometimes case insensitive... - * The given strings may differ stricto sensu, but represent the same file name. - * It might not be the real way of doing things. - * The return value is an undefined non 0 value when the two file names are equivalent. - * It is 0 otherwise. */ -synctex_bool_t _synctex_is_equivalent_file_name(const char *lhs, const char *rhs); - -/* Description forthcoming.*/ -synctex_bool_t _synctex_path_is_absolute(const char * name); - -/* Description forthcoming...*/ -const char * _synctex_last_path_component(const char * name); - -/* Description forthcoming...*/ -const char * _synctex_base_name(const char *path); - -/* If the core of the last path component of src is not already enclosed with double quotes ('"') - * and contains a space character (' '), then a new buffer is created, the src is copied and quotes are added. - * In all other cases, no destination buffer is created and the src is not copied. - * 0 on success, which means no error, something non 0 means error, mainly due to memory allocation failure, or bad parameter. - * This is used to fix a bug in the first version of pdftex with synctex (1.40.9) for which names with spaces - * were not managed in a standard way. - * On success, the caller owns the buffer pointed to by dest_ref (is any) and - * is responsible of freeing the memory when done. - * The size argument is the size of the src buffer. On return the dest_ref points to a buffer sized size+2.*/ -int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size); - -/* These are the possible extensions of the synctex file */ -extern const char * synctex_suffix; -extern const char * synctex_suffix_gz; - -typedef unsigned int synctex_io_mode_t; - -typedef enum { - synctex_io_append_mask = 1, - synctex_io_gz_mask = synctex_io_append_mask<<1 -} synctex_io_mode_masks_t; - -typedef enum { - synctex_compress_mode_none = 0, - synctex_compress_mode_gz = 1 -} synctex_compress_mode_t; - -int _synctex_get_name(const char * output, const char * build_directory, char ** synctex_name_ref, synctex_io_mode_t * io_mode_ref); - -/* returns the correct mode required by fopen and gzopen from the given io_mode */ -const char * _synctex_get_io_mode_name(synctex_io_mode_t io_mode); - -synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/zathura/synctex/synctex_parser_version.txt b/zathura/synctex/synctex_parser_version.txt deleted file mode 100644 index 68209c0..0000000 --- a/zathura/synctex/synctex_parser_version.txt +++ /dev/null @@ -1 +0,0 @@ -1.17 \ No newline at end of file