summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/synctexdir/synctex_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/synctexdir/synctex_parser.c')
-rw-r--r--Build/source/texk/web2c/synctexdir/synctex_parser.c2950
1 files changed, 1713 insertions, 1237 deletions
diff --git a/Build/source/texk/web2c/synctexdir/synctex_parser.c b/Build/source/texk/web2c/synctexdir/synctex_parser.c
index 1e99f2cf1ec..327ca37abef 100644
--- a/Build/source/texk/web2c/synctexdir/synctex_parser.c
+++ b/Build/source/texk/web2c/synctexdir/synctex_parser.c
@@ -1,8 +1,13 @@
/*
-Copyright (c) 2008 jerome DOT laurens AT u-bourgogne DOT fr
+Copyright (c) 2008, 2009 jerome DOT laurens AT u-bourgogne DOT fr
This file is part of the SyncTeX package.
+Version: 1.6
+See synctex_parser_readme.txt for more details
+
+Latest Revision: Wed Jul 1 11:18:18 UTC 2009
+
License:
--------
Permission is hereby granted, free of charge, to any person
@@ -59,39 +64,22 @@ Thu Jun 19 09:39:21 UTC 2008
# define HAVE_LOCALE_H 1
# define HAVE_SETLOCALE 1
# if defined(_MSC_VER)
-# define inline __inline
+# define SYNCTEX_INLINE __inline
+# else
+# define SYNCTEX_INLINE inline
# endif
# endif
-#include "stddef.h"
-#include "stdio.h"
-#include "stdlib.h"
-#include "string.h"
-#include "limits.h"
-#include "time.h"
-#include "math.h"
-#include "errno.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
#if defined(HAVE_LOCALE_H)
#include <locale.h>
#endif
-void *_synctex_malloc(size_t size);
-
-/* This custom malloc functions initializes to 0 the newly allocated memory. */
-void *_synctex_malloc(size_t size) {
- void * ptr = malloc(size);
- if(ptr) {
-/* In Visual C, bzero is not available */
-#ifdef _MSC_VER
- memset(ptr,0, size);
-#else
- bzero(ptr,size);
-#endif
- }
- return (void *)ptr;
-}
-
/* 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.
@@ -103,8 +91,9 @@ void *_synctex_malloc(size_t size) {
*/
#include "synctex_parser.h"
+#include <synctex_parser_utils.h>
-/* each synctex node has a class */
+/* each synctex node has a class */
typedef struct __synctex_class_t _synctex_class_t;
typedef _synctex_class_t * synctex_class_t;
@@ -214,17 +203,20 @@ struct __synctex_class_t {
SYNCTEX_GETTER(NEW_SIBLING,parent)[0]=SYNCTEX_GETTER(NODE,parent)[0];\
}\
}
-/* Friend getter and setter
+/* 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
+/* Next box getter and setter. The box tree can be traversed from one horizontal boxes to the other.
+ * Navigation starts with the deeper boxes.
*/
-# define SYNCTEX_NEXT_BOX(NODE) SYNCTEX_GET(NODE,next_box)
-# define SYNCTEX_SET_NEXT_BOX(NODE,NEXT_BOX) if(NODE && NEXT_BOX){\
+# define SYNCTEX_NEXT_HORIZ_BOX(NODE) SYNCTEX_GET(NODE,next_box)
+# define SYNCTEX_SET_NEXT_HORIZ_BOX(NODE,NEXT_BOX) if(NODE && NEXT_BOX){\
SYNCTEX_GETTER(NODE,next_box)[0]=NEXT_BOX;\
}
@@ -256,35 +248,42 @@ void _synctex_free_leaf(synctex_node_t node) {
}
return;
}
-
-#include <zlib.h>
+# ifdef __SYNCTEX_WORK__
+# include "/usr/include/zlib.h"
+# else
+# include <zlib.h>
+# 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 */
- unsigned char * buffer_cur; /* current location in the buffer */
- unsigned char * buffer_start; /* start of the buffer */
- unsigned 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 */
- 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 */
+ gzFile file; /* The (possibly compressed) file */
+ unsigned char * buffer_cur; /* current location in the buffer */
+ unsigned char * buffer_start; /* start of the buffer */
+ unsigned 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
@@ -337,8 +336,8 @@ SYNCTEX_MAKE_GET(_synctex_implementation_5,5)
typedef struct {
synctex_class_t class;
- synctex_info_t implementation[3+SYNCTEX_PAGE_IDX+1];/* child, sibling, next box,
- * SYNCTEX_PAGE_IDX */
+ synctex_info_t implementation[3+SYNCTEX_PAGE_IDX+1];/* child, sibling, next box,
+ * SYNCTEX_PAGE_IDX */
} synctex_sheet_t;
synctex_node_t _synctex_new_sheet(synctex_scanner_t scanner);
@@ -346,18 +345,18 @@ void _synctex_display_sheet(synctex_node_t sheet);
void _synctex_log_sheet(synctex_node_t sheet);
static const _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 box */
- (_synctex_info_getter_t)&_synctex_implementation_3 /* info */
+ 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 box */
+ (_synctex_info_getter_t)&_synctex_implementation_3 /* info */
};
/* sheet node creator */
@@ -390,12 +389,15 @@ synctex_node_t _synctex_new_sheet(synctex_scanner_t scanner) {
# 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_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_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_vert_box_node_t;
synctex_node_t _synctex_new_vbox(synctex_scanner_t scanner);
@@ -405,17 +407,17 @@ 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 const _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_box, /* 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 box */
+ NULL, /* No scanner yet */
+ synctex_node_type_vbox, /* Node type */
+ &_synctex_new_vbox, /* creator */
+ &_synctex_free_node, /* destructor */
+ &_synctex_log_box, /* 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 box */
(_synctex_info_getter_t)&_synctex_implementation_5
};
@@ -439,14 +441,17 @@ synctex_node_t _synctex_new_vbox(synctex_scanner_t scanner) {
# 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)))
/* Horizontal boxes must contain visible size, because 0 width does not mean emptiness */
typedef struct {
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_HORIZ_V,SYNCTEX_VERT_V,SYNCTEX_WIDTH_V,SYNCTEX_HEIGHT_V,SYNCTEX_DEPTH_V*/
+ * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
+ * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH,
+ * SYNCTEX_HORIZ_V,SYNCTEX_VERT_V,SYNCTEX_WIDTH_V,SYNCTEX_HEIGHT_V,SYNCTEX_DEPTH_V*/
} synctex_horiz_box_node_t;
synctex_node_t _synctex_new_hbox(synctex_scanner_t scanner);
@@ -455,17 +460,17 @@ void _synctex_log_horiz_box(synctex_node_t sheet);
static const _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_horiz_box, /* 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 box */
+ NULL, /* No scanner yet */
+ synctex_node_type_hbox, /* Node type */
+ &_synctex_new_hbox, /* creator */
+ &_synctex_free_node, /* destructor */
+ &_synctex_log_horiz_box, /* 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 box */
(_synctex_info_getter_t)&_synctex_implementation_5
};
@@ -483,9 +488,9 @@ synctex_node_t _synctex_new_hbox(synctex_scanner_t scanner) {
*/
typedef struct {
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_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_void_box_node_t;
synctex_node_t _synctex_new_void_vbox(synctex_scanner_t scanner);
@@ -493,17 +498,17 @@ void _synctex_log_void_box(synctex_node_t sheet);
void _synctex_display_void_vbox(synctex_node_t node);
static const _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 box */
+ 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 box */
(_synctex_info_getter_t)&_synctex_implementation_3
};
@@ -520,17 +525,17 @@ synctex_node_t _synctex_new_void_hbox(synctex_scanner_t scanner);
void _synctex_display_void_hbox(synctex_node_t node);
static const _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 box */
+ 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 box */
(_synctex_info_getter_t)&_synctex_implementation_3
};
@@ -543,34 +548,43 @@ synctex_node_t _synctex_new_void_hbox(synctex_scanner_t scanner) {
return node;
}
-/* The medium nodes correspond to kern, glue and math nodes. */
+/* The medium nodes correspond to kern, glue, penalty and math nodes. */
typedef struct {
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_info_t implementation[3+SYNCTEX_WIDTH_IDX+1]; /* parent,sibling,friend,
+ * SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
+ * SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH */
} synctex_medium_node_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))
+
+void _synctex_log_medium_node(synctex_node_t node);
+
+/* math node creator */
synctex_node_t _synctex_new_math(synctex_scanner_t scanner);
-void _synctex_log_medium_node(synctex_node_t sheet);
void _synctex_display_math(synctex_node_t node);
static const _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 box */
+ 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 box */
(_synctex_info_getter_t)&_synctex_implementation_3
};
-/* math node creator */
synctex_node_t _synctex_new_math(synctex_scanner_t scanner) {
synctex_node_t node = _synctex_malloc(sizeof(synctex_medium_node_t));
if(node) {
@@ -579,24 +593,60 @@ synctex_node_t _synctex_new_math(synctex_scanner_t scanner) {
return node;
}
+/* kern node creator */
+synctex_node_t _synctex_new_kern(synctex_scanner_t scanner);
+void _synctex_display_kern(synctex_node_t node);
+
+static const _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 box */
+ (_synctex_info_getter_t)&_synctex_implementation_3
+};
+
+synctex_node_t _synctex_new_kern(synctex_scanner_t scanner) {
+ synctex_node_t node = _synctex_malloc(sizeof(synctex_medium_node_t));
+ if(node) {
+ node->class = scanner?scanner->class+synctex_node_type_kern:(synctex_class_t)&synctex_class_kern;
+ }
+ return node;
+}
+
+/* The small nodes correspond to glue and boundary nodes. */
+typedef struct {
+ 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_small_node_t;
+
+void _synctex_log_small_node(synctex_node_t node);
+/* glue node creator */
synctex_node_t _synctex_new_glue(synctex_scanner_t scanner);
void _synctex_display_glue(synctex_node_t node);
static const _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 box */
+ 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 box */
(_synctex_info_getter_t)&_synctex_implementation_3
};
-/* glue node creator */
synctex_node_t _synctex_new_glue(synctex_scanner_t scanner) {
synctex_node_t node = _synctex_malloc(sizeof(synctex_medium_node_t));
if(node) {
@@ -605,29 +655,29 @@ synctex_node_t _synctex_new_glue(synctex_scanner_t scanner) {
return node;
}
-synctex_node_t _synctex_new_kern(synctex_scanner_t scanner);
-void _synctex_display_kern(synctex_node_t node);
-
-static const _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 box */
+/* boundary node creator */
+synctex_node_t _synctex_new_boundary(synctex_scanner_t scanner);
+void _synctex_display_boundary(synctex_node_t node);
+
+static const _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 box */
(_synctex_info_getter_t)&_synctex_implementation_3
};
-/* kern node creator */
-synctex_node_t _synctex_new_kern(synctex_scanner_t scanner) {
- synctex_node_t node = _synctex_malloc(sizeof(synctex_medium_node_t));
+synctex_node_t _synctex_new_boundary(synctex_scanner_t scanner) {
+ synctex_node_t node = _synctex_malloc(sizeof(synctex_small_node_t));
if(node) {
- node->class = scanner?scanner->class+synctex_node_type_kern:(synctex_class_t)&synctex_class_kern;
+ node->class = scanner?scanner->class+synctex_node_type_boundary:(synctex_class_t)&synctex_class_boundary;
}
return node;
}
@@ -639,8 +689,8 @@ synctex_node_t _synctex_new_kern(synctex_scanner_t scanner) {
* The synctex information is the SYNCTEX_TAG and SYNCTEX_NAME*/
typedef struct {
synctex_class_t class;
- synctex_info_t implementation[1+SYNCTEX_NAME_IDX+1]; /* sibling,
- * SYNCTEX_TAG,SYNCTEX_NAME */
+ synctex_info_t implementation[1+SYNCTEX_NAME_IDX+1]; /* sibling,
+ * SYNCTEX_TAG,SYNCTEX_NAME */
} synctex_input_t;
synctex_node_t _synctex_new_input(synctex_scanner_t scanner);
@@ -649,17 +699,17 @@ void _synctex_display_input(synctex_node_t node);
void _synctex_log_input(synctex_node_t sheet);
static const _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 box */
+ 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 box */
(_synctex_info_getter_t)&_synctex_implementation_1
};
@@ -690,7 +740,7 @@ 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 */
+ /* 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)
@@ -709,8 +759,8 @@ sibling:
if(SYNCTEX_SIBLING(node)) {
return SYNCTEX_SIBLING(node);
}
- if((node = SYNCTEX_PARENT(node)) != NULL) {
- if(node->class->type == synctex_node_type_sheet) {/* EXC_BAD_ACCESS? */
+ if((node = SYNCTEX_PARENT(node))) {
+ if(node->class->type == synctex_node_type_sheet) {/* EXC_BAD_ACCESS? */
return NULL;
}
goto sibling;
@@ -733,7 +783,7 @@ synctex_node_type_t synctex_node_type(synctex_node_t node) {
/* 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","sheet","vbox","void vbox","hbox","non void hbox","void hbox","kern","glue","math","input"};
+ {"Not a node","input","sheet","vbox","void vbox","hbox","void hbox","kern","glue","math","boundary"};
return isa[synctex_node_type(node)];
}
@@ -755,17 +805,38 @@ void synctex_node_display(synctex_node_t node) {
SYNCTEX_DISPLAY(node);
}
+void _synctex_display_input(synctex_node_t node) {
+ printf("....Input:%i:%s\n",
+ SYNCTEX_TAG(node),
+ SYNCTEX_NAME(node));
+ SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
+}
+
void _synctex_log_sheet(synctex_node_t sheet) {
if(sheet) {
printf("%s:%i\n",synctex_node_isa(sheet),SYNCTEX_PAGE(sheet));
- printf("SELF:%p",sheet);
- printf(" SYNCTEX_PARENT:%p",SYNCTEX_PARENT(sheet));
- printf(" SYNCTEX_CHILD:%p",SYNCTEX_CHILD(sheet));
- printf(" SYNCTEX_SIBLING:%p",SYNCTEX_SIBLING(sheet));
- printf(" SYNCTEX_FRIEND:%p\n",SYNCTEX_FRIEND(sheet));
+ printf("SELF:%p",(void *)sheet);
+ printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(sheet));
+ printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(sheet));
+ printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(sheet));
+ printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(sheet));
}
}
+void _synctex_log_small_node(synctex_node_t node) {
+ printf("%s:%i,%i:%i,%i\n",
+ synctex_node_isa(node),
+ SYNCTEX_TAG(node),
+ SYNCTEX_LINE(node),
+ SYNCTEX_HORIZ(node),
+ SYNCTEX_VERT(node));
+ 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));
+}
+
void _synctex_log_medium_node(synctex_node_t node) {
printf("%s:%i,%i:%i,%i:%i\n",
synctex_node_isa(node),
@@ -774,11 +845,11 @@ void _synctex_log_medium_node(synctex_node_t node) {
SYNCTEX_HORIZ(node),
SYNCTEX_VERT(node),
SYNCTEX_WIDTH(node));
- printf("SELF:%p",node);
- printf(" SYNCTEX_PARENT:%p",SYNCTEX_PARENT(node));
- printf(" SYNCTEX_CHILD:%p",SYNCTEX_CHILD(node));
- printf(" SYNCTEX_SIBLING:%p",SYNCTEX_SIBLING(node));
- printf(" SYNCTEX_FRIEND:%p\n",SYNCTEX_FRIEND(node));
+ 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));
}
void _synctex_log_void_box(synctex_node_t node) {
@@ -791,11 +862,11 @@ void _synctex_log_void_box(synctex_node_t node) {
printf(":%i",SYNCTEX_WIDTH(node));
printf(",%i",SYNCTEX_HEIGHT(node));
printf(",%i",SYNCTEX_DEPTH(node));
- printf("\nSELF:%p",node);
- printf(" SYNCTEX_PARENT:%p",SYNCTEX_PARENT(node));
- printf(" SYNCTEX_CHILD:%p",SYNCTEX_CHILD(node));
- printf(" SYNCTEX_SIBLING:%p",SYNCTEX_SIBLING(node));
- printf(" SYNCTEX_FRIEND:%p\n",SYNCTEX_FRIEND(node));
+ printf("\nSELF:%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));
}
void _synctex_log_box(synctex_node_t node) {
@@ -808,11 +879,11 @@ void _synctex_log_box(synctex_node_t node) {
printf(":%i",SYNCTEX_WIDTH(node));
printf(",%i",SYNCTEX_HEIGHT(node));
printf(",%i",SYNCTEX_DEPTH(node));
- printf("\nSELF:%p",node);
- printf(" SYNCTEX_PARENT:%p",SYNCTEX_PARENT(node));
- printf(" SYNCTEX_CHILD:%p",SYNCTEX_CHILD(node));
- printf(" SYNCTEX_SIBLING:%p",SYNCTEX_SIBLING(node));
- printf(" SYNCTEX_FRIEND:%p\n",SYNCTEX_FRIEND(node));
+ printf("\nSELF:%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));
}
void _synctex_log_horiz_box(synctex_node_t node) {
@@ -825,23 +896,23 @@ void _synctex_log_horiz_box(synctex_node_t 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_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));
- printf("\nSELF:%p",node);
- printf(" SYNCTEX_PARENT:%p",SYNCTEX_PARENT(node));
- printf(" SYNCTEX_CHILD:%p",SYNCTEX_CHILD(node));
- printf(" SYNCTEX_SIBLING:%p",SYNCTEX_SIBLING(node));
- printf(" SYNCTEX_FRIEND:%p\n",SYNCTEX_FRIEND(node));
+ printf("\nSELF:%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));
}
void _synctex_log_input(synctex_node_t node) {
printf("%s",synctex_node_isa(node));
printf(":%i",SYNCTEX_TAG(node));
printf(",%s",SYNCTEX_NAME(node));
- printf(" SYNCTEX_SIBLING:%p",SYNCTEX_SIBLING(node));
+ printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
}
void _synctex_display_sheet(synctex_node_t sheet) {
@@ -933,10 +1004,12 @@ void _synctex_display_kern(synctex_node_t node) {
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
}
-void _synctex_display_input(synctex_node_t node) {
- printf("....Input:%i:%s\n",
+void _synctex_display_boundary(synctex_node_t node) {
+ printf("....boundary:%i,%i:%i,%i\n",
SYNCTEX_TAG(node),
- SYNCTEX_NAME(node));
+ SYNCTEX_LINE(node),
+ SYNCTEX_HORIZ(node),
+ SYNCTEX_VERT(node));
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
}
@@ -968,7 +1041,7 @@ typedef int synctex_status_t;
/* Parameter error: */
# define SYNCTEX_STATUS_BAD_ARGUMENT -2
-# define SYNCTEX_FILE scanner->file
+# define SYNCTEX_FILE (scanner->file)
/* Actually, the minimum buffer size is driven by integer and float parsing.
* ±0.123456789e123
@@ -976,55 +1049,14 @@ typedef int synctex_status_t;
# define SYNCTEX_BUFFER_MIN_SIZE 16
# define SYNCTEX_BUFFER_SIZE 32768
-#include <stdarg.h>
-
-inline static int _synctex_error(char * reason,...) {
- va_list arg;
- int result;
- result = fprintf(stderr,"SyncTeX ERROR: ");
- va_start (arg, reason);
- result += vfprintf(stderr, reason, arg);
- va_end (arg);
- result = fprintf(stderr,"\n");
- return result;
-}
-
# ifdef SYNCTEX_NOTHING
# pragma mark -
# pragma mark Prototypes
# endif
-void _synctex_free_node(synctex_node_t node);
-void _synctex_free_leaf(synctex_node_t node);
-synctex_node_t _synctex_new_sheet(synctex_scanner_t scanner);
-synctex_node_t _synctex_new_vbox(synctex_scanner_t scanner);
-synctex_node_t _synctex_new_hbox(synctex_scanner_t scanner);
-synctex_node_t _synctex_new_void_vbox(synctex_scanner_t scanner);
-synctex_node_t _synctex_new_void_hbox(synctex_scanner_t scanner);
-synctex_node_t _synctex_new_math(synctex_scanner_t scanner);
-synctex_node_t _synctex_new_glue(synctex_scanner_t scanner);
-synctex_node_t _synctex_new_kern(synctex_scanner_t scanner);
-synctex_node_t _synctex_new_input(synctex_scanner_t scanner);
-void _synctex_free_input(synctex_node_t node);
-synctex_node_t synctex_node_next(synctex_node_t node);
-synctex_node_type_t synctex_node_type(synctex_node_t node);
-const char * synctex_node_isa(synctex_node_t node);
-void synctex_node_log(synctex_node_t node);
-void _synctex_log_sheet(synctex_node_t sheet);
-void _synctex_log_medium_node(synctex_node_t node);
void _synctex_log_void_box(synctex_node_t node);
void _synctex_log_box(synctex_node_t node);
void _synctex_log_horiz_box(synctex_node_t node);
void _synctex_log_input(synctex_node_t node);
-void _synctex_display_sheet(synctex_node_t sheet);
-void _synctex_display_vbox(synctex_node_t node);
-void _synctex_display_hbox(synctex_node_t node);
-void _synctex_display_void_vbox(synctex_node_t node);
-void _synctex_display_void_hbox(synctex_node_t node);
-void _synctex_display_glue(synctex_node_t node);
-void _synctex_display_math(synctex_node_t node);
-void _synctex_display_kern(synctex_node_t node);
-void _synctex_display_input(synctex_node_t node);
-inline static int _synctex_error(char * reason,...);
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);
@@ -1039,47 +1071,11 @@ synctex_status_t _synctex_setup_visible_box(synctex_node_t box);
synctex_status_t _synctex_horiz_box_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_content(synctex_scanner_t scanner);
-void synctex_strip_last_path_extension(char * string);
-synctex_scanner_t synctex_scanner_new_with_output_file(const char * output);
-synctex_scanner_t synctex_scanner_new_with_contents_of_file(const char * name);
-void synctex_scanner_free(synctex_scanner_t scanner);
int synctex_scanner_pre_x_offset(synctex_scanner_t scanner);
int synctex_scanner_pre_y_offset(synctex_scanner_t scanner);
-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);
-void synctex_scanner_display(synctex_scanner_t scanner);
-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_fmt(synctex_scanner_t scanner);
-const char * synctex_scanner_get_output(synctex_scanner_t scanner);
-float synctex_node_h(synctex_node_t node);
-float synctex_node_v(synctex_node_t node);
-float synctex_node_width(synctex_node_t node);
-float synctex_node_box_h(synctex_node_t node);
-float synctex_node_box_v(synctex_node_t node);
-float synctex_node_box_width(synctex_node_t node);
-float synctex_node_box_height(synctex_node_t node);
-float synctex_node_box_depth(synctex_node_t node);
-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);
-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);
-int synctex_node_page(synctex_node_t node);
-int synctex_node_tag(synctex_node_t node);
-int synctex_node_line(synctex_node_t node);
-int synctex_node_column(synctex_node_t node);
-synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page);
-int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column);
int _synctex_node_is_box(synctex_node_t node);
-int synctex_edit_query(synctex_scanner_t scanner,int page,float h,float v);
-synctex_node_t synctex_next_result(synctex_scanner_t scanner);
-int synctex_bail(void);
+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.
@@ -1089,7 +1085,7 @@ int synctex_bail(void);
* 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 returned in case of error, actually
+ * 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;
@@ -1100,36 +1096,43 @@ synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, s
if(size>SYNCTEX_BUFFER_SIZE){
size = SYNCTEX_BUFFER_SIZE;
}
- available = SYNCTEX_END - SYNCTEX_CUR; /* available is the number of unparsed chars in the buffer */
+ 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 */
+ /* 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 read = 0;
+ /* Copy the remaining part of the buffer to the beginning,
+ * then read the next part of the file */
+ int already_read = 0;
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 */
- read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,SYNCTEX_BUFFER_SIZE - available);
- if(read>0) {
- /* We assume that 0<read<=SYNCTEX_BUFFER_SIZE - available, such that
- * SYNCTEX_CUR + read = SYNCTEX_START + available + read <= SYNCTEX_START + SYNCTEX_BUFFER_SIZE */
- SYNCTEX_END = SYNCTEX_CUR + read;
+ 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 0<already_read<=SYNCTEX_BUFFER_SIZE - available, such that
+ * SYNCTEX_CUR + already_read = SYNCTEX_START + available + already_read <= SYNCTEX_START + SYNCTEX_BUFFER_SIZE */
+ SYNCTEX_END = SYNCTEX_CUR + already_read;
/* If the end of the file was reached, all the required SYNCTEX_BUFFER_SIZE - available
* may not be filled with values from the file.
- * In that case, the buffer should stop properly after read characters. */
+ * In that case, the buffer should stop properly after already_read characters. */
* SYNCTEX_END = '\0';
SYNCTEX_CUR = SYNCTEX_START;
- size = SYNCTEX_END - SYNCTEX_CUR; /* == old available + read*/
- return SYNCTEX_STATUS_OK; /* May be available is less than size, the caller will have to test. */
- } else if(read<0) {
- /*There is an error */
- _synctex_error("gzread error (1:%i)",read);
+ size = SYNCTEX_END - SYNCTEX_CUR; /* == old available + already_read*/
+ return SYNCTEX_STATUS_OK; /* May be available is less than size, the caller will have to test. */
+ } else if(0>already_read) {
+ /* There is an error in zlib */
+ 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);
+ } else {
+ _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string);
+ }
return SYNCTEX_STATUS_ERROR;
} else {
/* Nothing was read, we are at the end of the file. */
@@ -1137,13 +1140,13 @@ synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, s
SYNCTEX_FILE = NULL;
SYNCTEX_END = SYNCTEX_CUR;
SYNCTEX_CUR = SYNCTEX_START;
- * SYNCTEX_END = '\0';/* Terminate the string properly.*/
+ * SYNCTEX_END = '\0';/* Terminate the string properly.*/
size = SYNCTEX_END - SYNCTEX_CUR;
- return SYNCTEX_STATUS_EOF; /* there might be a bit of text left */
+ return SYNCTEX_STATUS_EOF; /* there might be a bit of text left */
}
- /* At this point, the function has already returned from above */
+ /* At this point, the function has already returned from above */
}
- /* We cannot enlarge the buffer because the end of the file was reached. */
+ /* We cannot enlarge the buffer because the end of the file was reached. */
size = available;
return SYNCTEX_STATUS_EOF;
# undef size
@@ -1194,14 +1197,14 @@ infinite_loop:
* As side effect, the buffer state may have changed if the given argument string can't fit into the buffer.
*/
synctex_status_t _synctex_match_string(synctex_scanner_t scanner, const char * the_string) {
- size_t tested_len = 0; /* the number of characters at the beginning of the_string that match */
- size_t remaining_len = 0; /* the number of remaining characters of the_string that should match */
+ size_t tested_len = 0; /* the number of characters at the beginning of the_string that match */
+ size_t remaining_len = 0; /* the number of remaining characters of the_string that should match */
size_t available = 0;
synctex_status_t status = 0;
if(NULL == scanner || NULL == the_string) {
return SYNCTEX_STATUS_BAD_ARGUMENT;
}
- remaining_len = strlen(the_string); /* All the_string should match */
+ remaining_len = strlen(the_string); /* All the_string should match */
if(0 == remaining_len) {
return SYNCTEX_STATUS_BAD_ARGUMENT;
}
@@ -1233,9 +1236,9 @@ return_OK:
/* update the remaining length and the parsed length. */
remaining_len -= available;
tested_len += available;
- SYNCTEX_CUR += available; /* We validate the tested characters. */
+ 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. */
+ /* 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
@@ -1246,7 +1249,7 @@ return_OK:
* 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 = 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.
@@ -1260,14 +1263,14 @@ more_characters:
available = remaining_len;
status = _synctex_buffer_get_available_size(scanner,&available);
if(status<SYNCTEX_STATUS_EOF) {
- return status; /* This is an error, no need to go further. */
+ return status; /* This is an error, no need to go further. */
}
if(available==0) {
- /* Missing characters: recover the initial state of the file and return. */
+ /* Missing characters: recover the initial state of the file and return. */
return_NOT_OK:
if(offset != gzseek(SYNCTEX_FILE,offset,SEEK_SET)) {
/* This is a critical error, we could not recover the previous state. */
- fprintf(stderr,"SyncTeX critical ERROR: can't seek file\n");
+ _synctex_error("can't seek file");
return SYNCTEX_STATUS_ERROR;
}
/* Next time we are asked to fill the buffer,
@@ -1278,7 +1281,7 @@ return_NOT_OK:
if(available<remaining_len) {
/* We'll have to loop one more time. */
if(strncmp((char *)SYNCTEX_CUR,the_string,available)) {
- /* This is not the expected string, recover the previous state and return. */
+ /* This is not the expected string, recover the previous state and return. */
goto return_NOT_OK;
}
/* Advance the_string to the first untested character. */
@@ -1286,21 +1289,21 @@ return_NOT_OK:
/* update the remaining length and the parsed length. */
remaining_len -= available;
tested_len += available;
- SYNCTEX_CUR += available; /* We validate the tested characters. */
+ SYNCTEX_CUR += available; /* We validate the tested characters. */
if(0 == remaining_len) {
- /* Nothing left to test, we have found the given string. */
+ /* Nothing left to test, we have found the given string. */
return SYNCTEX_STATUS_OK;
}
goto more_characters;
}
/* This is the last step. */
if(strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) {
- /* This is not the expected string, recover the previous state and return. */
+ /* This is not the expected string, recover the previous state and return. */
goto return_NOT_OK;
}
goto return_OK;
} else {
- /* The buffer can't contain the given string argument, and the EOF was reached */
+ /* The buffer can't contain the given string argument, and the EOF was reached */
return SYNCTEX_STATUS_EOF;
}
}
@@ -1327,17 +1330,17 @@ synctex_status_t _synctex_decode_int(synctex_scanner_t scanner, int* value_ref)
available = SYNCTEX_BUFFER_MIN_SIZE;
status = _synctex_buffer_get_available_size(scanner, &available);
if(status<SYNCTEX_STATUS_EOF) {
- return status;/* Forward error. */
+ return status;/* Forward error. */
}
if(available==0) {
- return SYNCTEX_STATUS_EOF;/* it is the end of file. */
+ return SYNCTEX_STATUS_EOF;/* it is the end of file. */
}
ptr = SYNCTEX_CUR;
if(*ptr==':' || *ptr==',') {
++ptr;
--available;
if(available==0) {
- return SYNCTEX_STATUS_NOT_OK;/* It is not possible to scan an int */
+ return SYNCTEX_STATUS_NOT_OK;/* It is not possible to scan an int */
}
}
result = (int)strtol((char *)ptr, (char **)&end, 10);
@@ -1346,9 +1349,9 @@ synctex_status_t _synctex_decode_int(synctex_scanner_t scanner, int* value_ref)
if(value_ref) {
* value_ref = result;
}
- return SYNCTEX_STATUS_OK;/* Successfully scanned an int */
+ return SYNCTEX_STATUS_OK;/* Successfully scanned an int */
}
- return SYNCTEX_STATUS_NOT_OK;/* Could not scan an int */
+ return SYNCTEX_STATUS_NOT_OK;/* Could not scan an int */
}
/* The purpose of this function is to read a string.
@@ -1372,13 +1375,13 @@ synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value
unsigned 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 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 */
+ /* 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);
@@ -1389,16 +1392,16 @@ synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value
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. */
+ /* 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' */
+ * value_ref = NULL;/* Initialize, it will be realloc'ed */
+ /* We scan all the characters up to the next '\n' */
next_character:
if(end<SYNCTEX_END) {
if(*end == '\n') {
- /* OK, we found where to stop */
+ /* OK, we found where to stop */
len = end - SYNCTEX_CUR;
if(current_size>UINT_MAX-len-1) {
/* But we have reached the limit: we do not have current_size+len+1>UINT_MAX.
@@ -1412,8 +1415,8 @@ next_character:
* where we have assumed that len<UINT_MAX */
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 += len;/* Advance to the terminating '\n' */
+ (* value_ref)[new_size]='\0'; /* Terminate the string */
+ SYNCTEX_CUR += len;/* Advance to the terminating '\n' */
return SYNCTEX_STATUS_OK;
}
free(* value_ref);
@@ -1428,7 +1431,7 @@ next_character:
goto next_character;
}
} else {
- /* end == SYNCTEX_END */
+ /* end == SYNCTEX_END */
len = SYNCTEX_END - SYNCTEX_CUR;
if(current_size>UINT_MAX-len-1) {
/* We have reached the limit. */
@@ -1438,8 +1441,8 @@ next_character:
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 */
+ (* 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);
@@ -1447,7 +1450,7 @@ next_character:
_synctex_error("could not copy memory (2).");
return SYNCTEX_STATUS_ERROR;
}
- /* Huge memory problem */
+ /* Huge memory problem */
_synctex_error("could not allocate memory (2).");
return SYNCTEX_STATUS_ERROR;
}
@@ -1501,7 +1504,7 @@ synctex_status_t _synctex_scan_input(synctex_scanner_t scanner) {
/* Prepend this input node to the input linked list of the scanner */
SYNCTEX_SET_SIBLING(input,scanner->input);
scanner->input = input;
- return _synctex_next_line(scanner);/* read the line termination character, if any */
+ return _synctex_next_line(scanner);/* read the line termination character, if any */
/* Now, set up the path */
}
@@ -1533,7 +1536,7 @@ not_found:
}
goto not_found;
}
- /* A line is found, scan the value */
+ /* A line is found, scan the value */
return (*decoder)(scanner,value_ref);
}
@@ -1705,19 +1708,19 @@ post_scriptum_not_found:
if(status<SYNCTEX_STATUS_EOF) {
return status;
} else if(status<SYNCTEX_STATUS_OK) {
- return SYNCTEX_STATUS_OK;/* The EOF is found, we have properly scanned the file */
+ return SYNCTEX_STATUS_OK;/* The EOF is found, we have properly scanned the file */
}
goto post_scriptum_not_found;
}
- /* We found the name, advance to the next line. */
+ /* We found the name, advance to the next line. */
next_line:
status = _synctex_next_line(scanner);
if(status<SYNCTEX_STATUS_EOF) {
return status;
} else if(status<SYNCTEX_STATUS_OK) {
- return SYNCTEX_STATUS_OK;/* The EOF is found, we have properly scanned the file */
+ return SYNCTEX_STATUS_OK;/* The EOF is found, we have properly scanned the file */
}
- /* Scanning the information */
+ /* Scanning the information */
status = _synctex_match_string(scanner,"Magnification:");
if(status == SYNCTEX_STATUS_OK ) {
#ifdef HAVE_SETLOCALE
@@ -1741,7 +1744,7 @@ next_line:
if(status<SYNCTEX_STATUS_EOF){
report_record_problem:
_synctex_error("Problem reading the Post Scriptum records");
- return status; /* echo the error. */
+ return status; /* echo the error. */
}
status = _synctex_match_string(scanner,"X Offset:");
if(status == SYNCTEX_STATUS_OK) {
@@ -1789,9 +1792,9 @@ count_again:
}
status = _synctex_scan_named(scanner,"Count:",&(scanner->count),(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 */
+ 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(status<SYNCTEX_STATUS_OK) {
return status;
}
@@ -1807,21 +1810,21 @@ count_again:
* At creation time, the visible size is set to the values of the real size.
*/
synctex_status_t _synctex_setup_visible_box(synctex_node_t box) {
- if(NULL == box
- || (box->class->type != synctex_node_type_hbox
- && box->class->type != synctex_node_type_hbox_non_void
- && box->class->type != synctex_node_type_vbox)) {
- return SYNCTEX_STATUS_BAD_ARGUMENT;
- }
- 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;
+ if(box) {
+ switch(box->class->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_ERROR;
+ return SYNCTEX_STATUS_BAD_ARGUMENT;
}
/* This method is sent to an horizontal box to setup the visible size
@@ -1833,40 +1836,31 @@ synctex_status_t _synctex_horiz_box_setup_visible(synctex_node_t node,int h, int
# pragma unused(v)
# endif
int itsBtm, itsTop;
- if(NULL == node || (node->class->type != synctex_node_type_hbox
- && node->class->type != synctex_node_type_hbox_non_void)) {
+ 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)+SYNCTEX_WIDTH_V(node);
- itsTop = SYNCTEX_HORIZ_V(node);
+ itsBtm = SYNCTEX_HORIZ_V(node);
+ itsTop = SYNCTEX_HORIZ_V(node)-SYNCTEX_WIDTH_V(node);
if(h<itsBtm) {
- itsBtm -= h;
- SYNCTEX_WIDTH_V(node) -= itsBtm;
- }
- if(h>itsTop) {
- h -= itsTop;
- SYNCTEX_WIDTH_V(node) -= h;
- SYNCTEX_HORIZ_V(node) += h;
+ SYNCTEX_HORIZ_V(node) = h;
+ SYNCTEX_WIDTH_V(node) = SYNCTEX_HORIZ_V(node) - itsTop;
+ } else if(h>itsTop) {
+ 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(h<itsBtm) {
- itsBtm -= h;
- SYNCTEX_HORIZ_V(node) -= itsBtm;
- SYNCTEX_WIDTH_V(node) += itsBtm;
- }
- if(h>itsTop) {
- h -= itsTop;
- SYNCTEX_WIDTH_V(node) += h;
+ SYNCTEX_HORIZ_V(node) = h;
+ SYNCTEX_WIDTH_V(node) = itsTop - SYNCTEX_HORIZ_V(node);
+ } else if(h>itsTop) {
+ SYNCTEX_WIDTH_V(node) = h - SYNCTEX_HORIZ_V(node);
}
}
return SYNCTEX_STATUS_OK;
}
-int synctex_bail(void);
-
/* Used when parsing the synctex file.
* The sheet argument is a newly created sheet node that will hold the contents.
* Something is returned in case of error.
@@ -1878,13 +1872,12 @@ synctex_status_t _synctex_scan_sheet(synctex_scanner_t scanner, synctex_node_t s
synctex_node_t box = sheet;
int friend_index = 0;
synctex_info_t * info = NULL;
- int curh, curv;
synctex_status_t status = 0;
size_t available = 0;
if((NULL == scanner) || (NULL == sheet)) {
return SYNCTEX_STATUS_BAD_ARGUMENT;
}
- /* We MUST start with a box, so at this level, the unique possibility is '[', '(' or "}". */
+ /* We MUST start with a box, so at this level, the unique possibility is '[', '(' or "}". */
prepare_loop:
if(SYNCTEX_CUR<SYNCTEX_END) {
if(*SYNCTEX_CUR == '[') {
@@ -1900,7 +1893,7 @@ scan_vbox:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad vbox record.");
#define SYNCTEX_RETURN(STATUS) return STATUS;
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -1908,7 +1901,7 @@ scan_vbox:
SYNCTEX_SET_CHILD(parent,child);
parent = child;
child = NULL;
- goto vertical_loop;
+ goto child_loop;/* next created node will be a child */
} else {
_synctex_error("Can't create vbox record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -1925,14 +1918,16 @@ scan_hbox:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
|| _synctex_setup_visible_box(child)<SYNCTEX_STATUS_OK
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad hbox record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
SYNCTEX_SET_CHILD(parent,child);
parent = child;
child = NULL;
- goto vertical_loop;
+ goto child_loop;/* next created node will be a child */
} else {
_synctex_error("Can't create hbox record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -1941,7 +1936,7 @@ scan_hbox:
scan_teehs:
++SYNCTEX_CUR;
if(NULL == parent || parent->class->type != synctex_node_type_sheet
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Unexpected end of sheet.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
@@ -1955,7 +1950,7 @@ scan_anchor:
}
goto prepare_loop;
} else {
- /* _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
+ /* _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
++SYNCTEX_CUR;
if(_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Unexpected end.");
@@ -1973,12 +1968,15 @@ scan_anchor:
goto prepare_loop;
}
}
- synctex_bail();
-vertical_loop:
+ _synctex_bail();
+/* The child loop means that we go do one level, when we just created a box node,
+ * the next node created is a child of this box. */
+child_loop:
if(SYNCTEX_CUR<SYNCTEX_END) {
if(*SYNCTEX_CUR == '[') {
goto scan_vbox;
} else if(*SYNCTEX_CUR == ']') {
+scan_xobv:
++SYNCTEX_CUR;
if(NULL != parent && parent->class->type == synctex_node_type_vbox) {
#define SYNCTEX_UPDATE_BOX_FRIEND(NODE)\
@@ -1986,7 +1984,7 @@ vertical_loop:
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 */
+ /* only void boxes are friends */
SYNCTEX_UPDATE_BOX_FRIEND(parent);
}
child = parent;
@@ -1998,20 +1996,21 @@ vertical_loop:
_synctex_error("Uncomplete sheet.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
- goto horizontal_loop;
+ goto sibling_loop;
} else if(*SYNCTEX_CUR == '(') {
goto scan_hbox;
} else if(*SYNCTEX_CUR == ')') {
+scan_xobh:
++SYNCTEX_CUR;
- if(NULL != parent && (parent->class->type == synctex_node_type_hbox
- || parent->class->type == synctex_node_type_hbox_non_void)) {
+ if((parent) && parent->class->type == synctex_node_type_hbox) {
if(NULL == child) {
+ /* Only boxes with no children are friends,
+ * boxes with children are indirectly friends through one of their descendants. */
SYNCTEX_UPDATE_BOX_FRIEND(parent);
}
- if(parent->class->type == synctex_node_type_hbox_non_void) {
- SYNCTEX_SET_NEXT_BOX(box,parent);
- box = parent;
- }
+ /* setting the next horizontal box at the end ensures that a child is recorded before any of its ancestors. */
+ SYNCTEX_SET_NEXT_HORIZ_BOX(box,parent);
+ box = parent;
child = parent;
parent = SYNCTEX_PARENT(child);
} else {
@@ -2021,7 +2020,7 @@ vertical_loop:
_synctex_error("Uncomplete sheet.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
- goto horizontal_loop;
+ goto sibling_loop;
} else if(*SYNCTEX_CUR == 'v') {
++SYNCTEX_CUR;
if(NULL != (child = _synctex_new_void_vbox(scanner))
@@ -2033,7 +2032,7 @@ vertical_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad void vbox record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
@@ -2043,7 +2042,7 @@ vertical_loop:
SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\
(scanner->lists_of_friends)[friend_index] = NODE;
SYNCTEX_UPDATE_FRIEND(child);
- goto horizontal_loop;
+ goto sibling_loop;
} else {
_synctex_error("Can't create vbox record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -2059,15 +2058,15 @@ vertical_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad void hbox record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_CHILD(parent,child);
SYNCTEX_UPDATE_FRIEND(child);
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child),synctex_node_v(child));
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child)+synctex_node_width(child),synctex_node_v(child));
- goto horizontal_loop;
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
+ goto sibling_loop;
} else {
_synctex_error("Can't create void hbox record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -2081,40 +2080,19 @@ vertical_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad kern record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_CHILD(parent,child);
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child),synctex_node_v(child));
- #define SYNCTEX_HBOX_SET_NON_VOID(NODE)\
- if(NODE->class->type == synctex_node_type_hbox) {\
- NODE->class->type = synctex_node_type_hbox_non_void;\
- }
- SYNCTEX_HBOX_SET_NON_VOID(parent);
SYNCTEX_UPDATE_FRIEND(child);
- if(NULL == parent) {
- _synctex_error("Missing parent for Child");
- synctex_node_log(child);
- SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
- }
- goto horizontal_loop;
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)-SYNCTEX_WIDTH(child),SYNCTEX_VERT(child));
+ goto sibling_loop;
} else {
_synctex_error("Can't create kern record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
- } else if(*SYNCTEX_CUR == 'x') {
- ++SYNCTEX_CUR;
- if(_synctex_decode_int(scanner,NULL)<SYNCTEX_STATUS_OK
- || _synctex_decode_int(scanner,NULL)<SYNCTEX_STATUS_OK
- || _synctex_decode_int(scanner,&curh)<SYNCTEX_STATUS_OK
- || _synctex_decode_int(scanner,&curv)<SYNCTEX_STATUS_OK
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
- _synctex_error("Bad x record.");
- SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
- }
- _synctex_horiz_box_setup_visible(parent,curh,curv);
- goto vertical_loop;
} else if(*SYNCTEX_CUR == 'g') {
++SYNCTEX_CUR;
if(NULL != (child = _synctex_new_glue(scanner))
@@ -2123,15 +2101,14 @@ vertical_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad glue record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_CHILD(parent,child);
- SYNCTEX_HBOX_SET_NON_VOID(parent);
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child),synctex_node_v(child));
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
SYNCTEX_UPDATE_FRIEND(child);
- goto horizontal_loop;
+ goto sibling_loop;
} else {
_synctex_error("Can't create glue record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -2144,15 +2121,34 @@ vertical_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad math record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_CHILD(parent,child);
- SYNCTEX_HBOX_SET_NON_VOID(parent);
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child),synctex_node_v(child));
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
SYNCTEX_UPDATE_FRIEND(child);
- goto horizontal_loop;
+ goto sibling_loop;
+ } else {
+ _synctex_error("Can't create math record.");
+ SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
+ }
+ } else if(*SYNCTEX_CUR == 'x') {
+ ++SYNCTEX_CUR;
+ if(NULL != (child = _synctex_new_boundary(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_next_line(scanner)<SYNCTEX_STATUS_OK) {
+ _synctex_error("Bad boundary record.");
+ SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
+ }
+ SYNCTEX_SET_CHILD(parent,child);
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ SYNCTEX_UPDATE_FRIEND(child);
+ goto sibling_loop;
} else {
_synctex_error("Can't create math record.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -2162,13 +2158,13 @@ vertical_loop:
} else if(*SYNCTEX_CUR == '!') {
goto scan_anchor;
} else {
- /* _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
+ /* _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
++SYNCTEX_CUR;
if(_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Unexpected end.");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
- goto vertical_loop;
+ goto child_loop;
}
} else {
available = 1;
@@ -2177,11 +2173,13 @@ vertical_loop:
_synctex_error("Uncomplete sheet(0)");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
} else {
- goto vertical_loop;
+ goto child_loop;
}
}
- synctex_bail();
-horizontal_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_CUR<SYNCTEX_END) {
if(*SYNCTEX_CUR == '[') {
++SYNCTEX_CUR;
@@ -2194,34 +2192,20 @@ horizontal_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad vbox record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_SIBLING(child,sibling);
parent = sibling;
child = NULL;
- goto vertical_loop;
+ goto child_loop;
} else {
_synctex_error("Can't create vbox record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
} else if(*SYNCTEX_CUR == ']') {
- ++SYNCTEX_CUR;
- if(NULL != parent && parent->class->type == synctex_node_type_vbox) {
- if(NULL == child) {
- SYNCTEX_UPDATE_BOX_FRIEND(parent);
- }
- child = parent;
- parent = SYNCTEX_PARENT(child);
- } else {
- _synctex_error("Unexpected end of vbox record (2), ignored.");
- }
- if(_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
- _synctex_error("Unexpected end of file (2).");
- SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
- }
- goto horizontal_loop;
+ goto scan_xobv;
} else if(*SYNCTEX_CUR == '(') {
++SYNCTEX_CUR;
if(NULL != (sibling = _synctex_new_hbox(scanner)) &&
@@ -2234,39 +2218,23 @@ horizontal_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
|| _synctex_setup_visible_box(sibling)<SYNCTEX_STATUS_OK
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad hbox record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_SIBLING(child,sibling);
- parent = sibling;
+ child = sibling;
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
+ parent = child;
child = NULL;
- goto vertical_loop;
+ goto child_loop;
} else {
_synctex_error("Can't create hbox record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
} else if(*SYNCTEX_CUR == ')') {
- ++SYNCTEX_CUR;
- if(NULL != parent &&(parent->class->type == synctex_node_type_hbox
- ||parent->class->type == synctex_node_type_hbox_non_void)) {
- if(NULL == child) {
- SYNCTEX_UPDATE_BOX_FRIEND(parent);
- }
- if(parent->class->type == synctex_node_type_hbox_non_void) {
- SYNCTEX_SET_NEXT_BOX(box,parent);
- box = parent;
- }
- child = parent;
- parent = SYNCTEX_PARENT(child);
- } else {
- _synctex_error("Unexpected end of hbox record (2).");
- }
- if(_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
- _synctex_error("Unexpected end of file (2,')').");
- SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
- }
- goto horizontal_loop;
+ goto scan_xobh;
} else if(*SYNCTEX_CUR == 'v') {
++SYNCTEX_CUR;
if(NULL != (sibling = _synctex_new_void_vbox(scanner)) &&
@@ -2278,14 +2246,14 @@ horizontal_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad void vbox record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_SIBLING(child,sibling);
- SYNCTEX_UPDATE_FRIEND(sibling);
child = sibling;
- goto horizontal_loop;
+ SYNCTEX_UPDATE_FRIEND(child);
+ goto sibling_loop;
} else {
_synctex_error("can't create void vbox record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -2301,32 +2269,20 @@ horizontal_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad void hbox record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_SIBLING(child,sibling);
- SYNCTEX_UPDATE_FRIEND(sibling);
child = sibling;
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child),synctex_node_v(child));
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child)+synctex_node_width(child),synctex_node_v(child));
- goto horizontal_loop;
+ SYNCTEX_UPDATE_FRIEND(child);
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
+ goto sibling_loop;
} else {
_synctex_error("can't create void hbox record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
- } else if(*SYNCTEX_CUR == 'x') {
- ++SYNCTEX_CUR;
- if(_synctex_decode_int(scanner,NULL)<SYNCTEX_STATUS_OK
- || _synctex_decode_int(scanner,NULL)<SYNCTEX_STATUS_OK
- || _synctex_decode_int(scanner,&curh)<SYNCTEX_STATUS_OK
- || _synctex_decode_int(scanner,&curv)<SYNCTEX_STATUS_OK
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
- _synctex_error("Bad x record (2).");
- SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
- }
- _synctex_horiz_box_setup_visible(parent,curh,curv);
- goto horizontal_loop;
} else if(*SYNCTEX_CUR == 'k') {
++SYNCTEX_CUR;
if(NULL != (sibling = _synctex_new_kern(scanner))
@@ -2336,16 +2292,16 @@ horizontal_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad kern record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_SIBLING(child,sibling);
- SYNCTEX_UPDATE_FRIEND(sibling);
child = sibling;
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child),synctex_node_v(child));
- SYNCTEX_HBOX_SET_NON_VOID(parent);
- goto horizontal_loop;
+ SYNCTEX_UPDATE_FRIEND(child);
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)-SYNCTEX_WIDTH(child),SYNCTEX_VERT(child));
+ goto sibling_loop;
} else {
_synctex_error("Can't create kern record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -2358,16 +2314,15 @@ horizontal_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad glue record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_SIBLING(child,sibling);
- SYNCTEX_UPDATE_FRIEND(sibling);
child = sibling;
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(child),synctex_node_v(child));
- SYNCTEX_HBOX_SET_NON_VOID(parent);
- goto horizontal_loop;
+ SYNCTEX_UPDATE_FRIEND(child);
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ goto sibling_loop;
} else {
_synctex_error("Can't create glue record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -2380,20 +2335,40 @@ horizontal_loop:
|| SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
|| SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
- || (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK)) {
+ || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
_synctex_error("Bad math record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
SYNCTEX_SET_SIBLING(child,sibling);
- _synctex_horiz_box_setup_visible(parent,synctex_node_h(sibling),synctex_node_v(sibling));
- SYNCTEX_UPDATE_FRIEND(sibling);
child = sibling;
- SYNCTEX_HBOX_SET_NON_VOID(parent);
- goto horizontal_loop;
+ SYNCTEX_UPDATE_FRIEND(child);
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ goto sibling_loop;
} else {
_synctex_error("Can't create math record (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
+ } else if(*SYNCTEX_CUR == 'x') {
+ ++SYNCTEX_CUR;
+ if(NULL != (sibling = _synctex_new_boundary(scanner))
+ && NULL != (info = SYNCTEX_INFO(sibling))) {
+ 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_next_line(scanner)<SYNCTEX_STATUS_OK) {
+ _synctex_error("Bad boundary record (2).");
+ SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
+ }
+ SYNCTEX_SET_SIBLING(child,sibling);
+ child = sibling;
+ SYNCTEX_UPDATE_FRIEND(child);
+ _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
+ goto sibling_loop;
+ } else {
+ _synctex_error("Can't create boundary record (2).");
+ SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
+ }
} else if(*SYNCTEX_CUR == '}') {
goto scan_teehs;
} else if(*SYNCTEX_CUR == '!') {
@@ -2402,20 +2377,20 @@ horizontal_loop:
_synctex_error("Missing anchor (2).");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
- goto horizontal_loop;
+ goto sibling_loop;
} else {
++SYNCTEX_CUR;
/* _synctex_error("Ignored record %c(2)\n",*SYNCTEX_CUR); */
if(_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
}
- goto horizontal_loop;
+ goto sibling_loop;
}
} else {
available = 1;
status = _synctex_buffer_get_available_size(scanner,&available);
if(status<SYNCTEX_STATUS_OK && available>0){
- goto horizontal_loop;
+ goto sibling_loop;
} else {
_synctex_error("Uncomplete sheet(2)");
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
@@ -2432,7 +2407,7 @@ synctex_status_t _synctex_scan_content(synctex_scanner_t scanner) {
if(NULL == scanner) {
return SYNCTEX_STATUS_BAD_ARGUMENT;
}
- /* set up the lists of friends */
+ /* 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));
@@ -2441,7 +2416,7 @@ synctex_status_t _synctex_scan_content(synctex_scanner_t scanner) {
return SYNCTEX_STATUS_ERROR;
}
}
- /* Find where this section starts */
+ /* Find where this section starts */
content_not_found:
status = _synctex_match_string(scanner,"Content:");
if(status<SYNCTEX_STATUS_EOF) {
@@ -2472,7 +2447,7 @@ next_sheet:
return SYNCTEX_STATUS_OK;
}
++SYNCTEX_CUR;
- /* Create a new sheet node */
+ /* Create a new sheet node */
sheet = _synctex_new_sheet(scanner);
status = _synctex_decode_int(scanner,&(SYNCTEX_PAGE(sheet)));
if(status<SYNCTEX_STATUS_OK) {
@@ -2494,7 +2469,7 @@ bail:
SYNCTEX_SET_SIBLING(sheet,scanner->sheet);
scanner->sheet = sheet;
sheet = NULL;
- /* Now read the list of Inputs between 2 sheets. */
+ /* Now read the list of Inputs between 2 sheets. */
do {
status = _synctex_scan_input(scanner);
if(status<SYNCTEX_STATUS_EOF) {
@@ -2506,119 +2481,251 @@ bail:
goto next_sheet;
}
-/* These are the possible extensions of the synctex file */
-static const char * synctex_suffix = ".synctex";
-static const char * synctex_suffix_gz = ".gz";
-
-/* strip the last extension of the given string */
-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(NULL != (next = strstr(last_component,"/"))){
- last_component = next+1;
- }
- }
- /* then we find the last path extension */
- if(NULL != (last_extension = strstr(last_component,"."))){
- ++last_extension;
- while(NULL != (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_scanner_t synctex_scanner_new_with_contents_of_file(const char * name);
-
-/* Where the synctex scanner is created.
- * output is the full or relative path of the uncompressed or compressed synctex file.
- * On error, NULL is returned.
- * This can be due to allocation error, or an internal inconsistency (bad SYNCTEX_BUFFER_SIZE). */
-synctex_scanner_t synctex_scanner_new_with_output_file(const char * output) {
- synctex_scanner_t scanner = NULL;
+/* 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;
- size_t size = 0;
+ synctex_scanner_t scanner = NULL;
+ synctex_io_mode_t io_mode = synctex_io_mode_read;
/* Here we assume that int are smaller than void * */
if(sizeof(int)>sizeof(void*)) {
- fputs("SyncTeX INTERNAL INCONSISTENCY: int's are unexpectedly bigger than pointers, bailing out.",stderr);
+ _synctex_error("INTERNAL INCONSISTENCY: int's are unexpectedly bigger than pointers, bailing out.");
return NULL;
}
- /* now create the synctex file name */
- size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1;
- synctex = (char *)malloc(size);
- if(NULL == synctex) {
- fprintf(stderr,"! synctex_scanner_new_with_output_file: Memory problem (1)\n");
+ /* We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */
+ if(SYNCTEX_BUFFER_SIZE >= UINT_MAX) {
+ _synctex_error("SyncTeX BUG: Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (1)");
return NULL;
}
- /* we have reserved for synctex enough memory to copy output and both suffices,
- * including the terminating character */
- if(synctex != strcpy(synctex,output)) {
- fprintf(stderr,"! synctex_scanner_new_with_output_file: Copy problem\n");
-return_on_error:
- free(synctex);
+ /* for integers: */
+ if(SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE) {
+ _synctex_error("SyncTeX BUG: Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (2)");
return NULL;
}
- /* remove the last path extension if any */
- synctex_strip_last_path_extension(synctex);
- if(synctex != strcat(synctex,synctex_suffix)){
- fprintf(stderr,"! synctex_scanner_new_with_output_file: Concatenation problem (can't add suffix '%s')\n",synctex_suffix);
- goto return_on_error;
+ /* now open the synctex file */
+ if(_synctex_open(output,build_directory,&synctex,&file,synctex_NO,&io_mode) || !file) {
+ if(_synctex_open(output,build_directory,&synctex,&file,synctex_YES,&io_mode) || !file) {
+ return NULL;
+ }
}
- scanner = synctex_scanner_new_with_contents_of_file(synctex);
+ scanner = (synctex_scanner_t)_synctex_malloc(sizeof(_synctex_scanner_t));
if(NULL == scanner) {
- if(synctex != strcat(synctex,synctex_suffix_gz)){
- fprintf(stderr,"! synctex_scanner_new_with_output_file: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz);
- goto return_on_error;
- }
- scanner = synctex_scanner_new_with_contents_of_file(synctex);
- if(NULL == scanner) {
- goto return_on_error;
- }
+ _synctex_error("SyncTeX: malloc problem");
+ free(synctex);
+ gzclose(file);
+ return NULL;
}
- /* make a private copy of output for the scanner */
+ /* make a private copy of output for the scanner */
if(NULL == (scanner->output = (char *)malloc(strlen(output)+1))){
- fputs("! synctex_scanner_new_with_output_file: Memory problem (2), scanner's output is not reliable.",stderr);
+ _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)) {
- fputs("! synctex_scanner_new_with_output_file: Copy problem, scanner's output is not reliable.\n",stderr);
+ _synctex_error("! synctex_scanner_new_with_output_file: Copy problem, scanner's output is not reliable.");
}
- scanner->synctex = synctex;/* Now the scanner owns synctex */
- return scanner;
+ scanner->synctex = synctex;/* Now the scanner owns synctex */
+ SYNCTEX_FILE = file;
+ return parse? synctex_scanner_parse(scanner):scanner;
}
-/* Where the synctex scanner is created.
- * name is the full path of the uncompressed or compressed synctex file.
- * It is not the designated initializer because the scanner's core_path field is not initialized here.
- * On error, NULL is returned.
- * This can be due to allocation error, or an internal inconsistency (bad SYNCTEX_BUFFER_SIZE). */
-synctex_scanner_t synctex_scanner_new_with_contents_of_file(const char * name) {
- synctex_scanner_t scanner = NULL;
- synctex_status_t status = 0;
- /* We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */
- if(SYNCTEX_BUFFER_SIZE >= UINT_MAX) {
- fprintf(stderr,"SyncTeX BUG: Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (1)");
- return NULL;
+int __synctex_open(const char * output, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_modeRef);
+
+/* This functions opens the file at the "output" given location.
+ * It manages the problem of quoted filenames that appear with pdftex an 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.
+ * 0 on success, non 0 on error. */
+int __synctex_open(const char * output, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_modeRef) {
+# define synctex_name (*synctex_name_ref)
+# define the_file (*file_ref)
+# define io_mode (*io_modeRef)
+ if(synctex_name_ref && file_ref) {
+ char * quoteless = NULL;
+ const char * mode = synctex_io_modes[io_mode];
+ size_t size = 0;
+ /* 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, both suffices and 2 quotes,
+ * 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);
+ synctex_name = NULL;/* Don't forget to reinitialize. */
+ the_file = NULL; /* Here as well */
+ free(quoteless);
+ 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,&quoted,size) || (NULL == quoted)) {
+ /* There was an error or quoting does not make sense: */
+ goto return_on_error;
+ }
+ quoteless = synctex_name;
+ synctex_name = quoted;
+ }
+ /* Now add 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;
+ }
+ /* To quoteless as well. */
+ if(quoteless && (quoteless != strcat(quoteless,synctex_suffix))){
+ free(quoteless);
+ quoteless = 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 lever error, I can't do anything. */
+ _synctex_error("SyncTeX: could not open %s, error %i\n",synctex_name,errno);
+ goto return_on_error;
+ }
+ /* 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;
+ mode = synctex_io_modes[io_mode]; /* the file is a compressed and is a binary file, this caused errors on Windows */
+ /* To quoteless as well. */
+ if(quoteless && (quoteless != strcat(quoteless,synctex_suffix_gz))){
+ free(quoteless);
+ quoteless = 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 lever error, I can't do anything. */
+ _synctex_error("SyncTeX: 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) {
+ gzclose(the_file);
+ if(rename(synctex_name,quoteless)) {
+ _synctex_error("SyncTeX: could not rename %s to %s, error %i\n",synctex_name,quoteless,errno);
+ /* Reopen the file. */
+ if(NULL == (the_file = gzopen(synctex_name,mode))) {
+ /* Could not open this file */
+ if(errno != ENOENT) {
+ /* The file does exist, this is a lower lever error, I can't do anything. */
+ _synctex_error("SyncTeX: could not open again %s, error %i\n",synctex_name,errno);
+ }
+ goto return_on_error;
+ }
+ } else {
+ if(NULL == (the_file = gzopen(quoteless,mode))) {
+ /* Could not open this file */
+ if(errno != ENOENT) {
+ /* The file does exist, this is a lower lever error, I can't do anything. */
+ _synctex_error("SyncTeX: could not open renamed %s, error %i\n",quoteless,errno);
+ }
+ goto return_on_error;
+ }
+ /* The quote free file name should replace the old one:*/
+ free(synctex_name);
+ synctex_name = quoteless;
+ quoteless = NULL;
+ }
+ }
+ return 0;
}
- /* for integers: */
- if(SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE) {
- fprintf(stderr,"SyncTeX BUG: Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (2)");
- return NULL;
+ return 3; /* Bad parameter. */
+# undef synctex_name
+# undef the_file
+# undef io_mode
+}
+
+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);
+
+/* 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_modeRef) {
+# define synctex_name (*synctex_name_ref)
+# define the_file (*file_ref)
+ int result = __synctex_open(output,synctex_name_ref,file_ref,add_quotes,io_modeRef);
+ if((result || !*file_ref) && build_directory && strlen(build_directory)) {
+ char * build_output, *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;
+ 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)) {
+ return -4;
+ }
+ *(lpc+(build_output-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,"/")) {
+ return -2;
+ }
+ }
+ /* Append the last path component of the output. */
+ if(build_output != strcat(build_output,lpc)) {
+ return -3;
+ }
+ return __synctex_open(build_output,synctex_name_ref,file_ref,add_quotes,io_modeRef);
+ }
+ }
+ return -1;
}
- scanner = (synctex_scanner_t)_synctex_malloc(sizeof(_synctex_scanner_t));
+ return result;
+# undef synctex_name
+# undef the_file
+}
+
+/* The scanner destructor
+ */
+void synctex_scanner_free(synctex_scanner_t scanner) {
if(NULL == scanner) {
- fprintf(stderr,"SyncTeX: malloc problem");
- return NULL;
+ 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;
@@ -2626,6 +2733,8 @@ synctex_scanner_t synctex_scanner_new_with_contents_of_file(const char * name) {
* 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;
scanner->class[synctex_node_type_sheet] = synctex_class_sheet;
+ scanner->class[synctex_node_type_input] = synctex_class_input;
+ (scanner->class[synctex_node_type_input]).scanner = scanner;
(scanner->class[synctex_node_type_sheet]).scanner = scanner;
scanner->class[synctex_node_type_vbox] = synctex_class_vbox;
(scanner->class[synctex_node_type_vbox]).scanner = scanner;
@@ -2633,8 +2742,6 @@ synctex_scanner_t synctex_scanner_new_with_contents_of_file(const char * name) {
(scanner->class[synctex_node_type_void_vbox]).scanner = scanner;
scanner->class[synctex_node_type_hbox] = synctex_class_hbox;
(scanner->class[synctex_node_type_hbox]).scanner = scanner;
- scanner->class[synctex_node_type_hbox_non_void] = synctex_class_hbox;
- (scanner->class[synctex_node_type_hbox_non_void]).scanner = scanner;
scanner->class[synctex_node_type_void_hbox] = synctex_class_void_hbox;
(scanner->class[synctex_node_type_void_hbox]).scanner = scanner;
scanner->class[synctex_node_type_kern] = synctex_class_kern;
@@ -2643,48 +2750,39 @@ synctex_scanner_t synctex_scanner_new_with_contents_of_file(const char * name) {
(scanner->class[synctex_node_type_glue]).scanner = scanner;
scanner->class[synctex_node_type_math] = synctex_class_math;
(scanner->class[synctex_node_type_math]).scanner = scanner;
- scanner->class[synctex_node_type_input] = synctex_class_input;
- (scanner->class[synctex_node_type_input]).scanner = scanner;
- SYNCTEX_FILE = gzopen(name,"r");
- if(NULL == SYNCTEX_FILE) {
- if(errno != ENOENT) {
- fprintf(stderr,"SyncTeX: could not open %s, error %i\n",name,errno);
- }
-bail:
+ scanner->class[synctex_node_type_boundary] = synctex_class_boundary;
+ (scanner->class[synctex_node_type_boundary]).scanner = scanner;
+ SYNCTEX_START = (unsigned char *)malloc(SYNCTEX_BUFFER_SIZE+1); /* one more character for null termination */
+ if(NULL == SYNCTEX_START) {
+ _synctex_error("SyncTeX: malloc error");
synctex_scanner_free(scanner);
return NULL;
}
- SYNCTEX_START = (unsigned char *)malloc(SYNCTEX_BUFFER_SIZE+1); /* one more character for null termination */
- if(NULL == SYNCTEX_START) {
- fprintf(stderr,"SyncTeX: malloc error");
- gzclose(SYNCTEX_FILE);
- goto bail;
- }
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_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;
status = _synctex_scan_preamble(scanner);
if(status<SYNCTEX_STATUS_OK) {
- fprintf(stderr,"SyncTeX Error: Bad preamble\n");
+ _synctex_error("SyncTeX Error: Bad preamble\n");
bailey:
- gzclose(SYNCTEX_FILE);
- goto bail;
+ synctex_scanner_free(scanner);
+ return NULL;
}
status = _synctex_scan_content(scanner);
if(status<SYNCTEX_STATUS_OK) {
- fprintf(stderr,"SyncTeX Error: Bad content\n");
+ _synctex_error("SyncTeX Error: Bad content\n");
goto bailey;
}
- /* Everything is finished, free the buffer, close he file */
+ /* Everything is finished, free the buffer, close the file */
free((void *)SYNCTEX_START);
SYNCTEX_START = SYNCTEX_CUR = SYNCTEX_END = NULL;
gzclose(SYNCTEX_FILE);
SYNCTEX_FILE = NULL;
- /* Final tuning: set the default values for various parameters */
- /* 1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp
+ /* Final tuning: set the default values for various parameters */
+ /* 1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp
* 1 pt = 65536 sp */
if(scanner->pre_unit<=0) {
scanner->pre_unit = 8192;
@@ -2693,19 +2791,19 @@ bailey:
scanner->pre_magnification = 1000;
}
if(scanner->unit <= 0) {
- /* no post magnification */
- scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/
+ /* no post magnification */
+ scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/
} else {
- /* post magnification */
+ /* post magnification */
scanner->unit *= scanner->pre_unit / 65781.76;
}
scanner->unit *= scanner->pre_magnification / 1000.0;
if(scanner->x_offset > 6e23) {
- /* no post offset */
+ /* 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 */
+ /* post offset */
scanner->x_offset /= 65781.76f;
scanner->y_offset /= 65781.76f;
}
@@ -2713,22 +2811,6 @@ bailey:
#undef SYNCTEX_FILE
}
-/* The scanner destructor
- */
-void synctex_scanner_free(synctex_scanner_t scanner) {
- if(NULL == scanner) {
- return;
- }
- 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);
-}
-
/* Scanner accessors.
*/
int synctex_scanner_pre_x_offset(synctex_scanner_t scanner){
@@ -2794,20 +2876,69 @@ const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag) {
} 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);
+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((strlen(name) == strlen((SYNCTEX_NAME(input)))) &&
- (0 == strncmp(name,(SYNCTEX_NAME(input)),strlen(name)))) {
+ if(_synctex_is_equivalent_file_name(name,(SYNCTEX_NAME(input)))) {
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(0<char_index) {
+ char_index -= 1;
+ if(SYNCTEX_IS_PATH_SEPARATOR(name[char_index])
+ && (result = _synctex_scanner_get_tag(scanner,name+char_index+1))) {
+ return result;
+ }
+ }
+ }
+ }
+ return result;
+ }
+ }
+ return 0;
+}
synctex_node_t synctex_scanner_input(synctex_scanner_t scanner) {
return scanner?scanner->input:NULL;
}
@@ -2824,88 +2955,88 @@ const char * synctex_scanner_get_synctex(synctex_scanner_t scanner) {
# pragma mark -
# pragma mark Public node attributes
# endif
-float synctex_node_h(synctex_node_t node){
+int synctex_node_h(synctex_node_t node){
if(!node) {
return 0;
}
- return (float)SYNCTEX_HORIZ(node);
+ return SYNCTEX_HORIZ(node);
}
-float synctex_node_v(synctex_node_t node){
+int synctex_node_v(synctex_node_t node){
if(!node) {
return 0;
}
- return (float)SYNCTEX_VERT(node);
+ return SYNCTEX_VERT(node);
}
-float synctex_node_width(synctex_node_t node){
+int synctex_node_width(synctex_node_t node){
if(!node) {
return 0;
}
- return (float)SYNCTEX_WIDTH(node);
+ return SYNCTEX_WIDTH(node);
}
-float synctex_node_box_h(synctex_node_t node){
+int synctex_node_box_h(synctex_node_t node){
if(!node) {
return 0;
}
- if((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_hbox_non_void)
- && (node->class->type != synctex_node_type_void_hbox)) {
- node = SYNCTEX_PARENT(node);
+ 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 (node->class->type == synctex_node_type_sheet)?0:(float)(SYNCTEX_HORIZ(node));
+ return 0;
}
-float synctex_node_box_v(synctex_node_t node){
+int synctex_node_box_v(synctex_node_t node){
if(!node) {
return 0;
}
- if((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_hbox_non_void)
- && (node->class->type != synctex_node_type_void_hbox)) {
- node = SYNCTEX_PARENT(node);
+ 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 (node->class->type == synctex_node_type_sheet)?0:(float)(SYNCTEX_VERT(node));
+ return 0;
}
-float synctex_node_box_width(synctex_node_t node){
+int synctex_node_box_width(synctex_node_t node){
if(!node) {
return 0;
}
- if((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_hbox_non_void)
- && (node->class->type != synctex_node_type_void_hbox)) {
- node = SYNCTEX_PARENT(node);
+ 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 (node->class->type == synctex_node_type_sheet)?0:(float)(SYNCTEX_WIDTH(node));
+ return 0;
}
-float synctex_node_box_height(synctex_node_t node){
+int synctex_node_box_height(synctex_node_t node){
if(!node) {
return 0;
}
- if((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_hbox_non_void)
- && (node->class->type != synctex_node_type_void_hbox)) {
- node = SYNCTEX_PARENT(node);
+ if(SYNCTEX_IS_BOX(node)) {
+result:
+ return SYNCTEX_HEIGHT(node);
}
- return (node->class->type == synctex_node_type_sheet)?0:(float)(SYNCTEX_HEIGHT(node));
+ if((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
+ goto result;
+ }
+ return 0;
}
-float synctex_node_box_depth(synctex_node_t node){
+int synctex_node_box_depth(synctex_node_t node){
if(!node) {
return 0;
}
- if((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_hbox_non_void)
- && (node->class->type != synctex_node_type_void_hbox)) {
- node = SYNCTEX_PARENT(node);
+ if(SYNCTEX_IS_BOX(node)) {
+result:
+ return SYNCTEX_DEPTH(node);
}
- return (node->class->type == synctex_node_type_sheet)?0:(float)(SYNCTEX_DEPTH(node));
+ if((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
+ goto result;
+ }
+ return 0;
}
# ifdef SYNCTEX_NOTHING
# pragma mark -
@@ -2933,119 +3064,91 @@ float synctex_node_box_visible_h(synctex_node_t node){
if(!node) {
return 0;
}
- if((node->class->type == synctex_node_type_vbox)
- || (node->class->type == synctex_node_type_void_hbox)
- || (node->class->type == synctex_node_type_void_vbox)) {
+ 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_WIDTH(node)<0?
- (SYNCTEX_HORIZ(node)+SYNCTEX_WIDTH(node))*node->class->scanner->unit+node->class->scanner->x_offset:
- SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset;
- }
- if(node->class->type != synctex_node_type_hbox
- && node->class->type != synctex_node_type_hbox_non_void) {
- node = SYNCTEX_PARENT(node);
+ return SYNCTEX_HORIZ_V(node)*node->class->scanner->unit+node->class->scanner->x_offset;
}
- if(node->class->type == synctex_node_type_sheet) {
- return 0;
- }
- if(node->class->type == synctex_node_type_vbox) {
+ if((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
goto result;
}
- return SYNCTEX_INFO(node)[SYNCTEX_WIDTH_V_IDX].INT<0?
- (SYNCTEX_INFO(node)[SYNCTEX_HORIZ_V_IDX].INT+SYNCTEX_INFO(node)[SYNCTEX_WIDTH_V_IDX].INT)*node->class->scanner->unit+node->class->scanner->x_offset:
- SYNCTEX_INFO(node)[SYNCTEX_HORIZ_V_IDX].INT*node->class->scanner->unit+node->class->scanner->x_offset;
+ return 0;
}
float synctex_node_box_visible_v(synctex_node_t node){
if(!node) {
return 0;
}
- if((node->class->type == synctex_node_type_vbox)
- || (node->class->type == synctex_node_type_void_hbox)
- || (node->class->type == synctex_node_type_void_vbox)) {
+ 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->x_offset;
+ case synctex_node_type_hbox:
result:
- return (float)(SYNCTEX_VERT(node))*node->class->scanner->unit+node->class->scanner->y_offset;
- }
- if(node->class->type != synctex_node_type_hbox
- && node->class->type != synctex_node_type_hbox_non_void) {
- node = SYNCTEX_PARENT(node);
+ return SYNCTEX_VERT_V(node)*node->class->scanner->unit+node->class->scanner->x_offset;
}
- if(node->class->type == synctex_node_type_sheet) {
- return 0;
- }
- if(node->class->type == synctex_node_type_vbox) {
+ if((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
goto result;
}
- return SYNCTEX_INFO(node)[SYNCTEX_VERT_V_IDX].INT*node->class->scanner->unit+node->class->scanner->y_offset;
+ return 0;
}
float synctex_node_box_visible_width(synctex_node_t node){
if(!node) {
return 0;
}
- if((node->class->type == synctex_node_type_vbox)
- || (node->class->type == synctex_node_type_void_hbox)
- || (node->class->type == synctex_node_type_void_vbox)) {
+ 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(node)<0?
- -SYNCTEX_WIDTH(node)*node->class->scanner->unit:
- SYNCTEX_WIDTH(node)*node->class->scanner->unit;
+ return SYNCTEX_WIDTH_V(node)*node->class->scanner->unit;
}
- if(node->class->type != synctex_node_type_hbox
- && node->class->type != synctex_node_type_hbox_non_void) {
- node = SYNCTEX_PARENT(node);
- }
- if(node->class->type == synctex_node_type_sheet) {
- return 0;
- }
- if(node->class->type == synctex_node_type_vbox) {
+ if((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
goto result;
}
- return SYNCTEX_INFO(node)[SYNCTEX_WIDTH_V_IDX].INT<0?
- -SYNCTEX_INFO(node)[SYNCTEX_WIDTH_V_IDX].INT*node->class->scanner->unit:
- SYNCTEX_INFO(node)[SYNCTEX_WIDTH_V_IDX].INT*node->class->scanner->unit;
+ return 0;
}
float synctex_node_box_visible_height(synctex_node_t node){
if(!node) {
return 0;
}
- if((node->class->type == synctex_node_type_vbox)
- || (node->class->type == synctex_node_type_void_hbox)
- || (node->class->type == synctex_node_type_void_vbox)) {
+ 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 (float)(SYNCTEX_HEIGHT(node))*node->class->scanner->unit;
+ return SYNCTEX_HEIGHT_V(node)*node->class->scanner->unit;
}
- if(node->class->type != synctex_node_type_hbox
- && node->class->type != synctex_node_type_hbox_non_void) {
- node = SYNCTEX_PARENT(node);
- }
- if(node->class->type == synctex_node_type_sheet) {
- return 0;
- }
- if(node->class->type == synctex_node_type_vbox) {
+ if((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
goto result;
}
- return SYNCTEX_INFO(node)[SYNCTEX_HEIGHT_V_IDX].INT*node->class->scanner->unit;
+ return 0;
}
float synctex_node_box_visible_depth(synctex_node_t node){
if(!node) {
return 0;
}
- if((node->class->type == synctex_node_type_vbox)
- || (node->class->type == synctex_node_type_void_hbox)
- || (node->class->type == synctex_node_type_void_vbox)) {
+ 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 (float)(SYNCTEX_DEPTH(node))*node->class->scanner->unit;
+ return SYNCTEX_DEPTH_V(node)*node->class->scanner->unit;
}
- if(node->class->type != synctex_node_type_hbox
- && node->class->type != synctex_node_type_hbox_non_void) {
- node = SYNCTEX_PARENT(node);
- }
- if(node->class->type == synctex_node_type_sheet) {
- return 0;
- }
- if(node->class->type == synctex_node_type_vbox) {
+ if((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
goto result;
}
- return SYNCTEX_INFO(node)[SYNCTEX_DEPTH_V_IDX].INT*node->class->scanner->unit;
+ return 0;
}
# ifdef SYNCTEX_NOTHING
# pragma mark -
@@ -3081,7 +3184,7 @@ int synctex_node_column(synctex_node_t node) {
}
# ifdef SYNCTEX_NOTHING
# pragma mark -
-# pragma mark Query
+# pragma mark Sheet
# endif
synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page) {
@@ -3102,10 +3205,6 @@ synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page) {
# pragma mark Query
# endif
-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);
-
int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column) {
# ifdef __DARWIN_UNIX03
# pragma unused(column)
@@ -3113,6 +3212,7 @@ int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,i
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);
@@ -3120,430 +3220,838 @@ int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,i
}
free(SYNCTEX_START);
SYNCTEX_CUR = SYNCTEX_END = SYNCTEX_START = NULL;
- friend_index = (tag+line)%(scanner->number_of_lists);
- node = (scanner->lists_of_friends)[friend_index];
- while(node) {
- 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);
- }
- node = SYNCTEX_FRIEND(node);
- }
- SYNCTEX_END = SYNCTEX_CUR;
- SYNCTEX_CUR = NULL;
- return SYNCTEX_END-SYNCTEX_START;
-}
-
-inline static synctex_node_t _synctex_best_child_node(synctex_node_t node,int H,int V, int * distanceRef);
-inline static synctex_node_t _synctex_best_child_node(synctex_node_t node,int H,int V, int * distanceRef) {
- if(NULL != distanceRef) {
- synctex_node_t child = NULL;
- switch((node->class)->type) {
- case synctex_node_type_hbox_non_void:
- if((child = SYNCTEX_CHILD(node))) {
- synctex_node_t result = NULL;
- do {
- synctex_node_t candidate = NULL;
- if((candidate = _synctex_best_child_node(child,H,V,distanceRef))) {
- if(0 == *distanceRef) {
- /* We can't do better */
- return candidate;
- }
- result = candidate;
- }
- } while((child = SYNCTEX_SIBLING(child)));
- return result;
- } else {
- /* this is an error if this box does not contain children. */
- fprintf(stderr,
- "SyncTeX internal inconsistency: we should not get there (synctex_best_child_node:%i), please report bug to the SyncTeX maintainer\n",
- (node->class)->type);
- return NULL;
+ max_line = line < INT_MAX-scanner->number_of_lists ? line+scanner->number_of_lists:INT_MAX;
+ while(line<max_line) {
+ /* This loop will only be performed once for advanced viewers */
+ friend_index = (tag+line)%(scanner->number_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);
}
- case synctex_node_type_hbox:
- case synctex_node_type_vbox:
- /* This is a box that contains children but no kern, math or glue nodes. */
- if((child = SYNCTEX_CHILD(node))) {
- synctex_node_t result = NULL;
+ } 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 {
- synctex_node_t candidate = NULL;
- if((candidate = _synctex_best_child_node(child,H,V,distanceRef))) {
- if(0 == *distanceRef) {
- /* We can't do better */
- return candidate;
- }
- result = candidate;
- }
- } while((child = SYNCTEX_SIBLING(child)));
- return result;
- } else {
- /* If the hit point is inside the box, we must return a node inside the box */
- int min = SYNCTEX_HORIZ_V(node);
- int max = min+SYNCTEX_WIDTH_V(node);
- if(min<=H && H<=max) {
- min = SYNCTEX_VERT_V(node);
- max = min + SYNCTEX_DEPTH_V(node);
- min -= SYNCTEX_HEIGHT_V(node);
- if(min<=V && V<=max) {
- /* The hit point and the result are in the same box, we can't do better */
- *distanceRef = 0;/* no one else will ever try to do better */
- return node;
+ 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);
}
- }
- return NULL;
+ } while((node = SYNCTEX_FRIEND(node)));
}
- case synctex_node_type_void_hbox:
- case synctex_node_type_void_vbox:
- /* Both boxes does not contain any material, they only contribute to SyncTeX by their line number. */
- return NULL;
- default:
+ }
+ SYNCTEX_END = SYNCTEX_CUR;
+ /* Now reverse the order to have nodes in display order, and keep just a few nodes */
+ if((SYNCTEX_START) && (SYNCTEX_END))
{
- int i = SYNCTEX_HORIZ(node);
- int distance = i>H?i-H:H-i;
- i = SYNCTEX_VERT(node);
- distance += i>V?i-V:V-i;
- if(distance<*distanceRef) {
- *distanceRef = distance;
- return node;
+ synctex_node_t * start_ref = (synctex_node_t *)SYNCTEX_START;
+ synctex_node_t * end_ref = (synctex_node_t *)SYNCTEX_END;
+ end_ref -= 1;
+ while(start_ref < end_ref) {
+ node = *start_ref;
+ *start_ref = *end_ref;
+ *end_ref = node;
+ start_ref += 1;
+ end_ref -= 1;
+ }
+ /* Basically, we keep the first node for each parent.
+ * More precisely, we keep only nodes that are not descendants 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;
}
- return NULL;
+ start_ref += 1;
+ SYNCTEX_END = (unsigned char *)start_ref;
}
- }
+ SYNCTEX_CUR = NULL;
+ return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
+ }
+# if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__)
+ break;
+# else
+ ++line;
+# endif
}
- return NULL;
+ return 0;
}
-/* The best container is the deeper box that contains the given point.
- * We traverse the node tree in a deep first manner and stop as soon as a resutl is found. */
-inline static synctex_node_t _synctex_best_container(synctex_node_t node,int H,int V);
-inline static synctex_node_t _synctex_best_container(synctex_node_t node,int H,int V) {
- int min, max;
- synctex_node_t child = NULL;
- synctex_node_t result = NULL;
- switch(node->class->type) {
- case synctex_node_type_hbox:
- case synctex_node_type_vbox:
- case synctex_node_type_hbox_non_void:
- max = SYNCTEX_WIDTH_V(node);
- if(max<0) {
- min = max;
- max = SYNCTEX_HORIZ_V(node);
- min += max;
- } else {
- min = SYNCTEX_HORIZ_V(node);
- max += min;
- }
- if(min<=H && H<=max) {
- child = node;
- while((child = SYNCTEX_CHILD(child))) {
- if((result = _synctex_best_container(child,H,V))) {
- return result;
- }
- }
- min = SYNCTEX_VERT_V(node);
- max = min + SYNCTEX_DEPTH_V(node);
- min -= SYNCTEX_HEIGHT_V(node);
- if(min<=V && V<=max) {
- /* The hit point and the result are in the same box, we can't do better */
- return node;
- }
- }
+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<SYNCTEX_END) {
+ return *(synctex_node_t*)SYNCTEX_CUR;
+ } else {
+ return NULL;
}
- return NULL;
}
+/* This struct records a point in TeX coordinates.*/
+typedef struct {
+ int h;
+ int v;
+} synctex_point_t;
+
+/* This struct records distances, the left one is positive or 0 and the right one is negative or 0.
+ * When comparing the locations of 2 different graphical objects on the page, we will have to also record the
+ * horizontal distance as signed to keep track of the typesetting order.*/
+typedef struct {
+ int left;
+ int right;
+} synctex_distances_t;
+
+typedef struct {
+ synctex_point_t left;
+ synctex_point_t right;
+} synctex_offsets_t;
+
+
+typedef struct {
+ synctex_node_t left;
+ synctex_node_t right;
+} synctex_node_set_t;
+
+/* The smallest container between two has the smallest width or height.
+ * This comparison is used when there are 2 overlapping boxes that contain the hit point.
+ * For ConTeXt, the problem appears at each page.
+ * The chosen box is the one with the smallest height, then the smallest width. */
+SYNCTEX_INLINE static synctex_node_t _synctex_smallest_container(synctex_node_t node, synctex_node_t other_node);
+
+/* Returns the distance between the hit point hitPoint=(H,V) and the given node. */
+synctex_bool_t _synctex_point_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible);
+int _synctex_node_distance_to_point(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible);
+
+/* The best container is the deeper box that contains the hit point (H,V).
+ * _synctex_eq_deepest_container starts with node whereas
+ * _synctex_box_child_deepest starts with node's children, if any
+ * if node is not a box, or a void box, NULL is returned.
+ * We traverse the node tree in a deep first manner and stop as soon as a result is found. */
+static synctex_node_t _synctex_eq_deepest_container(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible);
+
+/* Once a best container is found, the closest children are the closest nodes to the left or right of the hit point.
+ * Only horizontal and vertical offsets are used to compare the positions of the nodes. */
+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);
+
+/* The closest container is the box that is the one closest to the given point.
+ * The "visible" version takes into account the visible dimensions instead of the real ones given by TeX. */
+SYNCTEX_INLINE static synctex_node_t _synctex_eq_closest_child(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible);
+
+#define SYNCTEX_MASK_LEFT 1
+#define SYNCTEX_MASK_RIGHT 2
+
int synctex_edit_query(synctex_scanner_t scanner,int page,float h,float v) {
synctex_node_t sheet = NULL;
- synctex_node_t node = NULL;
- synctex_node_t best_node = NULL;
- synctex_node_t best_container = NULL;
- int H,V;
- int minH,maxH,minV,maxV;
- int best_distance,distance;
- if(NULL == scanner || 0 == scanner->unit) {
+ synctex_node_t node = NULL; /* placeholder */
+ synctex_node_t other_node = NULL; /* placeholder */
+ synctex_point_t hitPoint = {0,0}; /* placeholder */
+ synctex_node_set_t bestNodes = {NULL,NULL}; /* holds the best node */
+ synctex_distances_t bestDistances = {INT_MAX,INT_MAX};
+ synctex_node_t bestContainer = NULL; /* placeholder */
+ if(NULL == (scanner = synctex_scanner_parse(scanner)) || 0 >= scanner->unit) {/* scanner->unit must be >0 */
return 0;
}
- /* Convert the given point to scanner integer coordinates */
- H = (h-scanner->x_offset)/scanner->unit;
- V = (v-scanner->y_offset)/scanner->unit;
+ /* 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 */
+ /* Find the proper sheet */
sheet = scanner->sheet;
- while(sheet != NULL && SYNCTEX_PAGE(sheet) != page) {
+ 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 */
- /* try to find the box closest to the hit point (H,V) */
- /* We initialize the values with the next box of the sheet. */
- node = SYNCTEX_NEXT_BOX(sheet);
- if(NULL == node) {
- /* This is a very weird situation where there are no kern, math or glue nodes.
- * Ignore this, for the moment. */
- return 0;
- }
- /* 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. */
- /* In order to gain speed, we have made a linked list of all the box nodes that contain either kern, glue or math node.
- * These kind of boxes are expected to represent the vast majority of boxes.
- * It was created while parsing the sheet content, and the boxes are ordered from deeper to lower. */
- /* min? and max? are the coordinates of the box. */
-next_box:
- /* getting the box bounds, taking into account negative widths. */
- maxH = SYNCTEX_WIDTH_V(node);
- if(maxH<0) {
- minH = maxH;
- maxH = SYNCTEX_HORIZ_V(node);
- minH += maxH;
- } else {
- minH = SYNCTEX_HORIZ_V(node);
- maxH += minH;
- }
- minV = SYNCTEX_VERT_V(node);
- maxV = minV + SYNCTEX_DEPTH_V(node);
- minV -= SYNCTEX_HEIGHT_V(node);
- /* In what region is the point P=(H,V) ? */
- if(V<minV) {
- if(H<minH) {
- /* This is region 1. The distance to the box is the L1 distance PA. */
- best_distance = minV - V + minH - H;/* Integer overflow? probability epsilon */
- } else if(H<=maxH) {
- /* This is region 2. The distance to the box is the geometrical distance to the top edge. */
- best_distance = minV - V;
- } else {
- /* This is region 3. The distance to the box is the L1 distance PB. */
- best_distance = minV - V + H - maxH;
- }
- } else if(V<=maxV) {
- if(H<minH) {
- /* This is region 4. The distance to the box is the geometrical distance to the left edge. */
- best_distance = minH - H;
- } else if(H<=maxH) {
- /* This is region 4. We are inside the box. */
- best_distance = 0;
- } else {
- /* This is region 6. The distance to the box is the geometrical distance to the right edge. */
- best_distance = H - maxH;
- }
- } else {
- if(H<minH) {
- /* This is region 7. The distance to the box is the L1 distance PC. */
- best_distance = V - maxV + minH - H;
- } else if(H<=maxH) {
- /* This is region 8. The distance to the box is the geometrical distance to the top edge. */
- best_distance = V - maxV;
- } else {
- /* This is region 9. The distance to the box is the L1 distance PD. */
- best_distance = V - maxV + H - maxH;
- }
- }
- best_node = node;
- /* Is best_node a box containing the hit point? */
- if(best_distance==0) {
- if((best_container = _synctex_best_container(best_node,H,V)) && (best_container != best_node)) {
- /* We have found a box that contains the hit point, as a descendant of best_node.
- * best_container is a box that contains no kern, math and glue nodes,
- * otherwise, it would be located in the linked list of such boxes, before its ancestor best_node
- * and it would have been laready caught.
- * In mathematical formulas, there are such boxes because there is not enough material to add glue or kern. */
- if((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) {
- * (synctex_node_t *)SYNCTEX_START = best_container;
- SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t);
- SYNCTEX_CUR = NULL;
- return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
- } else {
+ /* 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_HORIZ_BOX(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_HORIZ_BOX(node))) {
+ do {
+ if(_synctex_point_in_box(hitPoint,other_node,synctex_YES)) {
+ node = _synctex_smallest_container(other_node,node);
+ }
+ } while((other_node = SYNCTEX_NEXT_HORIZ_BOX(other_node)));
+ }
+ 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_HORIZ_BOX(node)));
+ }
+ /* 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<min) {
+ return min - hitPoint.h; /* regions 1+4+7, result is > 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<min) {
+ return min - hitPoint.h; /* regions 1+4+7, result is > 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<<<<med<<<<max
+ * .................................
+ * Actually, we do not take into account negative widths.
+ * There is a problem for such situation when there is efectively overlapping text.
+ * But this should be extremely rare. I guess that in that case, many different choices
+ * could be made, one being in contradiction of the other.
+ * It means that the best choice should be made according to the situation that occurs
+ * most frequently.
+ */
+ if(hitPoint.h<min) {
+ return min - hitPoint.h + 1; /* penalty to ensure other nodes are chosen first in case of overlapping ones */
+ } else if (hitPoint.h>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;
}
- /* Then we try to find what is the best child node inside the box best_node,
- * which means the node closest to the hit point.*/
- distance = INT_MAX;
- if(node = _synctex_best_child_node(best_node,H,V,&distance)) {
- if((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) {
- * (synctex_node_t *)SYNCTEX_START = node;
- SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t);
- SYNCTEX_CUR = NULL;
- return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
- } else {
- return SYNCTEX_STATUS_ERROR;
- }
+ }
+ 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<min) {
+ return min - hitPoint.v; /* regions 1+2+3, result is > 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<min) {
+ return min - hitPoint.v; /* regions 1+2+3, result is > 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;
}
- /* We could not find a best node closest to the hit point.
- * This is unreachable code because all the boxes here are non void boxes. */
- if((node = SYNCTEX_NEXT_BOX(best_node))) {
- goto next_box;
- } else {
- return 0;
- }
- }
- node = best_node;
- /* Now we have best_distance>0
- * We continue through the non void box list until we find the box closest to the hit point */
- while(node = SYNCTEX_NEXT_BOX(node)) {
- maxH = SYNCTEX_WIDTH_V(node);
- if(maxH<0) {
- minH = maxH;
- maxH = SYNCTEX_HORIZ_V(node);
- minH += maxH;
- } else {
- minH = SYNCTEX_HORIZ_V(node);
- maxH += minH;
- }
- minV = SYNCTEX_VERT_V(node);
- maxV = minV + SYNCTEX_DEPTH_V(node);
- minV -= SYNCTEX_HEIGHT_V(node);
- if(V<minV) {
- if(H<minH) {
- /* This is region 1. The distance to the box is the L1 distance PA. */
- distance = minV - V + minH - H;/* Integer overflow? probability epsilon */
- } else if(H<=maxH) {
- /* This is region 2. The distance to the box is the geometrical distance to the top edge. */
- distance = minV - V;
- } else {
- /* This is region 3. The distance to the box is the L1 distance PB. */
- distance = minV - V + H - maxH;
- }
- } else if(V<=maxV) {
- if(H<minH) {
- /* This is region 4. The distance to the box is the geometrical distance to the left edge. */
- distance = minH - H;
- } else if(H<=maxH) {
- /* This is region 4. We are inside the box. */
- distance = 0;
- } else {
- /* This is region 6. The distance to the box is the geometrical distance to the right edge. */
- distance = H - maxH;
- }
- } else {
- if(H<minH) {
- /* This is region 7. The distance to the box is the L1 distance PC. */
- distance = V - maxV + minH - H;
- } else if(H<=maxH) {
- /* This is region 8. The distance to the box is the geometrical distance to the top edge. */
- distance = V - maxV;
- } else {
- /* This is region 9. The distance to the box is the L1 distance PD. */
- distance = V - maxV + H - maxH;
- }
+ }
+ 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_WIDTH(node)<SYNCTEX_WIDTH(other_node)) {
+ return node;
+ }
+ if(SYNCTEX_WIDTH(node)>SYNCTEX_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(height<other_height) {
+ return node;
+ }
+ if(height>other_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;
}
- if(distance>0) {
- /* This box does not contain the hit point */
- if(distance<best_distance) {
- /* but it is closer */
- best_distance = distance;
- best_node = node;
- }
- } else {
- /* This box contains the hit point */
- best_node = node;
- /* Is ther a better container, that was not a non void box?*/
- if((best_container = _synctex_best_container(node,H,V)) && (best_container != best_node)) {
- /* the answer is yes */
- if((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) {
- * (synctex_node_t *)SYNCTEX_START = best_container;
- SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t);
- SYNCTEX_CUR = NULL;
- return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
+ }
+ 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.v<minV) {
+ if(hitPoint.h<minH) {
+ /* This is region 1. The distance to the box is the L1 distance PA. */
+ result = minV - hitPoint.v + minH - hitPoint.h;/* Integer overflow? probability epsilon */
+ } else if(hitPoint.h<=maxH) {
+ /* This is region 2. The distance to the box is the geometrical distance to the top edge. */
+ result = minV - hitPoint.v;
+ } else {
+ /* This is region 3. The distance to the box is the L1 distance PB. */
+ result = minV - hitPoint.v + hitPoint.h - maxH;
+ }
+ } else if(hitPoint.v<=maxV) {
+ if(hitPoint.h<minH) {
+ /* This is region 4. The distance to the box is the geometrical distance to the left edge. */
+ result = minH - hitPoint.h;
+ } else if(hitPoint.h<=maxH) {
+ /* This is region 4. We are inside the box. */
+ result = 0;
+ } else {
+ /* This is region 6. The distance to the box is the geometrical distance to the right edge. */
+ result = hitPoint.h - maxH;
+ }
} else {
- return SYNCTEX_STATUS_ERROR;
+ if(hitPoint.h<minH) {
+ /* This is region 7. The distance to the box is the L1 distance PC. */
+ result = hitPoint.v - maxV + minH - hitPoint.h;
+ } else if(hitPoint.h<=maxH) {
+ /* This is region 8. The distance to the box is the geometrical distance to the top edge. */
+ result = hitPoint.v - maxV;
+ } else {
+ /* This is region 9. The distance to the box is the L1 distance PD. */
+ result = hitPoint.v - maxV + hitPoint.h - maxH;
+ }
}
- }
- /* the best_node is also the best_container, just find the closest child node. */
- distance = INT_MAX;
- if(best_node = _synctex_best_child_node(best_node,H,V,&distance)) {
- if((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) {
- * (synctex_node_t *)SYNCTEX_START = best_node;
- SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t);
- SYNCTEX_CUR = NULL;
- return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
+ break;
+ case synctex_node_type_kern:
+ maxH = SYNCTEX_WIDTH(node);
+ if(maxH<0) {
+ minH = SYNCTEX_HORIZ(node);
+ maxH = minH - maxH;
+ } else {
+ minH = -maxH;
+ maxH = SYNCTEX_HORIZ(node);
+ minH += maxH;
+ }
+ minV = SYNCTEX_VERT(node);
+ if(hitPoint.h<minH) {
+ if(hitPoint.v>minV) {
+ 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.h<minH) {
+ if(hitPoint.v>minV) {
+ 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 {
- return SYNCTEX_STATUS_ERROR;
+ 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)) {
+ if(node && (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) {
+ 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;
+ }
}
}
- /* We should have stopped here because _synctex_best_child_node always returns something for non void boxes. */
- }
- }
- /* Bad luck, no non void box does contain the hit point, we have to work harder.
- * We start from the top (the sheet's child) and try to find a box that contains the hit point.
- * It is a bit long but it should occur only seldomly. */
- if((node = SYNCTEX_CHILD(sheet)) && (best_container = _synctex_best_container(node,H,V)) && (best_container != best_node)) {
- /* in fact, we always have best_container != best_node, because the former contains the hit point, but not the latter.
- * At that point, we are sure that the distance between the hit point and the best_node is positive. */
- if((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) {
- * (synctex_node_t *)SYNCTEX_START = best_container;
- SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t);
- SYNCTEX_CUR = NULL;
- return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
- } else {
- return SYNCTEX_STATUS_ERROR;
+ } 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;
+ }
}
}
- /* Last chance, return the best_node or its best child. */
- if(best_node) {
- distance = INT_MAX;
- if((node = _synctex_best_child_node(best_node,H,V,&distance))) {
- best_node = 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((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) {
- * (synctex_node_t *)SYNCTEX_START = best_node;
- SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t);
- SYNCTEX_CUR = NULL;
- return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
- } else {
- return SYNCTEX_STATUS_ERROR;
+ 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_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<SYNCTEX_END) {
- return *(synctex_node_t*)SYNCTEX_CUR;
- } else {
- return NULL;
+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;
}
-
-int synctex_bail(void) {
- fprintf(stderr,"SyncTeX ERROR\n");
- return -1;
+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 ===== updater
+# pragma mark -
+# pragma mark Updater
# endif
-typedef int (*synctex_fprintf_t)(void *, const char * , ...); /* print formatted to either FILE * or gzFile */
+typedef int (*synctex_fprintf_t)(void *, const char * , ...); /* print formatted to either FILE * or gzFile */
# define SYNCTEX_BITS_PER_BYTE 8
@@ -3553,86 +4061,56 @@ struct __synctex_updater_t {
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 */
+ 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))
-# define SYNCTEX_YES (-1)
-# define SYNCTEX_NO (0)
-
-synctex_updater_t synctex_updater_new_with_output_file(const char * output);
-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);
-void synctex_updater_free(synctex_updater_t updater);
-synctex_updater_t synctex_updater_new_with_output_file(const char * output){
+synctex_updater_t synctex_updater_new_with_output_file(const char * output, const char * build_directory) {
synctex_updater_t updater = NULL;
char * synctex = NULL;
size_t size = 0;
- /* prepare the updater */
+ synctex_io_mode_t io_mode = synctex_io_mode_read;
+ const char * mode;
+ /* prepare the updater */
updater = (synctex_updater_t)_synctex_malloc(sizeof(synctex_updater_t));
if(NULL == updater) {
- fprintf(stderr,"! synctex_updater_new_with_file: malloc problem");
+ _synctex_error("! synctex_updater_new_with_file: malloc problem");
return NULL;
}
- size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1;
- synctex = (char *)malloc(size);
- if(NULL == synctex) {
- fprintf(stderr,"! synctex_updater_new_with_output_file: Memory problem (1)\n");
-return_on_error1:
+ if(_synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_NO,&io_mode)
+ && _synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_YES,&io_mode)) {
+return_on_error:
free(updater);
return NULL;
}
- /* we have reserved for synctex enough memory to copy output and both suffices,
- * including the terminating character */
- if(synctex != strcpy(synctex,output)) {
- fprintf(stderr,"! synctex_updater_new_with_output_file: Copy problem\n");
-return_on_error2:
- free(synctex);
- goto return_on_error1;
- }
- /* remove the last path extension if any */
- synctex_strip_last_path_extension(synctex);
- /* append the synctex suffix */
- if(synctex != strcat(synctex,synctex_suffix)){
- fprintf(stderr,"! synctex_scanner_new_with_output_file: Concatenation problem (can't add suffix '%s')\n",synctex_suffix);
- goto return_on_error2;
- }
- if(NULL != (SYNCTEX_FILE = fopen(synctex,"r"))){
- /* OK, the file exists */
- fclose(SYNCTEX_FILE);
- if(NULL == (SYNCTEX_FILE = (void *)fopen(synctex,"a"))) {
+ /* OK, the file exists */
+ gzclose(SYNCTEX_FILE);
+ SYNCTEX_FILE = NULL;
+ SYNCTEX_NO_GZ = io_mode%2?synctex_NO:synctex_YES;
+ mode = synctex_io_modes[io_mode+synctex_io_mode_append];/* either "a" or "ab", depending on the file extension */
+ if(SYNCTEX_NO_GZ) {
+ if(NULL == (SYNCTEX_FILE = (void *)fopen(synctex,mode))) {
no_write_error:
- fprintf(stderr,"! synctex_updater_new_with_file: Can't append to %s",synctex);
- goto return_on_error2;
+ _synctex_error("! synctex_updater_new_with_file: Can't append to %s",synctex);
+ free(synctex);
+ goto return_on_error;
}
- SYNCTEX_NO_GZ = SYNCTEX_YES;
updater->fprintf = (synctex_fprintf_t)(&fprintf);
-return_updater:
- printf("SyncTeX: updating %s...",synctex);
- free(synctex);
- return updater;
- }
- /* append the gz suffix */
- if(synctex != strcat(synctex,synctex_suffix_gz)){
- fprintf(stderr,"! synctex_scanner_new_with_output_file: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz);
- goto return_on_error2;
- }
- if(NULL != (SYNCTEX_FILE = gzopen(synctex,"r"))){
- gzclose(SYNCTEX_FILE);
- if(NULL == (SYNCTEX_FILE = gzopen(synctex,"a"))) {
+ } else {
+ if(NULL == (SYNCTEX_FILE = (void *)gzopen(synctex,mode))) {
goto no_write_error;
}
- SYNCTEX_NO_GZ = SYNCTEX_NO;
updater->fprintf = (synctex_fprintf_t)(&gzprintf);
- goto return_updater;
}
- goto return_on_error2;
+ printf("SyncTeX: updating %s...",synctex);
+ free(synctex);
+ return updater;
}
+
void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification){
if(NULL==updater) {
return;
@@ -3676,5 +4154,3 @@ void synctex_updater_free(synctex_updater_t updater){
printf("... done.\n");
return;
}
-
-