File indexing completed on 2024-05-12 04:33:36

0001 /*
0002     SPDX-FileCopyrightText: 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr
0003     SPDX-License-Identifier: X11
0004 
0005     This file is part of the __SyncTeX__ package.
0006 
0007     [//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017)
0008     [//]: # (Version: 1.19)
0009 
0010     See `synctex_parser_readme.md` for more details
0011 
0012     Acknowledgments:
0013     ----------------
0014     The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh,
0015     and significant help from XeTeX developer Jonathan Kew
0016 
0017     Nota Bene:
0018     ----------
0019     If you include or use a significant part of the synctex package into a software,
0020     I would appreciate to be listed as contributor and see "SyncTeX" highlighted.
0021 */
0022 
0023 /*  We assume that high level application like pdf viewers will want
0024  *  to embed this code as is. We assume that they also have locale.h and setlocale.
0025  *  For other tools such as TeXLive tools, you must define SYNCTEX_USE_LOCAL_HEADER,
0026  *  when building. You also have to create and customize synctex_parser_local.h to fit your system.
0027  *  In particular, the HAVE_LOCALE_H and HAVE_SETLOCALE macros should be properly defined.
0028  *  With this design, you should not need to edit this file. */
0029 
0030 /**
0031  *  \file synctex_parser.c
0032  *  \brief SyncTeX file parser and controller.
0033  *  - author: Jérôme LAURENS
0034  *  \version 1.19
0035  *  \date Mon Apr 24 07:08:56 UTC 2017
0036  *
0037  *  Reads and parse *.synctex[.gz] files,
0038  *  performs edit and display queries.
0039  *
0040  *  See
0041  *  - synctex_scanner_new_with_output_file
0042  *  - synctex_scanner_parse
0043  *  - synctex_scanner_free
0044  *  - synctex_display_query
0045  *  - synctex_edit_query
0046  *  - synctex_scanner_next_result
0047  *  - synctex_scanner_reset_result
0048  *
0049  *  The data is organized in a graph with multiple entries.
0050  *  The root object is a scanner, it is created with the contents on a synctex file.
0051  *  Each node of the tree is a synctex_node_t object.
0052  *  There are 3 subtrees, two of them sharing the same leaves.
0053  *  The first tree is the list of input records, where input file names are associated with tags.
0054  *  The second tree is the box tree as given by TeX when shipping pages out.
0055  *  First level objects are sheets and forms, containing boxes, glues, kerns...
0056  *  The third tree allows to browse leaves according to tag and line.
0057  */
0058 #if defined(SYNCTEX_USE_LOCAL_HEADER)
0059 #include "synctex_parser_local.h"
0060 #else
0061 #define HAVE_LOCALE_H 1
0062 #define HAVE_SETLOCALE 1
0063 #if defined(_MSC_VER)
0064 #define SYNCTEX_INLINE __inline
0065 #else
0066 #define SYNCTEX_INLINE
0067 #endif
0068 #endif
0069 
0070 #include <errno.h>
0071 #include <limits.h>
0072 #include <stdarg.h>
0073 #include <stdio.h>
0074 #include <stdlib.h>
0075 #include <string.h>
0076 
0077 #if defined(HAVE_LOCALE_H)
0078 #include <locale.h>
0079 #endif
0080 
0081 #include "synctex_parser_advanced.h"
0082 
0083 SYNCTEX_INLINE static int _synctex_abs(int x)
0084 {
0085     return x > 0 ? x : -x;
0086 }
0087 /*  These are the possible extensions of the synctex file */
0088 const char *synctex_suffix = ".synctex";
0089 const char *synctex_suffix_gz = ".gz";
0090 
0091 typedef synctex_node_p (*synctex_node_new_f)(synctex_scanner_p);
0092 typedef void (*synctex_node_fld_f)(synctex_node_p);
0093 typedef char *(*synctex_node_str_f)(synctex_node_p);
0094 
0095 /**
0096  *  Pseudo class.
0097  *  - author: J. Laurens
0098  *
0099  *  Each nodes has a class, it is therefore called an object.
0100  *  Each class has a unique scanner.
0101  *  Each class has a type which is a unique identifier.
0102  *  Each class has a node mask which identifies node's attributes.
0103  *  Each class has an info mask which info's attributes.
0104  *  The class points to various methods,
0105  *  each of them vary amongst objects.
0106  *  The navigator records the offsets of the tree members getters.
0107  *  The modelator records the offsets of the data members getters, relative to the last navigator getter.
0108  */
0109 
0110 /*  8 fields + size: spcflnat */
0111 typedef struct synctex_tree_model_t {
0112     int sibling;
0113     int parent;
0114     int child;
0115     int friend;
0116     int last;
0117     int next_hbox;
0118     int arg_sibling;
0119     int target;
0120     int size;
0121 } synctex_tree_model_s;
0122 typedef const synctex_tree_model_s *synctex_tree_model_p;
0123 
0124 typedef struct synctex_data_model_t {
0125     int tag;
0126     int line;
0127     int column;
0128     int h;
0129     int v;
0130     int width;
0131     int height;
0132     int depth;
0133     int mean_line;
0134     int weight;
0135     int h_V;
0136     int v_V;
0137     int width_V;
0138     int height_V;
0139     int depth_V;
0140     int name;
0141     int page;
0142     int size;
0143 } synctex_data_model_s;
0144 
0145 static const synctex_data_model_s synctex_data_model_none = {-1, /* tag */
0146                                                              -1, /* line */
0147                                                              -1, /* column */
0148                                                              -1, /* h */
0149                                                              -1, /* v */
0150                                                              -1, /* width */
0151                                                              -1, /* height */
0152                                                              -1, /* depth */
0153                                                              -1, /* mean_line */
0154                                                              -1, /* weight */
0155                                                              -1, /* h_V */
0156                                                              -1, /* v_V */
0157                                                              -1, /* width_V */
0158                                                              -1, /* height_V */
0159                                                              -1, /* depth_V */
0160                                                              -1, /* name */
0161                                                              -1, /* page */
0162                                                              0};
0163 typedef const synctex_data_model_s *synctex_data_model_p;
0164 
0165 typedef int (*synctex_int_getter_f)(synctex_node_p);
0166 typedef struct synctex_tlcpector_t {
0167     synctex_int_getter_f tag;
0168     synctex_int_getter_f line;
0169     synctex_int_getter_f column;
0170 } synctex_tlcpector_s;
0171 typedef const synctex_tlcpector_s *synctex_tlcpector_p;
0172 static int _synctex_int_none(synctex_node_p node)
0173 {
0174     (void)node; /* unused */
0175     return 0;
0176 }
0177 static const synctex_tlcpector_s synctex_tlcpector_none = {
0178     &_synctex_int_none, /* tag */
0179     &_synctex_int_none, /* line */
0180     &_synctex_int_none, /* column */
0181 };
0182 
0183 typedef struct synctex_inspector_t {
0184     synctex_int_getter_f h;
0185     synctex_int_getter_f v;
0186     synctex_int_getter_f width;
0187     synctex_int_getter_f height;
0188     synctex_int_getter_f depth;
0189 } synctex_inspector_s;
0190 typedef const synctex_inspector_s *synctex_inspector_p;
0191 static const synctex_inspector_s synctex_inspector_none = {
0192     &_synctex_int_none, /* h */
0193     &_synctex_int_none, /* v */
0194     &_synctex_int_none, /* width */
0195     &_synctex_int_none, /* height */
0196     &_synctex_int_none, /* depth */
0197 };
0198 
0199 typedef float (*synctex_float_getter_f)(synctex_node_p);
0200 typedef struct synctex_vispector_t {
0201     synctex_float_getter_f h;
0202     synctex_float_getter_f v;
0203     synctex_float_getter_f width;
0204     synctex_float_getter_f height;
0205     synctex_float_getter_f depth;
0206 } synctex_vispector_s;
0207 static float _synctex_float_none(synctex_node_p node)
0208 {
0209     (void)node; /* unused */
0210     return 0;
0211 }
0212 static const synctex_vispector_s synctex_vispector_none = {
0213     &_synctex_float_none, /* h */
0214     &_synctex_float_none, /* v */
0215     &_synctex_float_none, /* width */
0216     &_synctex_float_none, /* height */
0217     &_synctex_float_none, /* depth */
0218 };
0219 typedef const synctex_vispector_s *synctex_vispector_p;
0220 
0221 struct synctex_class_t {
0222     synctex_scanner_p scanner;
0223     synctex_node_type_t type;
0224     synctex_node_new_f new;
0225     synctex_node_fld_f free;
0226     synctex_node_fld_f log;
0227     synctex_node_fld_f display;
0228     synctex_node_str_f abstract;
0229     synctex_tree_model_p navigator;
0230     synctex_data_model_p modelator;
0231     synctex_tlcpector_p tlcpector;
0232     synctex_inspector_p inspector;
0233     synctex_vispector_p vispector;
0234 };
0235 
0236 /**
0237  *  Nota bene: naming convention.
0238  *  For static API, when the name contains proxy, it applies to proxies.
0239  *  When the name contains noxy, it applies to non proxies only.
0240  *  When the name contains node, weel it depends...
0241  */
0242 
0243 typedef synctex_node_p synctex_proxy_p;
0244 typedef synctex_node_p synctex_noxy_p;
0245 
0246 #ifdef SYNCTEX_NOTHING
0247 #pragma mark -
0248 #pragma mark Abstract OBJECTS and METHODS
0249 #endif
0250 
0251 /**
0252  *  \def SYNCTEX_MSG_SEND
0253  *  \brief Takes care of sending the given message if possible.
0254  *  - parameter NODE: of type synctex_node_p
0255  *  - parameter SELECTOR: one of the class pointer properties
0256  */
0257 #define SYNCTEX_MSG_SEND(NODE, SELECTOR)                                                                                                                                                                                                       \
0258     do {                                                                                                                                                                                                                                       \
0259         synctex_node_p N__ = NODE;                                                                                                                                                                                                             \
0260         if (N__ && N__->class->SELECTOR) {                                                                                                                                                                                                     \
0261             (*(N__->class->SELECTOR))(N__);                                                                                                                                                                                                    \
0262         }                                                                                                                                                                                                                                      \
0263     } while (synctex_NO)
0264 
0265 /**
0266  *  Free the given node by sending the free message.
0267  *  - parameter NODE: of type synctex_node_p
0268  */
0269 void synctex_node_free(synctex_node_p node)
0270 {
0271     SYNCTEX_MSG_SEND(node, free);
0272 }
0273 #if defined(SYNCTEX_TESTING)
0274 #if !defined(SYNCTEX_USE_HANDLE)
0275 #define SYNCTEX_USE_HANDLE 1
0276 #endif
0277 #if !defined(SYNCTEX_USE_CHARINDEX)
0278 #define SYNCTEX_USE_CHARINDEX 1
0279 #endif
0280 #endif
0281 SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target);
0282 #if defined(SYNCTEX_USE_HANDLE)
0283 #define SYNCTEX_SCANNER_FREE_HANDLE(SCANR) __synctex_scanner_free_handle(SCANR)
0284 #define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT) __synctex_scanner_remove_handle_to(WHAT)
0285 #define SYNCTEX_REGISTER_HANDLE_TO(NODE) __synctex_scanner_register_handle_to(NODE)
0286 #else
0287 #define SYNCTEX_SCANNER_FREE_HANDLE(SCANR)
0288 #define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT)
0289 #define SYNCTEX_REGISTER_HANDLE_TO(NODE)
0290 #endif
0291 
0292 #if defined(SYNCTEX_USE_CHARINDEX)
0293 #define SYNCTEX_CHARINDEX(NODE) (NODE->char_index)
0294 #define SYNCTEX_LINEINDEX(NODE) (NODE->line_index)
0295 #define SYNCTEX_PRINT_CHARINDEX_FMT "#%i"
0296 #define SYNCTEX_PRINT_CHARINDEX_WHAT , SYNCTEX_CHARINDEX(node)
0297 #define SYNCTEX_PRINT_CHARINDEX printf(SYNCTEX_PRINT_CHARINDEX_FMT SYNCTEX_PRINT_CHARINDEX_WHAT)
0298 #define SYNCTEX_PRINT_LINEINDEX_FMT "L#%i"
0299 #define SYNCTEX_PRINT_LINEINDEX_WHAT , SYNCTEX_LINEINDEX(node)
0300 #define SYNCTEX_PRINT_LINEINDEX printf(SYNCTEX_PRINT_LINEINDEX_FMT SYNCTEX_PRINT_LINEINDEX_WHAT)
0301 #define SYNCTEX_PRINT_CHARINDEX_NL printf(SYNCTEX_PRINT_CHARINDEX_FMT "\n" SYNCTEX_PRINT_CHARINDEX_WHAT)
0302 #define SYNCTEX_PRINT_LINEINDEX_NL printf(SYNCTEX_PRINT_CHARINDEX_FMT "\n" SYNCTEX_PRINT_LINEINDEX_WHAT)
0303 #define SYNCTEX_IMPLEMENT_CHARINDEX(NODE, CORRECTION)                                                                                                                                                                                          \
0304     NODE->char_index = (synctex_charindex_t)(scanner->reader->charindex_offset + SYNCTEX_CUR - SYNCTEX_START + (CORRECTION));                                                                                                                  \
0305     NODE->line_index = scanner->reader->line_number;
0306 #else
0307 #define SYNCTEX_CHARINDEX(NODE) 0
0308 #define SYNCTEX_LINEINDEX(NODE) 0
0309 #define SYNCTEX_PRINT_CHARINDEX_FMT
0310 #define SYNCTEX_PRINT_CHARINDEX_WHAT
0311 #define SYNCTEX_PRINT_CHARINDEX
0312 #define SYNCTEX_PRINT_CHARINDEX
0313 #define SYNCTEX_PRINT_LINEINDEX_FMT
0314 #define SYNCTEX_PRINT_LINEINDEX_WHAT
0315 #define SYNCTEX_PRINT_LINEINDEX
0316 #define SYNCTEX_PRINT_CHARINDEX_NL printf("\n")
0317 #define SYNCTEX_PRINT_LINEINDEX_NL printf("\n")
0318 #define SYNCTEX_IMPLEMENT_CHARINDEX(NODE, CORRECTION)
0319 #endif
0320 
0321 /**
0322  *  The next macros are used to access the node tree info
0323  *  SYNCTEX_DATA(node) points to the first synctex integer or pointer data of node
0324  *  SYNCTEX_DATA(node)[index] is the information at index
0325  *  for example, the page of a sheet is stored in SYNCTEX_DATA(sheet)[_synctex_data_page_idx]
0326  *  - parameter NODE: of type synctex_node_p
0327  *  If the name starts with "__", the argument is nonullable
0328  */
0329 #ifdef SYNCTEX_NOTHING
0330 #pragma mark -
0331 #pragma mark Tree SETGET
0332 #endif
0333 
0334 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 1000
0335 #define SYNCTEX_PARAMETER_ASSERT(WHAT)                                                                                                                                                                                                         \
0336     do {                                                                                                                                                                                                                                       \
0337         if (!(WHAT)) {                                                                                                                                                                                                                         \
0338             printf("! Parameter failure: %s\n", #WHAT);                                                                                                                                                                                        \
0339         }                                                                                                                                                                                                                                      \
0340     } while (synctex_NO)
0341 #define DEFINE_SYNCTEX_TREE_HAS(WHAT)                                                                                                                                                                                                          \
0342     static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node)                                                                                                                                                                        \
0343     {                                                                                                                                                                                                                                          \
0344         if (node) {                                                                                                                                                                                                                            \
0345             if (node->class->navigator->WHAT >= 0) {                                                                                                                                                                                           \
0346                 return synctex_YES;                                                                                                                                                                                                            \
0347             } else {                                                                                                                                                                                                                           \
0348                 printf("WARNING: NO tree %s for %s\n", #WHAT, synctex_node_isa(node));                                                                                                                                                         \
0349             }                                                                                                                                                                                                                                  \
0350         }                                                                                                                                                                                                                                      \
0351         return synctex_NO;                                                                                                                                                                                                                     \
0352     }
0353 #else
0354 #define SYNCTEX_PARAMETER_ASSERT(WHAT)
0355 #define DEFINE_SYNCTEX_TREE_HAS(WHAT)                                                                                                                                                                                                          \
0356     static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node)                                                                                                                                                                        \
0357     {                                                                                                                                                                                                                                          \
0358         return (node && (node->class->navigator->WHAT >= 0));                                                                                                                                                                                  \
0359     }
0360 #endif
0361 
0362 #define DEFINE_SYNCTEX_TREE__GET(WHAT)                                                                                                                                                                                                         \
0363     SYNCTEX_INLINE static synctex_node_p __synctex_tree_##WHAT(synctex_non_null_node_p node)                                                                                                                                                   \
0364     {                                                                                                                                                                                                                                          \
0365         return node->data[node->class->navigator->WHAT].as_node;                                                                                                                                                                               \
0366     }
0367 #define DEFINE_SYNCTEX_TREE_GET(WHAT)                                                                                                                                                                                                          \
0368     DEFINE_SYNCTEX_TREE__GET(WHAT)                                                                                                                                                                                                             \
0369     static synctex_node_p _synctex_tree_##WHAT(synctex_node_p node)                                                                                                                                                                            \
0370     {                                                                                                                                                                                                                                          \
0371         if (_synctex_tree_has_##WHAT(node)) {                                                                                                                                                                                                  \
0372             return __synctex_tree_##WHAT(node);                                                                                                                                                                                                \
0373         }                                                                                                                                                                                                                                      \
0374         return 0;                                                                                                                                                                                                                              \
0375     }
0376 #define DEFINE_SYNCTEX_TREE__RESET(WHAT)                                                                                                                                                                                                       \
0377     SYNCTEX_INLINE static synctex_node_p __synctex_tree_reset_##WHAT(synctex_non_null_node_p node)                                                                                                                                             \
0378     {                                                                                                                                                                                                                                          \
0379         synctex_node_p old = node->data[node->class->navigator->WHAT].as_node;                                                                                                                                                                 \
0380         node->data[node->class->navigator->WHAT].as_node = NULL;                                                                                                                                                                               \
0381         return old;                                                                                                                                                                                                                            \
0382     }
0383 #define DEFINE_SYNCTEX_TREE_RESET(WHAT)                                                                                                                                                                                                        \
0384     DEFINE_SYNCTEX_TREE__RESET(WHAT)                                                                                                                                                                                                           \
0385     SYNCTEX_INLINE static synctex_node_p _synctex_tree_reset_##WHAT(synctex_node_p node)                                                                                                                                                       \
0386     {                                                                                                                                                                                                                                          \
0387         return _synctex_tree_has_##WHAT(node) ? __synctex_tree_reset_##WHAT(node) : NULL;                                                                                                                                                      \
0388     }
0389 #define DEFINE_SYNCTEX_TREE__SET(WHAT)                                                                                                                                                                                                         \
0390     SYNCTEX_INLINE static synctex_node_p __synctex_tree_set_##WHAT(synctex_non_null_node_p node, synctex_node_p new_value)                                                                                                                     \
0391     {                                                                                                                                                                                                                                          \
0392         synctex_node_p old = __synctex_tree_##WHAT(node);                                                                                                                                                                                      \
0393         node->data[node->class->navigator->WHAT].as_node = new_value;                                                                                                                                                                          \
0394         return old;                                                                                                                                                                                                                            \
0395     }
0396 #define DEFINE_SYNCTEX_TREE_SET(WHAT)                                                                                                                                                                                                          \
0397     DEFINE_SYNCTEX_TREE__SET(WHAT)                                                                                                                                                                                                             \
0398     SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_##WHAT(synctex_node_p node, synctex_node_p new_value)                                                                                                                               \
0399     {                                                                                                                                                                                                                                          \
0400         return _synctex_tree_has_##WHAT(node) ? __synctex_tree_set_##WHAT(node, new_value) : NULL;                                                                                                                                             \
0401     }
0402 #define DEFINE_SYNCTEX_TREE__GETSETRESET(WHAT)                                                                                                                                                                                                 \
0403     DEFINE_SYNCTEX_TREE__GET(WHAT)                                                                                                                                                                                                             \
0404     DEFINE_SYNCTEX_TREE__SET(WHAT)                                                                                                                                                                                                             \
0405     DEFINE_SYNCTEX_TREE__RESET(WHAT)
0406 
0407 #define DEFINE_SYNCTEX_TREE_GETSET(WHAT)                                                                                                                                                                                                       \
0408     DEFINE_SYNCTEX_TREE_HAS(WHAT)                                                                                                                                                                                                              \
0409     DEFINE_SYNCTEX_TREE_GET(WHAT)                                                                                                                                                                                                              \
0410     DEFINE_SYNCTEX_TREE_SET(WHAT)
0411 
0412 #define DEFINE_SYNCTEX_TREE_GETRESET(WHAT)                                                                                                                                                                                                     \
0413     DEFINE_SYNCTEX_TREE_HAS(WHAT)                                                                                                                                                                                                              \
0414     DEFINE_SYNCTEX_TREE_GET(WHAT)                                                                                                                                                                                                              \
0415     DEFINE_SYNCTEX_TREE_RESET(WHAT)
0416 
0417 #define DEFINE_SYNCTEX_TREE_GETSETRESET(WHAT)                                                                                                                                                                                                  \
0418     DEFINE_SYNCTEX_TREE_HAS(WHAT)                                                                                                                                                                                                              \
0419     DEFINE_SYNCTEX_TREE_GET(WHAT)                                                                                                                                                                                                              \
0420     DEFINE_SYNCTEX_TREE_SET(WHAT)                                                                                                                                                                                                              \
0421     DEFINE_SYNCTEX_TREE_RESET(WHAT)
0422 
0423 /*
0424  *  _synctex_tree_set_... methods return the old value.
0425  *  The return value of _synctex_tree_set_child and
0426  *  _synctex_tree_set_sibling must be released somehown.
0427  */
0428 DEFINE_SYNCTEX_TREE__GETSETRESET(sibling)
0429 DEFINE_SYNCTEX_TREE_GETSETRESET(parent)
0430 DEFINE_SYNCTEX_TREE_GETSETRESET(child)
0431 DEFINE_SYNCTEX_TREE_GETSETRESET(friend)
0432 DEFINE_SYNCTEX_TREE_GETSET(last)
0433 DEFINE_SYNCTEX_TREE_GETSET(next_hbox)
0434 DEFINE_SYNCTEX_TREE_GETSET(arg_sibling)
0435 DEFINE_SYNCTEX_TREE_GETSET(target)
0436 
0437 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 1000
0438 #undef SYNCTEX_USE_NODE_COUNT
0439 #define SYNCTEX_USE_NODE_COUNT 1
0440 #endif
0441 #if defined SYNCTEX_USE_NODE_COUNT && SYNCTEX_USE_NODE_COUNT > 0
0442 #define SYNCTEX_DECLARE_NODE_COUNT int node_count;
0443 #define SYNCTEX_INIT_NODE_COUNT                                                                                                                                                                                                                \
0444     do {                                                                                                                                                                                                                                       \
0445         node_count = 0;                                                                                                                                                                                                                        \
0446     } while (synctex_NO)
0447 #else
0448 #define SYNCTEX_DECLARE_NODE_COUNT
0449 #define SYNCTEX_INIT_NODE_COUNT
0450 #endif
0451 
0452 #if defined SYNCTEX_USE_NODE_COUNT && SYNCTEX_USE_NODE_COUNT > 10
0453 #define SYNCTEX_DID_NEW(N) _synctex_did_new(N)
0454 #define SYNCTEX_WILL_FREE(N) _synctex_will_free(N)
0455 #else
0456 #define SYNCTEX_DID_NEW(N)
0457 #define SYNCTEX_WILL_FREE(N)
0458 #endif
0459 
0460 #define SYNCTEX_HAS_CHILDREN(NODE) (NODE && _synctex_tree_child(NODE))
0461 #ifdef __SYNCTEX_WORK__
0462 #include "/usr/include/zlib.h"
0463 #else
0464 #include <zlib.h>
0465 #endif
0466 
0467 #ifdef SYNCTEX_NOTHING
0468 #pragma mark -
0469 #pragma mark STATUS
0470 #endif
0471 /*  When the end of the synctex file has been reached: */
0472 #define SYNCTEX_STATUS_EOF 0
0473 /*  When the function could not return the value it was asked for: */
0474 #define SYNCTEX_STATUS_NOT_OK (SYNCTEX_STATUS_EOF + 1)
0475 /*  When the function returns the value it was asked for:
0476  It must be the biggest one */
0477 #define SYNCTEX_STATUS_OK (SYNCTEX_STATUS_NOT_OK + 1)
0478 /*  Generic error: */
0479 #define SYNCTEX_STATUS_ERROR (SYNCTEX_STATUS_EOF - 1)
0480 /*  Parameter error: */
0481 #define SYNCTEX_STATUS_BAD_ARGUMENT (SYNCTEX_STATUS_ERROR - 1)
0482 
0483 #ifdef SYNCTEX_NOTHING
0484 #pragma mark -
0485 #pragma mark File reader
0486 #endif
0487 
0488 /*  We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */
0489 /*  Actually, the minimum buffer size is driven by integer and float parsing, including the unit.
0490  *  ±0.123456789e123??
0491  */
0492 #define SYNCTEX_BUFFER_MIN_SIZE 32
0493 #define SYNCTEX_BUFFER_SIZE 32768
0494 
0495 #if SYNCTEX_BUFFER_SIZE >= UINT_MAX
0496 #error BAD BUFFER SIZE(1)
0497 #endif
0498 #if SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE
0499 #error BAD BUFFER SIZE(2)
0500 #endif
0501 
0502 typedef struct synctex_reader_t {
0503     gzFile file; /*  The (possibly compressed) file */
0504     char *output;
0505     char *synctex;
0506     char *current; /*  current location in the buffer */
0507     char *start;   /*  start of the buffer */
0508     char *end;     /*  end of the buffer */
0509     size_t min_size;
0510     size_t size;
0511     int lastv;
0512     int line_number;
0513     SYNCTEX_DECLARE_CHAR_OFFSET
0514 } synctex_reader_s;
0515 
0516 typedef synctex_reader_s *synctex_reader_p;
0517 
0518 typedef struct {
0519     synctex_status_t status;
0520     char *synctex;
0521     gzFile file;
0522     synctex_io_mode_t io_mode;
0523 } synctex_open_s;
0524 
0525 /*  This functions opens the file at the "output" given location.
0526  *  It manages the problem of quoted filenames that appear with pdftex and filenames containing the space character.
0527  *  In TeXLive 2008, the synctex file created with pdftex did contain unexpected quotes.
0528  *  This function will remove them if possible.
0529  *  All the reference arguments will take a value on return. They must be non NULL.
0530  *  - returns: an open structure which status is
0531  *      SYNCTEX_STATUS_OK on success,
0532  *      SYNCTEX_STATUS_ERROR on failure.
0533  *  - note: on success, the caller is the owner
0534  *      of the fields of the returned open structure.
0535  */
0536 static synctex_open_s __synctex_open_v2(const char *output, synctex_io_mode_t io_mode, synctex_bool_t add_quotes)
0537 {
0538     synctex_open_s open = {SYNCTEX_STATUS_ERROR, NULL, NULL, io_mode};
0539     char *quoteless_synctex_name = NULL;
0540     const char *mode = _synctex_get_io_mode_name(open.io_mode);
0541     size_t size = strlen(output) + strlen(synctex_suffix) + strlen(synctex_suffix_gz) + 1;
0542     if (NULL == (open.synctex = (char *)malloc(size))) {
0543         _synctex_error("!  __synctex_open_v2: Memory problem (1)\n");
0544         return open;
0545     }
0546     /*  we have reserved for synctex enough memory to copy output (including its 2 eventual quotes), both suffices,
0547      *  including the terminating character. size is free now. */
0548     if (open.synctex != strcpy(open.synctex, output)) {
0549         _synctex_error("!  __synctex_open_v2: Copy problem\n");
0550     return_on_error:
0551         free(open.synctex);
0552         open.synctex = NULL;
0553         free(quoteless_synctex_name); /* We MUST have quoteless_synctex_name<>synctex_name */
0554         return open;
0555     }
0556     /*  remove the last path extension if any */
0557     _synctex_strip_last_path_extension(open.synctex);
0558     if (!strlen(open.synctex)) {
0559         goto return_on_error;
0560     }
0561     /*  now insert quotes. */
0562     if (add_quotes) {
0563         char *quoted = NULL;
0564         if (_synctex_copy_with_quoting_last_path_component(open.synctex, &quoted, size) || quoted == NULL) {
0565             /*  There was an error or quoting does not make sense: */
0566             goto return_on_error;
0567         }
0568         quoteless_synctex_name = open.synctex;
0569         open.synctex = quoted;
0570     }
0571     /*  Now add to open.synctex the first path extension. */
0572     if (open.synctex != strcat(open.synctex, synctex_suffix)) {
0573         _synctex_error("!  __synctex_open_v2: Concatenation problem (can't add suffix '%s')\n", synctex_suffix);
0574         goto return_on_error;
0575     }
0576     /*  Add to quoteless_synctex_name as well, if relevant. */
0577     if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name, synctex_suffix))) {
0578         free(quoteless_synctex_name);
0579         quoteless_synctex_name = NULL;
0580     }
0581     if (NULL == (open.file = gzopen(open.synctex, mode))) {
0582         /*  Could not open this file */
0583         if (errno != ENOENT) {
0584             /*  The file does exist, this is a lower level error, I can't do anything. */
0585             _synctex_error("could not open %s, error %i\n", open.synctex, errno);
0586             goto return_on_error;
0587         }
0588         /*  Apparently, there is no uncompressed synctex file. Try the compressed version */
0589         if (open.synctex != strcat(open.synctex, synctex_suffix_gz)) {
0590             _synctex_error("!  __synctex_open_v2: Concatenation problem (can't add suffix '%s')\n", synctex_suffix_gz);
0591             goto return_on_error;
0592         }
0593         open.io_mode |= synctex_io_gz_mask;
0594         mode = _synctex_get_io_mode_name(open.io_mode); /* the file is a compressed and is a binary file, this caused errors on Windows */
0595         /*  Add the suffix to the quoteless_synctex_name as well. */
0596         if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name, synctex_suffix_gz))) {
0597             free(quoteless_synctex_name);
0598             quoteless_synctex_name = NULL;
0599         }
0600         if (NULL == (open.file = gzopen(open.synctex, mode))) {
0601             /*  Could not open this file */
0602             if (errno != ENOENT) {
0603                 /*  The file does exist, this is a lower level error, I can't do anything. */
0604                 _synctex_error("Could not open %s, error %i\n", open.synctex, errno);
0605             }
0606             goto return_on_error;
0607         }
0608     }
0609     /*  At this point, the file is properly open.
0610      *  If we are in the add_quotes mode, we change the file name by removing the quotes. */
0611     if (quoteless_synctex_name) {
0612         gzclose(open.file);
0613         if (rename(open.synctex, quoteless_synctex_name)) {
0614             _synctex_error("Could not rename %s to %s, error %i\n", open.synctex, quoteless_synctex_name, errno);
0615             /*  We could not rename, reopen the file with the quoted name. */
0616             if (NULL == (open.file = gzopen(open.synctex, mode))) {
0617                 /*  No luck, could not re open this file, something has happened meanwhile */
0618                 if (errno != ENOENT) {
0619                     /*  The file does not exist any more, it has certainly be removed somehow
0620                      *  this is a lower level error, I can't do anything. */
0621                     _synctex_error("Could not open again %s, error %i\n", open.synctex, errno);
0622                 }
0623                 goto return_on_error;
0624             }
0625         } else {
0626             /*  The file has been successfully renamed */
0627             if (NULL == (open.file = gzopen(quoteless_synctex_name, mode))) {
0628                 /*  Could not open this file */
0629                 if (errno != ENOENT) {
0630                     /*  The file does exist, this is a lower level error, I can't do anything. */
0631                     _synctex_error("Could not open renamed %s, error %i\n", quoteless_synctex_name, errno);
0632                 }
0633                 goto return_on_error;
0634             }
0635             /*  The quote free file name should replace the old one:*/
0636             free(open.synctex);
0637             open.synctex = quoteless_synctex_name;
0638             quoteless_synctex_name = NULL;
0639         }
0640     }
0641     /*  The operation is successful, return the arguments by value.    */
0642     open.status = SYNCTEX_STATUS_OK;
0643     return open;
0644 }
0645 
0646 /*  Opens the output file, taking into account the eventual build_directory.
0647  *  - returns: an open structure which status is
0648  *      SYNCTEX_STATUS_OK on success,
0649  *      SYNCTEX_STATUS_ERROR on failure.
0650  *  - note: on success, the caller is the owner
0651  *      of the fields of the returned open structure.
0652  */
0653 static synctex_open_s _synctex_open_v2(const char *output, const char *build_directory, synctex_io_mode_t io_mode, synctex_bool_t add_quotes)
0654 {
0655     synctex_open_s open = __synctex_open_v2(output, io_mode, add_quotes);
0656     if (open.status == SYNCTEX_STATUS_OK) {
0657         return open;
0658     }
0659     if (build_directory && strlen(build_directory)) {
0660         char *build_output;
0661         const char *lpc;
0662         size_t size;
0663         synctex_bool_t is_absolute;
0664         build_output = NULL;
0665         lpc = _synctex_last_path_component(output);
0666         size = strlen(build_directory) + strlen(lpc) + 2; /*  One for the '/' and one for the '\0'.   */
0667         is_absolute = _synctex_path_is_absolute(build_directory);
0668         if (!is_absolute) {
0669             size += strlen(output);
0670         }
0671         if ((build_output = (char *)_synctex_malloc(size))) {
0672             if (is_absolute) {
0673                 build_output[0] = '\0';
0674             } else {
0675                 if (build_output != strcpy(build_output, output)) {
0676                     _synctex_free(build_output);
0677                     return open;
0678                 }
0679                 build_output[lpc - output] = '\0';
0680             }
0681             if (build_output == strcat(build_output, build_directory)) {
0682                 /*  Append a path separator if necessary. */
0683                 if (!SYNCTEX_IS_PATH_SEPARATOR(build_output[strlen(build_directory) - 1])) {
0684                     if (build_output != strcat(build_output, "/")) {
0685                         _synctex_free(build_output);
0686                         return open;
0687                     }
0688                 }
0689                 /*  Append the last path component of the output. */
0690                 if (build_output != strcat(build_output, lpc)) {
0691                     _synctex_free(build_output);
0692                     return open;
0693                 }
0694                 open = __synctex_open_v2(build_output, io_mode, add_quotes);
0695             }
0696             _synctex_free(build_output);
0697         } /* if ((build_output... */
0698     }     /* if (build_directory...) */
0699     return open;
0700 }
0701 void synctex_reader_free(synctex_reader_p reader)
0702 {
0703     if (reader) {
0704         _synctex_free(reader->output);
0705         _synctex_free(reader->synctex);
0706         _synctex_free(reader->start);
0707         gzclose(reader->file);
0708         _synctex_free(reader);
0709     }
0710 }
0711 /*
0712  *  Return reader on success.
0713  *  Deallocate reader and return NULL on failure.
0714  */
0715 synctex_reader_p synctex_reader_init_with_output_file(synctex_reader_p reader, const char *output, const char *build_directory)
0716 {
0717     if (reader) {
0718         /*  now open the synctex file */
0719         synctex_open_s open = _synctex_open_v2(output, build_directory, 0, synctex_ADD_QUOTES);
0720         if (open.status < SYNCTEX_STATUS_OK) {
0721             open = _synctex_open_v2(output, build_directory, 0, synctex_DONT_ADD_QUOTES);
0722             if (open.status < SYNCTEX_STATUS_OK) {
0723                 synctex_reader_free(reader);
0724                 return NULL;
0725             }
0726         }
0727         reader->synctex = open.synctex;
0728         reader->file = open.file;
0729         /*  make a private copy of output */
0730         if (NULL == (reader->output = (char *)_synctex_malloc(strlen(output) + 1))) {
0731             _synctex_error("!  synctex_scanner_new_with_output_file: Memory problem (2), reader's output is not reliable.");
0732         } else if (reader->output != strcpy(reader->output, output)) {
0733             _synctex_free(reader->output);
0734             reader->output = NULL;
0735             _synctex_error("!  synctex_scanner_new_with_output_file: Copy problem, reader's output is not reliable.");
0736         }
0737         reader->start = reader->end = reader->current = NULL;
0738         reader->min_size = SYNCTEX_BUFFER_MIN_SIZE;
0739         reader->size = SYNCTEX_BUFFER_SIZE;
0740         reader->start = reader->current = (char *)_synctex_malloc(reader->size + 1); /*  one more character for null termination */
0741         if (NULL == reader->start) {
0742             _synctex_error("!  malloc error in synctex_reader_init_with_output_file.");
0743 #ifdef SYNCTEX_DEBUG
0744             return reader;
0745 #else
0746             synctex_reader_free(reader);
0747             return NULL;
0748 #endif
0749         }
0750         reader->end = reader->start + reader->size;
0751         /*  reader->end always points to a null terminating character.
0752          *  Maybe there is another null terminating character between reader->current and reader->end-1.
0753          *  At least, we are sure that reader->current points to a string covering a valid part of the memory. */
0754 #if defined(SYNCTEX_USE_CHARINDEX)
0755         reader->charindex_offset = -reader->size;
0756 #endif
0757     }
0758     return reader;
0759 }
0760 
0761 #if defined(SYNCTEX_USE_HANDLE)
0762 #define SYNCTEX_DECLARE_HANDLE synctex_node_p handle;
0763 #else
0764 #define SYNCTEX_DECLARE_HANDLE
0765 #endif
0766 
0767 #ifdef SYNCTEX_NOTHING
0768 #pragma mark -
0769 #pragma mark SCANNER
0770 #endif
0771 /**
0772  *  The synctex scanner is the root object.
0773  *  Is is initialized with the contents of a text file or a gzipped file.
0774  *  The buffer_.* are first used to parse the text.
0775  */
0776 struct synctex_scanner_t {
0777     synctex_reader_p reader;
0778     SYNCTEX_DECLARE_NODE_COUNT
0779     SYNCTEX_DECLARE_HANDLE
0780     char *output_fmt;            /*  dvi or pdf, not yet used */
0781     synctex_iterator_p iterator; /*  result iterator */
0782     int version;                 /*  1, not yet used */
0783     struct {
0784         unsigned has_parsed : 1;                  /*  Whether the scanner has parsed its underlying synctex file. */
0785         unsigned postamble : 1;                   /*  Whether the scanner has parsed its underlying synctex file. */
0786         unsigned reserved : sizeof(unsigned) - 2; /*  alignment */
0787     } flags;
0788     int pre_magnification;                               /*  magnification from the synctex preamble */
0789     int pre_unit;                                        /*  unit from the synctex preamble */
0790     int pre_x_offset;                                    /*  X offset from the synctex preamble */
0791     int pre_y_offset;                                    /*  Y offset from the synctex preamble */
0792     int count;                                           /*  Number of records, from the synctex postamble */
0793     float unit;                                          /*  real unit, from synctex preamble or post scriptum */
0794     float x_offset;                                      /*  X offset, from synctex preamble or post scriptum */
0795     float y_offset;                                      /*  Y Offset, from synctex preamble or post scriptum */
0796     synctex_node_p input;                                /*  The first input node, its siblings are the other input nodes */
0797     synctex_node_p sheet;                                /*  The first sheet node, its siblings are the other sheet nodes */
0798     synctex_node_p form;                                 /*  The first form, its siblings are the other forms */
0799     synctex_node_p ref_in_sheet;                         /*  The first form ref node in sheet, its friends are the other form ref nodes */
0800     synctex_node_p ref_in_form;                          /*  The first form ref node, its friends are the other form ref nodes in sheet */
0801     int number_of_lists;                                 /*  The number of friend lists */
0802     synctex_node_r lists_of_friends;                     /*  The friend lists */
0803     synctex_class_s class[synctex_node_number_of_types]; /*  The classes of the nodes of the scanner */
0804     int display_switcher;
0805     char *display_prompt;
0806 };
0807 
0808 /**
0809  *  Create a new node of the given type.
0810  *  - parameter scanner: of type synctex_node_p
0811  *  - parameter type: a type, the client is responsible
0812  *  to ask for an acceptable type.
0813  */
0814 synctex_node_p synctex_node_new(synctex_scanner_p scanner, synctex_node_type_t type)
0815 {
0816     return scanner ? scanner->class[type].new(scanner) : NULL;
0817 }
0818 #if defined(SYNCTEX_USE_HANDLE)
0819 SYNCTEX_INLINE static void __synctex_scanner_free_handle(synctex_scanner_p scanner)
0820 {
0821     synctex_node_free(scanner->handle);
0822 }
0823 SYNCTEX_INLINE static void __synctex_scanner_remove_handle_to(synctex_node_p node)
0824 {
0825     synctex_node_p arg_sibling = NULL;
0826     synctex_node_p handle = node->class->scanner->handle;
0827     while (handle) {
0828         synctex_node_p sibling;
0829         if (node == _synctex_tree_target(handle)) {
0830             sibling = __synctex_tree_reset_sibling(handle);
0831             if (arg_sibling) {
0832                 __synctex_tree_set_sibling(arg_sibling, sibling);
0833             } else {
0834                 node->class->scanner->handle = sibling;
0835             }
0836             synctex_node_free(handle);
0837             break;
0838         } else {
0839             sibling = __synctex_tree_sibling(handle);
0840         }
0841         arg_sibling = handle;
0842         handle = sibling;
0843     }
0844 }
0845 SYNCTEX_INLINE static void __synctex_scanner_register_handle_to(synctex_node_p node)
0846 {
0847     synctex_node_p NNN = _synctex_new_handle_with_target(node);
0848     __synctex_tree_set_sibling(NNN, node->class->scanner->handle);
0849     node->class->scanner->handle = NNN;
0850 }
0851 #endif
0852 #if defined SYNCTEX_USE_NODE_COUNT && SYNCTEX_USE_NODE_COUNT > 10
0853 SYNCTEX_INLINE static void _synctex_did_new(synctex_node_p node)
0854 {
0855     printf("NODE CREATED # %i, %s, %p\n", (node->class->scanner->node_count)++, synctex_node_isa(node), node);
0856 }
0857 SYNCTEX_INLINE static void _synctex_will_free(synctex_node_p node)
0858 {
0859     printf("NODE DELETED # %i, %s, %p\n", --(node->class->scanner->node_count), synctex_node_isa(node), node);
0860 }
0861 #endif
0862 
0863 /**
0864  *  Free the given node.
0865  *  - parameter node: of type synctex_node_p
0866  *  - note: a node is meant to own its child and sibling.
0867  *  It is not owned by its parent, unless it is its first child.
0868  *  This destructor is for all nodes with children.
0869  */
0870 static void _synctex_free_node(synctex_node_p node)
0871 {
0872     if (node) {
0873         SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node);
0874         SYNCTEX_WILL_FREE(node);
0875         synctex_node_free(__synctex_tree_sibling(node));
0876         synctex_node_free(_synctex_tree_child(node));
0877         _synctex_free(node);
0878     }
0879     return;
0880 }
0881 
0882 /**
0883  *  Free the given leaf node.
0884  *  - parameter node: of type synctex_node_p, with no child nor sibling.
0885  *  - note: a node is meant to own its child and sibling.
0886  *  It is not owned by its parent, unless it is its first child.
0887  *  This destructor is for all nodes with no children.
0888  */
0889 static void _synctex_free_leaf(synctex_node_p node)
0890 {
0891     if (node) {
0892         SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node);
0893         SYNCTEX_WILL_FREE(node);
0894         synctex_node_free(__synctex_tree_sibling(node));
0895         _synctex_free(node);
0896     }
0897     return;
0898 }
0899 
0900 /**
0901  SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts
0902  */
0903 #define SYNCTEX_CUR (scanner->reader->current)
0904 #define SYNCTEX_START (scanner->reader->start)
0905 #define SYNCTEX_END (scanner->reader->end)
0906 
0907 /*  Here are gathered all the possible status that the next scanning functions will return.
0908  *  All these functions return a status, and pass their result through pointers.
0909  *  Negative values correspond to errors.
0910  *  The management of the buffer is causing some significant overhead.
0911  *  Every function that may access the buffer returns a status related to the buffer and file state.
0912  *  status >= SYNCTEX_STATUS_OK means the function worked as expected
0913  *  status < SYNCTEX_STATUS_OK means the function did not work as expected
0914  *  status == SYNCTEX_STATUS_NOT_OK means the function did not work as expected but there is still some material to parse.
0915  *  status == SYNCTEX_STATUS_EOF means the function did not work as expected and there is no more material.
0916  *  status<SYNCTEX_STATUS_EOF means an error
0917  */
0918 #if defined(SYNCTEX_USE_CHARINDEX)
0919 synctex_node_p synctex_scanner_handle(synctex_scanner_p scanner)
0920 {
0921     return scanner ? scanner->handle : NULL;
0922 }
0923 #endif
0924 
0925 #ifdef SYNCTEX_NOTHING
0926 #pragma mark -
0927 #pragma mark Decoding prototypes
0928 #endif
0929 
0930 typedef struct {
0931     int integer;
0932     synctex_status_t status;
0933 } synctex_is_s;
0934 
0935 static synctex_is_s _synctex_decode_int(synctex_scanner_p scanner);
0936 static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value);
0937 static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner);
0938 
0939 typedef struct {
0940     char *string;
0941     synctex_status_t status;
0942 } synctex_ss_s;
0943 
0944 static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner);
0945 
0946 #ifdef SYNCTEX_NOTHING
0947 #pragma mark -
0948 #pragma mark Data SETGET
0949 #endif
0950 
0951 /**
0952  *  The next macros are used to access the node data info
0953  *  through the class modelator integer fields.
0954  *  - parameter NODE: of type synctex_node_p
0955  */
0956 #define SYNCTEX_DATA(NODE) ((*((((NODE)->class))->info))(NODE))
0957 #if defined SYNCTEX_DEBUG > 1000
0958 #define DEFINE_SYNCTEX_DATA_HAS(WHAT)                                                                                                                                                                                                          \
0959     SYNCTEX_INLINE static synctex_bool_t __synctex_data_has_##WHAT(synctex_node_p node)                                                                                                                                                        \
0960     {                                                                                                                                                                                                                                          \
0961         return (node && (node->class->modelator->WHAT >= 0));                                                                                                                                                                                  \
0962     }                                                                                                                                                                                                                                          \
0963     SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node)                                                                                                                                                         \
0964     {                                                                                                                                                                                                                                          \
0965         if (node && (node->class->modelator->WHAT < 0)) {                                                                                                                                                                                      \
0966             printf("WARNING: NO %s for %s\n", #WHAT, synctex_node_isa(node));                                                                                                                                                                  \
0967         }                                                                                                                                                                                                                                      \
0968         return __synctex_data_has_##WHAT(node);                                                                                                                                                                                                \
0969     }
0970 #else
0971 #define DEFINE_SYNCTEX_DATA_HAS(WHAT)                                                                                                                                                                                                          \
0972     SYNCTEX_INLINE static synctex_bool_t __synctex_data_has_##WHAT(synctex_node_p node)                                                                                                                                                        \
0973     {                                                                                                                                                                                                                                          \
0974         return (node && (node->class->modelator->WHAT >= 0));                                                                                                                                                                                  \
0975     }                                                                                                                                                                                                                                          \
0976     SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node)                                                                                                                                                         \
0977     {                                                                                                                                                                                                                                          \
0978         return __synctex_data_has_##WHAT(node);                                                                                                                                                                                                \
0979     }
0980 #endif
0981 
0982 SYNCTEX_INLINE static synctex_data_p __synctex_data(synctex_node_p node)
0983 {
0984     return node->data + node->class->navigator->size;
0985 }
0986 #define DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT)                                                                                                                                                                                                   \
0987     DEFINE_SYNCTEX_DATA_HAS(WHAT)                                                                                                                                                                                                              \
0988     static int _synctex_data_##WHAT(synctex_node_p node)                                                                                                                                                                                       \
0989     {                                                                                                                                                                                                                                          \
0990         if (_synctex_data_has_##WHAT(node)) {                                                                                                                                                                                                  \
0991             return __synctex_data(node)[node->class->modelator->WHAT].as_integer;                                                                                                                                                              \
0992         }                                                                                                                                                                                                                                      \
0993         return 0;                                                                                                                                                                                                                              \
0994     }                                                                                                                                                                                                                                          \
0995     static int _synctex_data_set_##WHAT(synctex_node_p node, int new_value)                                                                                                                                                                    \
0996     {                                                                                                                                                                                                                                          \
0997         int old = 0;                                                                                                                                                                                                                           \
0998         if (_synctex_data_has_##WHAT(node)) {                                                                                                                                                                                                  \
0999             old = __synctex_data(node)[node->class->modelator->WHAT].as_integer;                                                                                                                                                               \
1000             __synctex_data(node)[node->class->modelator->WHAT].as_integer = new_value;                                                                                                                                                         \
1001         }                                                                                                                                                                                                                                      \
1002         return old;                                                                                                                                                                                                                            \
1003     }
1004 #define DEFINE_SYNCTEX_DATA_INT_DECODE(WHAT)                                                                                                                                                                                                   \
1005     static synctex_status_t _synctex_data_decode_##WHAT(synctex_node_p node)                                                                                                                                                                   \
1006     {                                                                                                                                                                                                                                          \
1007         if (_synctex_data_has_##WHAT(node)) {                                                                                                                                                                                                  \
1008             synctex_is_s is = _synctex_decode_int(node->class->scanner);                                                                                                                                                                       \
1009             if (is.status == SYNCTEX_STATUS_OK) {                                                                                                                                                                                              \
1010                 _synctex_data_set_##WHAT(node, is.integer);                                                                                                                                                                                    \
1011             }                                                                                                                                                                                                                                  \
1012             return is.status;                                                                                                                                                                                                                  \
1013         }                                                                                                                                                                                                                                      \
1014         return SYNCTEX_STATUS_BAD_ARGUMENT;                                                                                                                                                                                                    \
1015     }
1016 #define DEFINE_SYNCTEX_DATA_INT_DECODE_v(WHAT)                                                                                                                                                                                                 \
1017     static synctex_status_t _synctex_data_decode_##WHAT##_v(synctex_node_p node)                                                                                                                                                               \
1018     {                                                                                                                                                                                                                                          \
1019         if (_synctex_data_has_##WHAT(node)) {                                                                                                                                                                                                  \
1020             synctex_is_s is = _synctex_decode_int_v(node->class->scanner);                                                                                                                                                                     \
1021             if (is.status == SYNCTEX_STATUS_OK) {                                                                                                                                                                                              \
1022                 _synctex_data_set_##WHAT(node, is.integer);                                                                                                                                                                                    \
1023             }                                                                                                                                                                                                                                  \
1024             return is.status;                                                                                                                                                                                                                  \
1025         }                                                                                                                                                                                                                                      \
1026         return SYNCTEX_STATUS_BAD_ARGUMENT;                                                                                                                                                                                                    \
1027     }
1028 #define DEFINE_SYNCTEX_DATA_STR_GETSET(WHAT)                                                                                                                                                                                                   \
1029     DEFINE_SYNCTEX_DATA_HAS(WHAT)                                                                                                                                                                                                              \
1030     static char *_synctex_data_##WHAT(synctex_node_p node)                                                                                                                                                                                     \
1031     {                                                                                                                                                                                                                                          \
1032         if (_synctex_data_has_##WHAT(node)) {                                                                                                                                                                                                  \
1033             return node->data[node->class->navigator->size + node->class->modelator->WHAT].as_string;                                                                                                                                          \
1034         }                                                                                                                                                                                                                                      \
1035         return NULL;                                                                                                                                                                                                                           \
1036     }                                                                                                                                                                                                                                          \
1037     static const char *_synctex_data_set_##WHAT(synctex_node_p node, char *new_value)                                                                                                                                                          \
1038     {                                                                                                                                                                                                                                          \
1039         const char *old = "";                                                                                                                                                                                                                  \
1040         if (_synctex_data_has_##WHAT(node)) {                                                                                                                                                                                                  \
1041             old = node->data[node->class->navigator->size + node->class->modelator->WHAT].as_string;                                                                                                                                           \
1042             node->data[node->class->navigator->size + node->class->modelator->WHAT].as_string = new_value;                                                                                                                                     \
1043         }                                                                                                                                                                                                                                      \
1044         return old;                                                                                                                                                                                                                            \
1045     }
1046 #define DEFINE_SYNCTEX_DATA_STR_DECODE(WHAT)                                                                                                                                                                                                   \
1047     static synctex_status_t _synctex_data_decode_##WHAT(synctex_node_p node)                                                                                                                                                                   \
1048     {                                                                                                                                                                                                                                          \
1049         if (_synctex_data_has_##WHAT(node)) {                                                                                                                                                                                                  \
1050             synctex_ss_s ss = _synctex_decode_string(node->class->scanner);                                                                                                                                                                    \
1051             if (ss.status == SYNCTEX_STATUS_OK) {                                                                                                                                                                                              \
1052                 _synctex_data_set_##WHAT(node, ss.string);                                                                                                                                                                                     \
1053             }                                                                                                                                                                                                                                  \
1054             return ss.status;                                                                                                                                                                                                                  \
1055         }                                                                                                                                                                                                                                      \
1056         return SYNCTEX_STATUS_BAD_ARGUMENT;                                                                                                                                                                                                    \
1057     }
1058 #define DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(WHAT)                                                                                                                                                                                            \
1059     DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT)                                                                                                                                                                                                       \
1060     DEFINE_SYNCTEX_DATA_INT_DECODE(WHAT)
1061 #define DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE_v(WHAT)                                                                                                                                                                                          \
1062     DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT)                                                                                                                                                                                                       \
1063     DEFINE_SYNCTEX_DATA_INT_DECODE_v(WHAT)
1064 #define DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(WHAT)                                                                                                                                                                                            \
1065     DEFINE_SYNCTEX_DATA_STR_GETSET(WHAT)                                                                                                                                                                                                       \
1066     DEFINE_SYNCTEX_DATA_STR_DECODE(WHAT)
1067 
1068 #ifdef SYNCTEX_NOTHING
1069 #pragma mark -
1070 #pragma mark OBJECTS, their creators and destructors.
1071 #endif
1072 
1073 #ifdef SYNCTEX_NOTHING
1074 #pragma mark input.
1075 #endif
1076 
1077 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(tag)
1078 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(line)
1079 DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(name)
1080 
1081 /*  Input nodes only know about their sibling, which is another input node.
1082  *  The synctex information is the _synctex_data_tag and _synctex_data_name
1083  *  note: the input owns its name. */
1084 
1085 #define SYNCTEX_INPUT_MARK "Input:"
1086 
1087 static const synctex_tree_model_s synctex_tree_model_input = {synctex_tree_sibling_idx, /* sibling */
1088                                                               -1,                       /* parent */
1089                                                               -1,                       /* child */
1090                                                               -1,                       /* friend */
1091                                                               -1,                       /* last */
1092                                                               -1,                       /* next_hbox */
1093                                                               -1,                       /* arg_sibling */
1094                                                               -1,                       /* target */
1095                                                               synctex_tree_s_input_max};
1096 static const synctex_data_model_s synctex_data_model_input = {synctex_data_input_tag_idx,  /* tag */
1097                                                               synctex_data_input_line_idx, /* line */
1098                                                               -1,                          /* column */
1099                                                               -1,                          /* h */
1100                                                               -1,                          /* v */
1101                                                               -1,                          /* width */
1102                                                               -1,                          /* height */
1103                                                               -1,                          /* depth */
1104                                                               -1,                          /* mean_line */
1105                                                               -1,                          /* weight */
1106                                                               -1,                          /* h_V */
1107                                                               -1,                          /* v_V */
1108                                                               -1,                          /* width_V */
1109                                                               -1,                          /* height_V */
1110                                                               -1,                          /* depth_V */
1111                                                               synctex_data_input_name_idx, /* name */
1112                                                               -1,                          /* page */
1113                                                               synctex_data_input_tln_max};
1114 
1115 #define SYNCTEX_INSPECTOR_GETTER_F(WHAT) &_synctex_data_##WHAT, &_synctex_data_set_##WHAT
1116 
1117 static synctex_node_p _synctex_new_input(synctex_scanner_p scanner);
1118 static void _synctex_free_input(synctex_node_p node);
1119 static void _synctex_log_input(synctex_node_p node);
1120 static char *_synctex_abstract_input(synctex_node_p node);
1121 static void _synctex_display_input(synctex_node_p node);
1122 
1123 static const synctex_tlcpector_s synctex_tlcpector_input = {
1124     &_synctex_data_tag, /* tag */
1125     &_synctex_int_none, /* line */
1126     &_synctex_int_none, /* column */
1127 };
1128 
1129 static synctex_class_s synctex_class_input = {
1130     NULL,                      /*  No scanner yet */
1131     synctex_node_type_input,   /*  Node type */
1132     &_synctex_new_input,       /*  creator */
1133     &_synctex_free_input,      /*  destructor */
1134     &_synctex_log_input,       /*  log */
1135     &_synctex_display_input,   /*  display */
1136     &_synctex_abstract_input,  /*  abstract */
1137     &synctex_tree_model_input, /*  tree model */
1138     &synctex_data_model_input, /*  data model */
1139     &synctex_tlcpector_input,  /*  inspector */
1140     &synctex_inspector_none,   /*  inspector */
1141     &synctex_vispector_none,   /*  vispector */
1142 };
1143 
1144 typedef struct {
1145     SYNCTEX_DECLARE_CHARINDEX
1146     synctex_class_p class;
1147     synctex_data_u data[synctex_tree_s_input_max + synctex_data_input_tln_max];
1148 } synctex_input_s;
1149 
1150 static synctex_node_p _synctex_new_input(synctex_scanner_p scanner)
1151 {
1152     if (scanner) {
1153         synctex_node_p node = _synctex_malloc(sizeof(synctex_input_s));
1154         if (node) {
1155             node->class = scanner->class + synctex_node_type_input;
1156             SYNCTEX_DID_NEW(node);
1157             SYNCTEX_IMPLEMENT_CHARINDEX(node, 0);
1158             SYNCTEX_REGISTER_HANDLE_TO(node);
1159         }
1160         return node;
1161     }
1162     return NULL;
1163 }
1164 
1165 static void _synctex_free_input(synctex_node_p node)
1166 {
1167     if (node) {
1168         SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node);
1169         SYNCTEX_WILL_FREE(node);
1170         synctex_node_free(__synctex_tree_sibling(node));
1171         _synctex_free(_synctex_data_name(node));
1172         _synctex_free(node);
1173     }
1174 }
1175 
1176 /*  The sheet is a first level node.
1177  *  It has no parent (the owner is the scanner itself)
1178  *  Its sibling points to another sheet.
1179  *  Its child points to its first child, in general a box.
1180  *  A sheet node contains only one synctex information: the page.
1181  *  This is the 1 based page index as given by TeX.
1182  */
1183 
1184 #ifdef SYNCTEX_NOTHING
1185 #pragma mark sheet.
1186 #endif
1187 /**
1188  *  Every node has the same structure, but not the same size.
1189  */
1190 
1191 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(page)
1192 
1193 typedef struct {
1194     SYNCTEX_DECLARE_CHARINDEX
1195     synctex_class_p class;
1196     synctex_data_u data[synctex_tree_scn_sheet_max + synctex_data_p_sheet_max];
1197 } synctex_node_sheet_s;
1198 
1199 /*  sheet node creator */
1200 
1201 #define DEFINE_synctex_new_scanned_NODE(NAME)                                                                                                                                                                                                  \
1202     static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner)                                                                                                                                                                       \
1203     {                                                                                                                                                                                                                                          \
1204         if (scanner) {                                                                                                                                                                                                                         \
1205             ++SYNCTEX_CUR;                                                                                                                                                                                                                     \
1206             synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));                                                                                                                                                            \
1207             if (node) {                                                                                                                                                                                                                        \
1208                 node->class = scanner->class + synctex_node_type_##NAME;                                                                                                                                                                       \
1209                 SYNCTEX_DID_NEW(node);                                                                                                                                                                                                         \
1210                 SYNCTEX_IMPLEMENT_CHARINDEX(node, -1);                                                                                                                                                                                         \
1211                 SYNCTEX_REGISTER_HANDLE_TO(node);                                                                                                                                                                                              \
1212             }                                                                                                                                                                                                                                  \
1213             return node;                                                                                                                                                                                                                       \
1214         }                                                                                                                                                                                                                                      \
1215         return NULL;                                                                                                                                                                                                                           \
1216     }
1217 /*  NB: -1 in SYNCTEX_IMPLEMENT_CHARINDEX above because
1218  *  the first char of the line has been scanned
1219  */
1220 DEFINE_synctex_new_scanned_NODE(sheet) static void _synctex_log_sheet(synctex_node_p node);
1221 static char *_synctex_abstract_sheet(synctex_node_p node);
1222 static void _synctex_display_sheet(synctex_node_p node);
1223 
1224 static const synctex_tree_model_s synctex_tree_model_sheet = {synctex_tree_sibling_idx,      /* sibling */
1225                                                               -1,                            /* parent */
1226                                                               synctex_tree_s_child_idx,      /* child */
1227                                                               -1,                            /* friend */
1228                                                               -1,                            /* last */
1229                                                               synctex_tree_sc_next_hbox_idx, /* next_hbox */
1230                                                               -1,                            /* arg_sibling */
1231                                                               -1,                            /* target */
1232                                                               synctex_tree_scn_sheet_max};
1233 static const synctex_data_model_s synctex_data_model_sheet = {-1,                          /* tag */
1234                                                               -1,                          /* line */
1235                                                               -1,                          /* column */
1236                                                               -1,                          /* h */
1237                                                               -1,                          /* v */
1238                                                               -1,                          /* width */
1239                                                               -1,                          /* height */
1240                                                               -1,                          /* depth */
1241                                                               -1,                          /* mean_line */
1242                                                               -1,                          /* weight */
1243                                                               -1,                          /* h_V */
1244                                                               -1,                          /* v_V */
1245                                                               -1,                          /* width_V */
1246                                                               -1,                          /* height_V */
1247                                                               -1,                          /* depth_V */
1248                                                               -1,                          /* name */
1249                                                               synctex_data_sheet_page_idx, /* page */
1250                                                               synctex_data_p_sheet_max};
1251 static synctex_class_s synctex_class_sheet = {
1252     NULL,                      /*  No scanner yet */
1253     synctex_node_type_sheet,   /*  Node type */
1254     &_synctex_new_sheet,       /*  creator */
1255     &_synctex_free_node,       /*  destructor */
1256     &_synctex_log_sheet,       /*  log */
1257     &_synctex_display_sheet,   /*  display */
1258     &_synctex_abstract_sheet,  /*  abstract */
1259     &synctex_tree_model_sheet, /*  tree model */
1260     &synctex_data_model_sheet, /*  data model */
1261     &synctex_tlcpector_none,   /*  tlcpector */
1262     &synctex_inspector_none,   /*  inspector */
1263     &synctex_vispector_none,   /*  vispector */
1264 };
1265 
1266 #ifdef SYNCTEX_NOTHING
1267 #pragma mark form.
1268 #endif
1269 /**
1270  *  Every node has the same structure, but not the same size.
1271  */
1272 typedef struct {
1273     SYNCTEX_DECLARE_CHARINDEX
1274     synctex_class_p class;
1275     synctex_data_u data[synctex_tree_sct_form_max + synctex_data_t_form_max];
1276 } synctex_node_form_s;
1277 
1278 DEFINE_synctex_new_scanned_NODE(form)
1279 
1280     static char *_synctex_abstract_form(synctex_node_p node);
1281 static void _synctex_display_form(synctex_node_p node);
1282 static void _synctex_log_form(synctex_node_p node);
1283 
1284 static const synctex_tree_model_s synctex_tree_model_form = {synctex_tree_sibling_idx,   /* sibling */
1285                                                              -1,                         /* parent */
1286                                                              synctex_tree_s_child_idx,   /* child */
1287                                                              -1,                         /* friend */
1288                                                              -1,                         /* last */
1289                                                              -1,                         /* next_hbox */
1290                                                              -1,                         /* arg_sibling */
1291                                                              synctex_tree_sc_target_idx, /* target */
1292                                                              synctex_tree_sct_form_max};
1293 static const synctex_data_model_s synctex_data_model_form = {synctex_data_form_tag_idx, /* tag */
1294                                                              -1,                        /* line */
1295                                                              -1,                        /* column */
1296                                                              -1,                        /* h */
1297                                                              -1,                        /* v */
1298                                                              -1,                        /* width */
1299                                                              -1,                        /* height */
1300                                                              -1,                        /* depth */
1301                                                              -1,                        /* mean_line */
1302                                                              -1,                        /* weight */
1303                                                              -1,                        /* h_V */
1304                                                              -1,                        /* v_V */
1305                                                              -1,                        /* width_V */
1306                                                              -1,                        /* height_V */
1307                                                              -1,                        /* depth_V */
1308                                                              -1,                        /* name */
1309                                                              -1,                        /* page */
1310                                                              synctex_data_t_form_max};
1311 static synctex_class_s synctex_class_form = {
1312     NULL,                     /*  No scanner yet */
1313     synctex_node_type_form,   /*  Node type */
1314     &_synctex_new_form,       /*  creator */
1315     &_synctex_free_node,      /*  destructor */
1316     &_synctex_log_form,       /*  log */
1317     &_synctex_display_form,   /*  display */
1318     &_synctex_abstract_form,  /*  abstract */
1319     &synctex_tree_model_form, /*  tree model */
1320     &synctex_data_model_form, /*  data model */
1321     &synctex_tlcpector_none,  /*  tlcpector */
1322     &synctex_inspector_none,  /*  inspector */
1323     &synctex_vispector_none,  /*  vispector */
1324 };
1325 
1326 #ifdef SYNCTEX_NOTHING
1327 #pragma mark vbox.
1328 #endif
1329 
1330 /*  A box node contains navigation and synctex information
1331  *  There are different kinds of boxes.
1332  *  Only horizontal boxes are treated differently because of their visible size.
1333  */
1334 typedef struct {
1335     SYNCTEX_DECLARE_CHARINDEX
1336     synctex_class_p class;
1337     synctex_data_u data[synctex_tree_spcfl_vbox_max + synctex_data_box_max];
1338 } synctex_node_vbox_s;
1339 
1340 /*  vertical box node creator */
1341 DEFINE_synctex_new_scanned_NODE(vbox)
1342 
1343     static char *_synctex_abstract_vbox(synctex_node_p node);
1344 static void _synctex_display_vbox(synctex_node_p node);
1345 static void _synctex_log_vbox(synctex_node_p node);
1346 
1347 static const synctex_tree_model_s synctex_tree_model_vbox = {synctex_tree_sibling_idx,    /* sibling */
1348                                                              synctex_tree_s_parent_idx,   /* parent */
1349                                                              synctex_tree_sp_child_idx,   /* child */
1350                                                              synctex_tree_spc_friend_idx, /* friend */
1351                                                              synctex_tree_spcf_last_idx,  /* last */
1352                                                              -1,                          /* next_hbox */
1353                                                              -1,                          /* arg_sibling */
1354                                                              -1,                          /* target */
1355                                                              synctex_tree_spcfl_vbox_max};
1356 
1357 DEFINE_SYNCTEX_DATA_INT_GETSET(column)
1358 static synctex_status_t _synctex_data_decode_column(synctex_node_p node)
1359 {
1360     if (_synctex_data_has_column(node)) {
1361         synctex_is_s is = _synctex_decode_int_opt(node->class->scanner, -1);
1362         if (is.status == SYNCTEX_STATUS_OK) {
1363             _synctex_data_set_column(node, is.integer);
1364         }
1365         return is.status;
1366     }
1367     return SYNCTEX_STATUS_BAD_ARGUMENT;
1368 }
1369 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(h)
1370 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE_v(v) DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(width) DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(height) DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(depth)
1371 
1372     static const synctex_data_model_s synctex_data_model_box = {synctex_data_tag_idx,    /* tag */
1373                                                                 synctex_data_line_idx,   /* line */
1374                                                                 synctex_data_column_idx, /* column */
1375                                                                 synctex_data_h_idx,      /* h */
1376                                                                 synctex_data_v_idx,      /* v */
1377                                                                 synctex_data_width_idx,  /* width */
1378                                                                 synctex_data_height_idx, /* height */
1379                                                                 synctex_data_depth_idx,  /* depth */
1380                                                                 -1,                      /* mean_line */
1381                                                                 -1,                      /* weight */
1382                                                                 -1,                      /* h_V */
1383                                                                 -1,                      /* v_V */
1384                                                                 -1,                      /* width_V */
1385                                                                 -1,                      /* height_V */
1386                                                                 -1,                      /* depth_V */
1387                                                                 -1,                      /* name */
1388                                                                 -1,                      /* page */
1389                                                                 synctex_data_box_max};
1390 static const synctex_tlcpector_s synctex_tlcpector_default = {
1391     &_synctex_data_tag,    /* tag */
1392     &_synctex_data_line,   /* line */
1393     &_synctex_data_column, /* column */
1394 };
1395 static const synctex_inspector_s synctex_inspector_box = {
1396     &_synctex_data_h,
1397     &_synctex_data_v,
1398     &_synctex_data_width,
1399     &_synctex_data_height,
1400     &_synctex_data_depth,
1401 };
1402 static float __synctex_node_visible_h(synctex_node_p node);
1403 static float __synctex_node_visible_v(synctex_node_p node);
1404 static float __synctex_node_visible_width(synctex_node_p node);
1405 static float __synctex_node_visible_height(synctex_node_p node);
1406 static float __synctex_node_visible_depth(synctex_node_p node);
1407 static synctex_vispector_s synctex_vispector_box = {
1408     &__synctex_node_visible_h,
1409     &__synctex_node_visible_v,
1410     &__synctex_node_visible_width,
1411     &__synctex_node_visible_height,
1412     &__synctex_node_visible_depth,
1413 };
1414 /*  These are static class objects, each scanner will make a copy of them and setup the scanner field.
1415  */
1416 static synctex_class_s synctex_class_vbox = {
1417     NULL,                       /*  No scanner yet */
1418     synctex_node_type_vbox,     /*  Node type */
1419     &_synctex_new_vbox,         /*  creator */
1420     &_synctex_free_node,        /*  destructor */
1421     &_synctex_log_vbox,         /*  log */
1422     &_synctex_display_vbox,     /*  display */
1423     &_synctex_abstract_vbox,    /*  abstract */
1424     &synctex_tree_model_vbox,   /*  tree model */
1425     &synctex_data_model_box,    /*  data model */
1426     &synctex_tlcpector_default, /*  tlcpector */
1427     &synctex_inspector_box,     /*  inspector */
1428     &synctex_vispector_box,     /*  vispector */
1429 };
1430 
1431 #ifdef SYNCTEX_NOTHING
1432 #pragma mark hbox.
1433 #endif
1434 
1435 /*  Horizontal boxes must contain visible size, because 0 width does not mean emptiness.
1436  *  They also contain an average of the line numbers of the containing nodes. */
1437 
1438 static const synctex_tree_model_s synctex_tree_model_hbox = {synctex_tree_sibling_idx,         /* sibling */
1439                                                              synctex_tree_s_parent_idx,        /* parent */
1440                                                              synctex_tree_sp_child_idx,        /* child */
1441                                                              synctex_tree_spc_friend_idx,      /* friend */
1442                                                              synctex_tree_spcf_last_idx,       /* last */
1443                                                              synctex_tree_spcfl_next_hbox_idx, /* next_hbox */
1444                                                              -1,                               /* arg_sibling */
1445                                                              -1,                               /* target */
1446                                                              synctex_tree_spcfln_hbox_max};
1447 
1448 DEFINE_SYNCTEX_DATA_INT_GETSET(mean_line)
1449 DEFINE_SYNCTEX_DATA_INT_GETSET(weight)
1450 DEFINE_SYNCTEX_DATA_INT_GETSET(h_V)
1451 DEFINE_SYNCTEX_DATA_INT_GETSET(v_V)
1452 DEFINE_SYNCTEX_DATA_INT_GETSET(width_V)
1453 DEFINE_SYNCTEX_DATA_INT_GETSET(height_V)
1454 DEFINE_SYNCTEX_DATA_INT_GETSET(depth_V)
1455 
1456 /**
1457  *  The hbox model.
1458  *  It contains V variants of geometrical information.
1459  *  It happens that hboxes contain material that is not used to compute
1460  *  the bounding box. Some letters may appear out of the box given by TeX.
1461  *  In such a situation, the visible bounding box is bigger than the V variant.
1462  *  Only hboxes have such variant. It does not make sense for void boxes
1463  *  and it is not used here for vboxes.
1464  *  - author: JL
1465  */
1466 
1467 static const synctex_data_model_s synctex_data_model_hbox = {synctex_data_tag_idx,       /* tag */
1468                                                              synctex_data_line_idx,      /* line */
1469                                                              synctex_data_column_idx,    /* column */
1470                                                              synctex_data_h_idx,         /* h */
1471                                                              synctex_data_v_idx,         /* v */
1472                                                              synctex_data_width_idx,     /* width */
1473                                                              synctex_data_height_idx,    /* height */
1474                                                              synctex_data_depth_idx,     /* depth */
1475                                                              synctex_data_mean_line_idx, /* mean_line */
1476                                                              synctex_data_weight_idx,    /* weight */
1477                                                              synctex_data_h_V_idx,       /* h_V */
1478                                                              synctex_data_v_V_idx,       /* v_V */
1479                                                              synctex_data_width_V_idx,   /* width_V */
1480                                                              synctex_data_height_V_idx,  /* height_V */
1481                                                              synctex_data_depth_V_idx,   /* depth_V */
1482                                                              -1,                         /* name */
1483                                                              -1,                         /* page */
1484                                                              synctex_data_hbox_max};
1485 
1486 typedef struct {
1487     SYNCTEX_DECLARE_CHARINDEX
1488     synctex_class_p class;
1489     synctex_data_u data[synctex_tree_spcfln_hbox_max + synctex_data_hbox_max];
1490 } synctex_node_hbox_s;
1491 
1492 /*  horizontal box node creator */
1493 DEFINE_synctex_new_scanned_NODE(hbox)
1494 
1495     static void _synctex_log_hbox(synctex_node_p node);
1496 static char *_synctex_abstract_hbox(synctex_node_p node);
1497 static void _synctex_display_hbox(synctex_node_p node);
1498 
1499 static synctex_class_s synctex_class_hbox = {
1500     NULL,                       /*  No scanner yet */
1501     synctex_node_type_hbox,     /*  Node type */
1502     &_synctex_new_hbox,         /*  creator */
1503     &_synctex_free_node,        /*  destructor */
1504     &_synctex_log_hbox,         /*  log */
1505     &_synctex_display_hbox,     /*  display */
1506     &_synctex_abstract_hbox,    /*  abstract */
1507     &synctex_tree_model_hbox,   /*  tree model */
1508     &synctex_data_model_hbox,   /*  data model */
1509     &synctex_tlcpector_default, /*  tlcpector */
1510     &synctex_inspector_box,     /*  inspector */
1511     &synctex_vispector_box,     /*  vispector */
1512 };
1513 
1514 #ifdef SYNCTEX_NOTHING
1515 #pragma mark void vbox.
1516 #endif
1517 
1518 /*  This void box node implementation is either horizontal or vertical
1519  *  It does not contain a child field.
1520  */
1521 static const synctex_tree_model_s synctex_tree_model_spf = {synctex_tree_sibling_idx,   /* sibling */
1522                                                             synctex_tree_s_parent_idx,  /* parent */
1523                                                             -1,                         /* child */
1524                                                             synctex_tree_sp_friend_idx, /* friend */
1525                                                             -1,                         /* last */
1526                                                             -1,                         /* next_hbox */
1527                                                             -1,                         /* arg_sibling */
1528                                                             -1,                         /* target */
1529                                                             synctex_tree_spf_max};
1530 typedef struct {
1531     SYNCTEX_DECLARE_CHARINDEX
1532     synctex_class_p class;
1533     synctex_data_u data[synctex_tree_spf_max + synctex_data_box_max];
1534 } synctex_node_void_vbox_s;
1535 
1536 /*  vertical void box node creator */
1537 DEFINE_synctex_new_scanned_NODE(void_vbox)
1538 
1539     static void _synctex_log_void_box(synctex_node_p node);
1540 static char *_synctex_abstract_void_vbox(synctex_node_p node);
1541 static void _synctex_display_void_vbox(synctex_node_p node);
1542 
1543 static synctex_class_s synctex_class_void_vbox = {
1544     NULL,                         /*  No scanner yet */
1545     synctex_node_type_void_vbox,  /*  Node type */
1546     &_synctex_new_void_vbox,      /*  creator */
1547     &_synctex_free_leaf,          /*  destructor */
1548     &_synctex_log_void_box,       /*  log */
1549     &_synctex_display_void_vbox,  /*  display */
1550     &_synctex_abstract_void_vbox, /*  abstract */
1551     &synctex_tree_model_spf,      /*  tree model */
1552     &synctex_data_model_box,      /*  data model */
1553     &synctex_tlcpector_default,   /*  tlcpector */
1554     &synctex_inspector_box,       /*  inspector */
1555     &synctex_vispector_box,       /*  vispector */
1556 };
1557 
1558 #ifdef SYNCTEX_NOTHING
1559 #pragma mark void hbox.
1560 #endif
1561 
1562 typedef synctex_node_void_vbox_s synctex_node_void_hbox_s;
1563 
1564 /*  horizontal void box node creator */
1565 DEFINE_synctex_new_scanned_NODE(void_hbox)
1566 
1567     static char *_synctex_abstract_void_hbox(synctex_node_p node);
1568 static void _synctex_display_void_hbox(synctex_node_p node);
1569 
1570 static synctex_class_s synctex_class_void_hbox = {
1571     NULL,                         /*  No scanner yet */
1572     synctex_node_type_void_hbox,  /*  Node type */
1573     &_synctex_new_void_hbox,      /*  creator */
1574     &_synctex_free_leaf,          /*  destructor */
1575     &_synctex_log_void_box,       /*  log */
1576     &_synctex_display_void_hbox,  /*  display */
1577     &_synctex_abstract_void_hbox, /*  abstract */
1578     &synctex_tree_model_spf,      /*  tree model */
1579     &synctex_data_model_box,      /*  data model */
1580     &synctex_tlcpector_default,   /*  tlcpector */
1581     &synctex_inspector_box,       /*  inspector */
1582     &synctex_vispector_box,       /*  vispector */
1583 };
1584 
1585 #ifdef SYNCTEX_NOTHING
1586 #pragma mark form ref.
1587 #endif
1588 
1589 /*  The form ref node.  */
1590 typedef struct {
1591     SYNCTEX_DECLARE_CHARINDEX
1592     synctex_class_p class;
1593     synctex_data_u data[synctex_tree_spfa_max + synctex_data_ref_thv_max];
1594 } synctex_node_ref_s;
1595 
1596 /*  form ref node creator */
1597 DEFINE_synctex_new_scanned_NODE(ref)
1598 
1599     static void _synctex_log_ref(synctex_node_p node);
1600 static char *_synctex_abstract_ref(synctex_node_p node);
1601 static void _synctex_display_ref(synctex_node_p node);
1602 
1603 static const synctex_tree_model_s synctex_tree_model_spfa = {synctex_tree_sibling_idx,         /* sibling */
1604                                                              synctex_tree_s_parent_idx,        /* parent */
1605                                                              -1,                               /* child */
1606                                                              synctex_tree_sp_friend_idx,       /* friend */
1607                                                              -1,                               /* last */
1608                                                              -1,                               /* next_hbox */
1609                                                              synctex_tree_spf_arg_sibling_idx, /* arg_sibling */
1610                                                              -1,                               /* target */
1611                                                              synctex_tree_spfa_max};
1612 static const synctex_data_model_s synctex_data_model_ref = {synctex_data_tag_idx,   /* tag */
1613                                                             -1,                     /* line */
1614                                                             -1,                     /* column */
1615                                                             synctex_data_ref_h_idx, /* h */
1616                                                             synctex_data_ref_v_idx, /* v */
1617                                                             -1,                     /* width */
1618                                                             -1,                     /* height */
1619                                                             -1,                     /* depth */
1620                                                             -1,                     /* mean_line */
1621                                                             -1,                     /* weight */
1622                                                             -1,                     /* h_V */
1623                                                             -1,                     /* v_V */
1624                                                             -1,                     /* width_V */
1625                                                             -1,                     /* height_V */
1626                                                             -1,                     /* depth_V */
1627                                                             synctex_data_ref_thv_max};
1628 static synctex_class_s synctex_class_ref = {
1629     NULL,                     /*  No scanner yet */
1630     synctex_node_type_ref,    /*  Node type */
1631     &_synctex_new_ref,        /*  creator */
1632     &_synctex_free_leaf,      /*  destructor */
1633     &_synctex_log_ref,        /*  log */
1634     &_synctex_display_ref,    /*  display */
1635     &_synctex_abstract_ref,   /*  abstract */
1636     &synctex_tree_model_spfa, /*  navigator */
1637     &synctex_data_model_ref,  /*  data model */
1638     &synctex_tlcpector_none,  /*  tlcpector */
1639     &synctex_inspector_none,  /*  inspector */
1640     &synctex_vispector_none,  /*  vispector */
1641 };
1642 #ifdef SYNCTEX_NOTHING
1643 #pragma mark small node.
1644 #endif
1645 
1646 /*  The small nodes correspond to glue, penalty, math and boundary nodes. */
1647 static const synctex_data_model_s synctex_data_model_tlchv = {synctex_data_tag_idx,    /* tag */
1648                                                               synctex_data_line_idx,   /* line */
1649                                                               synctex_data_column_idx, /* column */
1650                                                               synctex_data_h_idx,      /* h */
1651                                                               synctex_data_v_idx,      /* v */
1652                                                               -1,                      /* width */
1653                                                               -1,                      /* height */
1654                                                               -1,                      /* depth */
1655                                                               -1,                      /* mean_line */
1656                                                               -1,                      /* weight */
1657                                                               -1,                      /* h_V */
1658                                                               -1,                      /* v_V */
1659                                                               -1,                      /* width_V */
1660                                                               -1,                      /* height_V */
1661                                                               -1,                      /* depth_V */
1662                                                               -1,                      /* name */
1663                                                               -1,                      /* page */
1664                                                               synctex_data_tlchv_max};
1665 
1666 typedef struct {
1667     SYNCTEX_DECLARE_CHARINDEX
1668     synctex_class_p class;
1669     synctex_data_u data[synctex_tree_spf_max + synctex_data_tlchv_max];
1670 } synctex_node_tlchv_s;
1671 
1672 static void _synctex_log_tlchv_node(synctex_node_p node);
1673 
1674 #ifdef SYNCTEX_NOTHING
1675 #pragma mark math.
1676 #endif
1677 
1678 typedef synctex_node_tlchv_s synctex_node_math_s;
1679 
1680 /*  math node creator */
1681 DEFINE_synctex_new_scanned_NODE(math)
1682 
1683     static char *_synctex_abstract_math(synctex_node_p node);
1684 static void _synctex_display_math(synctex_node_p node);
1685 static synctex_inspector_s synctex_inspector_hv = {
1686     &_synctex_data_h,
1687     &_synctex_data_v,
1688     &_synctex_int_none,
1689     &_synctex_int_none,
1690     &_synctex_int_none,
1691 };
1692 static synctex_vispector_s synctex_vispector_hv = {
1693     &__synctex_node_visible_h,
1694     &__synctex_node_visible_v,
1695     &_synctex_float_none,
1696     &_synctex_float_none,
1697     &_synctex_float_none,
1698 };
1699 
1700 static synctex_class_s synctex_class_math = {
1701     NULL,                       /*  No scanner yet */
1702     synctex_node_type_math,     /*  Node type */
1703     &_synctex_new_math,         /*  creator */
1704     &_synctex_free_leaf,        /*  destructor */
1705     &_synctex_log_tlchv_node,   /*  log */
1706     &_synctex_display_math,     /*  display */
1707     &_synctex_abstract_math,    /*  abstract */
1708     &synctex_tree_model_spf,    /*  tree model */
1709     &synctex_data_model_tlchv,  /*  data model */
1710     &synctex_tlcpector_default, /*  tlcpector */
1711     &synctex_inspector_hv,      /*  inspector */
1712     &synctex_vispector_hv,      /*  vispector */
1713 };
1714 
1715 #ifdef SYNCTEX_NOTHING
1716 #pragma mark kern node.
1717 #endif
1718 
1719 static const synctex_data_model_s synctex_data_model_tlchvw = {synctex_data_tag_idx,    /* tag */
1720                                                                synctex_data_line_idx,   /* line */
1721                                                                synctex_data_column_idx, /* column */
1722                                                                synctex_data_h_idx,      /* h */
1723                                                                synctex_data_v_idx,      /* v */
1724                                                                synctex_data_width_idx,  /* width */
1725                                                                -1,                      /* height */
1726                                                                -1,                      /* depth */
1727                                                                -1,                      /* mean_line */
1728                                                                -1,                      /* weight */
1729                                                                -1,                      /* h_V */
1730                                                                -1,                      /* v_V */
1731                                                                -1,                      /* width_V */
1732                                                                -1,                      /* height_V */
1733                                                                -1,                      /* depth_V */
1734                                                                -1,                      /* name */
1735                                                                -1,                      /* page */
1736                                                                synctex_data_tlchvw_max};
1737 typedef struct {
1738     SYNCTEX_DECLARE_CHARINDEX
1739     synctex_class_p class;
1740     synctex_data_u data[synctex_tree_spf_max + synctex_data_tlchvw_max];
1741 } synctex_node_kern_s;
1742 
1743 /*  kern node creator */
1744 DEFINE_synctex_new_scanned_NODE(kern)
1745 
1746     static void _synctex_log_kern_node(synctex_node_p node);
1747 static char *_synctex_abstract_kern(synctex_node_p node);
1748 static void _synctex_display_kern(synctex_node_p node);
1749 
1750 static synctex_inspector_s synctex_inspector_kern = {
1751     &_synctex_data_h,
1752     &_synctex_data_v,
1753     &_synctex_data_width,
1754     &_synctex_int_none,
1755     &_synctex_int_none,
1756 };
1757 static float __synctex_kern_visible_h(synctex_node_p node);
1758 static float __synctex_kern_visible_width(synctex_node_p node);
1759 static synctex_vispector_s synctex_vispector_kern = {
1760     &__synctex_kern_visible_h,
1761     &__synctex_node_visible_v,
1762     &__synctex_kern_visible_width,
1763     &_synctex_float_none,
1764     &_synctex_float_none,
1765 };
1766 
1767 static synctex_class_s synctex_class_kern = {
1768     NULL,                       /*  No scanner yet */
1769     synctex_node_type_kern,     /*  Node type */
1770     &_synctex_new_kern,         /*  creator */
1771     &_synctex_free_leaf,        /*  destructor */
1772     &_synctex_log_kern_node,    /*  log */
1773     &_synctex_display_kern,     /*  display */
1774     &_synctex_abstract_kern,    /*  abstract */
1775     &synctex_tree_model_spf,    /*  tree model */
1776     &synctex_data_model_tlchvw, /*  data model */
1777     &synctex_tlcpector_default, /*  tlcpector */
1778     &synctex_inspector_kern,    /*  inspector */
1779     &synctex_vispector_kern,    /*  vispector */
1780 };
1781 
1782 #ifdef SYNCTEX_NOTHING
1783 #pragma mark glue.
1784 #endif
1785 
1786 /*  glue node creator */
1787 typedef synctex_node_tlchv_s synctex_node_glue_s;
1788 DEFINE_synctex_new_scanned_NODE(glue)
1789 
1790     static char *_synctex_abstract_glue(synctex_node_p node);
1791 static void _synctex_display_glue(synctex_node_p node);
1792 
1793 static synctex_class_s synctex_class_glue = {
1794     NULL,                       /*  No scanner yet */
1795     synctex_node_type_glue,     /*  Node type */
1796     &_synctex_new_glue,         /*  creator */
1797     &_synctex_free_leaf,        /*  destructor */
1798     &_synctex_log_tlchv_node,   /*  log */
1799     &_synctex_display_glue,     /*  display */
1800     &_synctex_abstract_glue,    /*  abstract */
1801     &synctex_tree_model_spf,    /*  tree model */
1802     &synctex_data_model_tlchv,  /*  data model */
1803     &synctex_tlcpector_default, /*  tlcpector */
1804     &synctex_inspector_hv,      /*  inspector */
1805     &synctex_vispector_hv,      /*  vispector */
1806 };
1807 
1808 /*  The small nodes correspond to glue and boundary nodes.  */
1809 
1810 #ifdef SYNCTEX_NOTHING
1811 #pragma mark rule.
1812 #endif
1813 
1814 typedef struct {
1815     SYNCTEX_DECLARE_CHARINDEX
1816     synctex_class_p class;
1817     synctex_data_u data[synctex_tree_spf_max + synctex_data_box_max];
1818 } synctex_node_rule_s;
1819 
1820 DEFINE_synctex_new_scanned_NODE(rule)
1821 
1822     static void _synctex_log_rule(synctex_node_p node);
1823 static char *_synctex_abstract_rule(synctex_node_p node);
1824 static void _synctex_display_rule(synctex_node_p node);
1825 
1826 static float __synctex_rule_visible_h(synctex_node_p node);
1827 static float __synctex_rule_visible_v(synctex_node_p node);
1828 static float __synctex_rule_visible_width(synctex_node_p node);
1829 static float __synctex_rule_visible_height(synctex_node_p node);
1830 static float __synctex_rule_visible_depth(synctex_node_p node);
1831 static synctex_vispector_s synctex_vispector_rule = {
1832     &__synctex_rule_visible_h,
1833     &__synctex_rule_visible_v,
1834     &__synctex_rule_visible_width,
1835     &__synctex_rule_visible_height,
1836     &__synctex_rule_visible_depth,
1837 };
1838 
1839 static synctex_class_s synctex_class_rule = {
1840     NULL,                       /*  No scanner yet */
1841     synctex_node_type_rule,     /*  Node type */
1842     &_synctex_new_rule,         /*  creator */
1843     &_synctex_free_leaf,        /*  destructor */
1844     &_synctex_log_rule,         /*  log */
1845     &_synctex_display_rule,     /*  display */
1846     &_synctex_abstract_rule,    /*  abstract */
1847     &synctex_tree_model_spf,    /*  tree model */
1848     &synctex_data_model_box,    /*  data model */
1849     &synctex_tlcpector_default, /*  tlcpector */
1850     &synctex_inspector_box,     /*  inspector */
1851     &synctex_vispector_rule,    /*  vispector */
1852 };
1853 
1854 #ifdef SYNCTEX_NOTHING
1855 #pragma mark boundary.
1856 #endif
1857 
1858 /*  boundary node creator */
1859 typedef synctex_node_tlchv_s synctex_node_boundary_s;
1860 DEFINE_synctex_new_scanned_NODE(boundary)
1861 
1862     static char *_synctex_abstract_boundary(synctex_node_p node);
1863 static void _synctex_display_boundary(synctex_node_p node);
1864 
1865 static synctex_class_s synctex_class_boundary = {
1866     NULL,                        /*  No scanner yet */
1867     synctex_node_type_boundary,  /*  Node type */
1868     &_synctex_new_boundary,      /*  creator */
1869     &_synctex_free_leaf,         /*  destructor */
1870     &_synctex_log_tlchv_node,    /*  log */
1871     &_synctex_display_boundary,  /*  display */
1872     &_synctex_abstract_boundary, /*  abstract */
1873     &synctex_tree_model_spf,     /*  tree model */
1874     &synctex_data_model_tlchv,   /*  data model */
1875     &synctex_tlcpector_default,  /*  tlcpector */
1876     &synctex_inspector_hv,       /*  inspector */
1877     &synctex_vispector_hv,       /*  vispector */
1878 };
1879 
1880 #ifdef SYNCTEX_NOTHING
1881 #pragma mark box boundary.
1882 #endif
1883 
1884 typedef struct {
1885     SYNCTEX_DECLARE_CHARINDEX
1886     synctex_class_p class;
1887     synctex_data_u data[synctex_tree_spfa_max + synctex_data_tlchv_max];
1888 } synctex_node_box_bdry_s;
1889 
1890 #define DEFINE_synctex_new_unscanned_NODE(NAME)                                                                                                                                                                                                \
1891     SYNCTEX_INLINE static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner)                                                                                                                                                        \
1892     {                                                                                                                                                                                                                                          \
1893         if (scanner) {                                                                                                                                                                                                                         \
1894             synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));                                                                                                                                                            \
1895             if (node) {                                                                                                                                                                                                                        \
1896                 node->class = scanner->class + synctex_node_type_##NAME;                                                                                                                                                                       \
1897                 SYNCTEX_DID_NEW(node);                                                                                                                                                                                                         \
1898             }                                                                                                                                                                                                                                  \
1899             return node;                                                                                                                                                                                                                       \
1900         }                                                                                                                                                                                                                                      \
1901         return NULL;                                                                                                                                                                                                                           \
1902     }
1903 DEFINE_synctex_new_unscanned_NODE(box_bdry)
1904 
1905     static char *_synctex_abstract_box_bdry(synctex_node_p node);
1906 static void _synctex_display_box_bdry(synctex_node_p node);
1907 
1908 static synctex_class_s synctex_class_box_bdry = {
1909     NULL,                        /*  No scanner yet */
1910     synctex_node_type_box_bdry,  /*  Node type */
1911     &_synctex_new_box_bdry,      /*  creator */
1912     &_synctex_free_leaf,         /*  destructor */
1913     &_synctex_log_tlchv_node,    /*  log */
1914     &_synctex_display_box_bdry,  /*  display */
1915     &_synctex_abstract_box_bdry, /*  display */
1916     &synctex_tree_model_spfa,    /*  tree model */
1917     &synctex_data_model_tlchv,   /*  data model */
1918     &synctex_tlcpector_default,  /*  tlcpector */
1919     &synctex_inspector_hv,       /*  inspector */
1920     &synctex_vispector_hv,       /*  vispector */
1921 };
1922 
1923 #ifdef SYNCTEX_NOTHING
1924 #pragma mark hbox proxy.
1925 #endif
1926 
1927 /**
1928  *  Standard nodes refer to TeX nodes: math, kern, boxes...
1929  *  Proxy nodes are used to support forms.
1930  *  A form is parsed as a tree of standard nodes starting
1931  *  at the top left position.
1932  *  When a reference is used, the form is duplicated
1933  *  to the location specified by the reference.
1934  *  As the same form can be duplicated at different locations,
1935  *  the geometrical information is relative to its own top left point.
1936  *  As we need absolute locations, we use proxy nodes.
1937  *  A proxy node records an offset and the target node.
1938  *  The target partly acts as a delegate.
1939  *  The h and v position of the proxy node is the h and v
1940  *  position of the target shifted by the proxy's offset.
1941  *  The width, height and depth are not sensitive to offsets.
1942  *  When are proxies created ?
1943  *  1)  when the synctex file has been parsed, all the form refs
1944  *  are replaced by proxies to the content of a form.
1945  *  This content is a node with siblings (actually none).
1946  *  Those root proxies have the parent of the ref they replace,
1947  *  so their parents exist and are no proxy.
1948  *  Moreover, if they have no sibling, it means that their target have no
1949  *  sibling as well.
1950  *  Such nodes are called root proxies.
1951  *  2)  On the fly, when a proxy is asked for its child
1952  *  (or sibling) and has none, a proxy to its target's child
1953  *  (or sibling) is created if any. There are only 2 possible situations:
1954  *  either the newly created proxy is the child of a proxy,
1955  *  or it is the sibling of a proxy created on the fly.
1956  *  In both cases, the parent is a proxy with children.
1957  *  Such nodes are called child proxies.
1958  *  How to compute the offset of a proxy ?
1959  *  The offset of root proxy objects is exactly
1960  *  the offset of the ref they replace.
1961  *  The offset of other proxies is their owner's,
1962  *  except when pointing to a root proxy.
1963  *  What happens for cascading forms ?
1964  *  Here is an example diagram
1965  *
1966  *  At parse time, the arrow means "owns":
1967  *  sheet0 -> ref_to1
1968  *
1969  *            target1 -> ref_to2
1970  *
1971  *                       target2 -> child22
1972  *
1973  *  After replacing the refs:
1974  *  sheet0 -> proxy00 -> proxy01 -> proxy02
1975  *               |          |          |
1976  *            target1 -> proxy11 -> proxy12
1977  *                          |          |
1978  *                       target2 -> proxy22
1979  *
1980  *  proxy00, proxy11 and proxy22 are root proxies.
1981  *  Their offset is the one of the ref they replace
1982  *  proxy01, proxy02 and proxy12 are child proxies.
1983  *  Their proxy is the one of their parent.
1984  *  Optimization.
1985  *  After all the refs are replaced, there are only root nodes
1986  *  targeting standard node. We make sure that each child proxy
1987  *  also targets a standard node.
1988  *  It is possible for a proxy to have a standard sibling
1989  *  whereas its target has no sibling at all. Root proxies
1990  *  are such nodes, and are the only ones.
1991  *  The consequence is that proxies created on the fly
1992  *  must take into account this situation.
1993  */
1994 
1995 /*  A proxy to a hbox.
1996  *  A proxy do have a target, which can be a proxy
1997  */
1998 
1999 static const synctex_tree_model_s synctex_tree_model_proxy_hbox = {synctex_tree_sibling_idx,         /* sibling */
2000                                                                    synctex_tree_s_parent_idx,        /* parent */
2001                                                                    synctex_tree_sp_child_idx,        /* child */
2002                                                                    synctex_tree_spc_friend_idx,      /* friend */
2003                                                                    synctex_tree_spcf_last_idx,       /* last */
2004                                                                    synctex_tree_spcfl_next_hbox_idx, /* next_hbox */
2005                                                                    -1,                               /* arg_sibling */
2006                                                                    synctex_tree_spcfln_target_idx,   /* target */
2007                                                                    synctex_tree_spcflnt_proxy_hbox_max};
2008 static const synctex_data_model_s synctex_data_model_proxy = {-1,                       /* tag */
2009                                                               -1,                       /* line */
2010                                                               -1,                       /* column */
2011                                                               synctex_data_proxy_h_idx, /* h */
2012                                                               synctex_data_proxy_v_idx, /* v */
2013                                                               -1,                       /* width */
2014                                                               -1,                       /* height */
2015                                                               -1,                       /* depth */
2016                                                               -1,                       /* mean_line */
2017                                                               -1,                       /* weight */
2018                                                               -1,                       /* h_V */
2019                                                               -1,                       /* v_V */
2020                                                               -1,                       /* width_V */
2021                                                               -1,                       /* height_V */
2022                                                               -1,                       /* depth_V */
2023                                                               -1,                       /* name */
2024                                                               -1,                       /* page */
2025                                                               synctex_data_proxy_hv_max};
2026 typedef struct {
2027     SYNCTEX_DECLARE_CHARINDEX
2028     synctex_class_p class;
2029     synctex_data_u data[synctex_tree_spcflnt_proxy_hbox_max + synctex_data_proxy_hv_max];
2030 } synctex_node_proxy_hbox_s;
2031 
2032 /*  box proxy node creator */
2033 DEFINE_synctex_new_unscanned_NODE(proxy_hbox)
2034 
2035     static void _synctex_log_proxy(synctex_node_p node);
2036 static char *_synctex_abstract_proxy_hbox(synctex_node_p node);
2037 static void _synctex_display_proxy_hbox(synctex_node_p node);
2038 
2039 static int _synctex_proxy_tag(synctex_node_p);
2040 static int _synctex_proxy_line(synctex_node_p);
2041 static int _synctex_proxy_column(synctex_node_p);
2042 
2043 static synctex_tlcpector_s synctex_tlcpector_proxy = {
2044     &_synctex_proxy_tag,
2045     &_synctex_proxy_line,
2046     &_synctex_proxy_column,
2047 };
2048 static int _synctex_proxy_h(synctex_node_p);
2049 static int _synctex_proxy_v(synctex_node_p);
2050 static int _synctex_proxy_width(synctex_node_p);
2051 static int _synctex_proxy_height(synctex_node_p);
2052 static int _synctex_proxy_depth(synctex_node_p);
2053 static synctex_inspector_s synctex_inspector_proxy_box = {
2054     &_synctex_proxy_h,
2055     &_synctex_proxy_v,
2056     &_synctex_proxy_width,
2057     &_synctex_proxy_height,
2058     &_synctex_proxy_depth,
2059 };
2060 
2061 static float __synctex_proxy_visible_h(synctex_node_p);
2062 static float __synctex_proxy_visible_v(synctex_node_p);
2063 static float __synctex_proxy_visible_width(synctex_node_p);
2064 static float __synctex_proxy_visible_height(synctex_node_p);
2065 static float __synctex_proxy_visible_depth(synctex_node_p);
2066 
2067 static synctex_vispector_s synctex_vispector_proxy_box = {
2068     &__synctex_proxy_visible_h,
2069     &__synctex_proxy_visible_v,
2070     &__synctex_proxy_visible_width,
2071     &__synctex_proxy_visible_height,
2072     &__synctex_proxy_visible_depth,
2073 };
2074 
2075 static synctex_class_s synctex_class_proxy_hbox = {
2076     NULL,                           /*  No scanner yet */
2077     synctex_node_type_proxy_hbox,   /*  Node type */
2078     &_synctex_new_proxy_hbox,       /*  creator */
2079     &_synctex_free_node,            /*  destructor */
2080     &_synctex_log_proxy,            /*  log */
2081     &_synctex_display_proxy_hbox,   /*  display */
2082     &_synctex_abstract_proxy_hbox,  /*  abstract */
2083     &synctex_tree_model_proxy_hbox, /*  tree model */
2084     &synctex_data_model_proxy,      /*  data model */
2085     &synctex_tlcpector_proxy,       /*  tlcpector */
2086     &synctex_inspector_proxy_box,   /*  inspector */
2087     &synctex_vispector_proxy_box,   /*  vispector */
2088 };
2089 
2090 #ifdef SYNCTEX_NOTHING
2091 #pragma mark vbox proxy.
2092 #endif
2093 
2094 /*  A proxy to a vbox. */
2095 
2096 static const synctex_tree_model_s synctex_tree_model_proxy_vbox = {synctex_tree_sibling_idx,      /* sibling */
2097                                                                    synctex_tree_s_parent_idx,     /* parent */
2098                                                                    synctex_tree_sp_child_idx,     /* child */
2099                                                                    synctex_tree_spc_friend_idx,   /* friend */
2100                                                                    synctex_tree_spcf_last_idx,    /* last */
2101                                                                    -1,                            /* next_hbox */
2102                                                                    -1,                            /* arg_sibling */
2103                                                                    synctex_tree_spcfl_target_idx, /* target */
2104                                                                    synctex_tree_spcflt_proxy_vbox_max};
2105 
2106 typedef struct {
2107     SYNCTEX_DECLARE_CHARINDEX
2108     synctex_class_p class;
2109     synctex_data_u data[synctex_tree_spcflt_proxy_vbox_max + synctex_data_proxy_hv_max];
2110 } synctex_node_proxy_vbox_s;
2111 
2112 /*  box proxy node creator */
2113 DEFINE_synctex_new_unscanned_NODE(proxy_vbox)
2114 
2115     static void _synctex_log_proxy(synctex_node_p node);
2116 static char *_synctex_abstract_proxy_vbox(synctex_node_p node);
2117 static void _synctex_display_proxy_vbox(synctex_node_p node);
2118 
2119 static synctex_class_s synctex_class_proxy_vbox = {
2120     NULL,                           /*  No scanner yet */
2121     synctex_node_type_proxy_vbox,   /*  Node type */
2122     &_synctex_new_proxy_vbox,       /*  creator */
2123     &_synctex_free_node,            /*  destructor */
2124     &_synctex_log_proxy,            /*  log */
2125     &_synctex_display_proxy_vbox,   /*  display */
2126     &_synctex_abstract_proxy_vbox,  /*  abstract */
2127     &synctex_tree_model_proxy_vbox, /*  tree model */
2128     &synctex_data_model_proxy,      /*  data model */
2129     &synctex_tlcpector_proxy,       /*  tlcpector */
2130     &synctex_inspector_proxy_box,   /*  inspector */
2131     &synctex_vispector_proxy_box,   /*  vispector */
2132 };
2133 
2134 #ifdef SYNCTEX_NOTHING
2135 #pragma mark proxy.
2136 #endif
2137 
2138 /**
2139  *  A proxy to a node but a box.
2140  */
2141 
2142 static const synctex_tree_model_s synctex_tree_model_proxy = {synctex_tree_sibling_idx,    /* sibling */
2143                                                               synctex_tree_s_parent_idx,   /* parent */
2144                                                               -1,                          /* child */
2145                                                               synctex_tree_sp_friend_idx,  /* friend */
2146                                                               -1,                          /* last */
2147                                                               -1,                          /* next_hbox */
2148                                                               -1,                          /* arg_sibling */
2149                                                               synctex_tree_spf_target_idx, /* target */
2150                                                               synctex_tree_spft_proxy_max};
2151 
2152 typedef struct {
2153     SYNCTEX_DECLARE_CHARINDEX
2154     synctex_class_p class;
2155     synctex_data_u data[synctex_tree_spft_proxy_max + synctex_data_proxy_hv_max];
2156 } synctex_node_proxy_s;
2157 
2158 /*  proxy node creator */
2159 DEFINE_synctex_new_unscanned_NODE(proxy)
2160 
2161     static void _synctex_log_proxy(synctex_node_p node);
2162 static char *_synctex_abstract_proxy(synctex_node_p node);
2163 static void _synctex_display_proxy(synctex_node_p node);
2164 
2165 static synctex_vispector_s synctex_vispector_proxy = {
2166     &__synctex_proxy_visible_h,
2167     &__synctex_proxy_visible_v,
2168     &__synctex_proxy_visible_width,
2169     &_synctex_float_none,
2170     &_synctex_float_none,
2171 };
2172 
2173 static synctex_class_s synctex_class_proxy = {
2174     NULL,                         /*  No scanner yet */
2175     synctex_node_type_proxy,      /*  Node type */
2176     &_synctex_new_proxy,          /*  creator */
2177     &_synctex_free_leaf,          /*  destructor */
2178     &_synctex_log_proxy,          /*  log */
2179     &_synctex_display_proxy,      /*  display */
2180     &_synctex_abstract_proxy,     /*  abstract */
2181     &synctex_tree_model_proxy,    /*  tree model */
2182     &synctex_data_model_proxy,    /*  data model */
2183     &synctex_tlcpector_proxy,     /*  tlcpector */
2184     &synctex_inspector_proxy_box, /*  inspector */
2185     &synctex_vispector_proxy,     /*  vispector */
2186 };
2187 
2188 #ifdef SYNCTEX_NOTHING
2189 #pragma mark last proxy.
2190 #endif
2191 
2192 /**
2193  *  A proxy to the last proxy/box boundary.
2194  */
2195 
2196 static const synctex_tree_model_s synctex_tree_model_proxy_last = {synctex_tree_sibling_idx,         /* sibling */
2197                                                                    synctex_tree_s_parent_idx,        /* parent */
2198                                                                    -1,                               /* child */
2199                                                                    synctex_tree_sp_friend_idx,       /* friend */
2200                                                                    -1,                               /* last */
2201                                                                    -1,                               /* next_hbox */
2202                                                                    synctex_tree_spf_arg_sibling_idx, /* arg_sibling */
2203                                                                    synctex_tree_spfa_target_idx,     /* target */
2204                                                                    synctex_tree_spfat_proxy_last_max};
2205 
2206 typedef struct {
2207     SYNCTEX_DECLARE_CHARINDEX
2208     synctex_class_p class;
2209     synctex_data_u data[synctex_tree_spfat_proxy_last_max + synctex_data_proxy_hv_max];
2210 } synctex_node_proxy_last_s;
2211 
2212 /*  proxy node creator */
2213 DEFINE_synctex_new_unscanned_NODE(proxy_last)
2214 
2215     static void _synctex_log_proxy(synctex_node_p node);
2216 static char *_synctex_abstract_proxy(synctex_node_p node);
2217 static void _synctex_display_proxy(synctex_node_p node);
2218 
2219 static synctex_class_s synctex_class_proxy_last = {
2220     NULL,                           /*  No scanner yet */
2221     synctex_node_type_proxy_last,   /*  Node type */
2222     &_synctex_new_proxy,            /*  creator */
2223     &_synctex_free_leaf,            /*  destructor */
2224     &_synctex_log_proxy,            /*  log */
2225     &_synctex_display_proxy,        /*  display */
2226     &_synctex_abstract_proxy,       /*  abstract */
2227     &synctex_tree_model_proxy_last, /*  tree model */
2228     &synctex_data_model_proxy,      /*  data model */
2229     &synctex_tlcpector_proxy,       /*  tlcpector */
2230     &synctex_inspector_proxy_box,   /*  inspector */
2231     &synctex_vispector_proxy,       /*  vispector */
2232 };
2233 
2234 #ifdef SYNCTEX_NOTHING
2235 #pragma mark handle.
2236 #endif
2237 
2238 /**
2239  *  A result node.
2240  */
2241 
2242 static const synctex_tree_model_s synctex_tree_model_handle = {synctex_tree_sibling_idx,    /* sibling */
2243                                                                synctex_tree_s_parent_idx,   /* parent */
2244                                                                synctex_tree_sp_child_idx,   /* child */
2245                                                                -1,                          /* friend */
2246                                                                -1,                          /* last */
2247                                                                -1,                          /* next_hbox */
2248                                                                -1,                          /* arg_sibling */
2249                                                                synctex_tree_spc_target_idx, /* target */
2250                                                                synctex_tree_spct_handle_max};
2251 
2252 typedef struct {
2253     SYNCTEX_DECLARE_CHARINDEX
2254     synctex_class_p class;
2255     synctex_data_u data[synctex_tree_spct_handle_max + 0];
2256 } synctex_node_handle_s;
2257 
2258 /*  result node creator */
2259 DEFINE_synctex_new_unscanned_NODE(handle)
2260 
2261     static void _synctex_log_handle(synctex_node_p node);
2262 static char *_synctex_abstract_handle(synctex_node_p node);
2263 static void _synctex_display_handle(synctex_node_p node);
2264 
2265 static synctex_class_s synctex_class_handle = {
2266     NULL,                         /*  No scanner yet */
2267     synctex_node_type_handle,     /*  Node type */
2268     &_synctex_new_handle,         /*  creator */
2269     &_synctex_free_node,          /*  destructor */
2270     &_synctex_log_handle,         /*  log */
2271     &_synctex_display_handle,     /*  display */
2272     &_synctex_abstract_handle,    /*  abstract */
2273     &synctex_tree_model_handle,   /*  tree model */
2274     &synctex_data_model_none,     /*  data model */
2275     &synctex_tlcpector_proxy,     /*  tlcpector */
2276     &synctex_inspector_proxy_box, /*  inspector */
2277     &synctex_vispector_proxy_box, /*  vispector */
2278 };
2279 
2280 SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target)
2281 {
2282     if (target) {
2283         synctex_node_p result = _synctex_new_handle(target->class->scanner);
2284         if (result) {
2285             _synctex_tree_set_target(result, target);
2286             return result;
2287         }
2288     }
2289     return NULL;
2290 }
2291 
2292 #ifdef SYNCTEX_NOTHING
2293 #pragma mark -
2294 #pragma mark Navigation
2295 #endif
2296 synctex_node_p synctex_node_parent(synctex_node_p node)
2297 {
2298     return _synctex_tree_parent(node);
2299 }
2300 synctex_node_p synctex_node_parent_sheet(synctex_node_p node)
2301 {
2302     while (node && synctex_node_type(node) != synctex_node_type_sheet) {
2303         node = _synctex_tree_parent(node);
2304     }
2305     /*  exit the while loop either when node is NULL or node is a sheet */
2306     return node;
2307 }
2308 synctex_node_p synctex_node_parent_form(synctex_node_p node)
2309 {
2310     while (node && synctex_node_type(node) != synctex_node_type_form) {
2311         node = _synctex_tree_parent(node);
2312     }
2313     /*  exit the while loop either when node is NULL or node is a form */
2314     return node;
2315 }
2316 
2317 /**
2318  *  The returned proxy will be the child or a sibling of source.
2319  *  The returned proxy has no parent, child nor sibling.
2320  *  Used only by __synctex_replace_ref.
2321  *  argument to_node: a box, not a proxy nor anything else.
2322  */
2323 SYNCTEX_INLINE static synctex_node_p __synctex_new_proxy_from_ref_to(synctex_node_p ref, synctex_node_p to_node)
2324 {
2325     synctex_node_p proxy = NULL;
2326     if (!ref || !to_node) {
2327         return NULL;
2328     }
2329     switch (synctex_node_type(to_node)) {
2330     case synctex_node_type_vbox:
2331         proxy = _synctex_new_proxy_vbox(ref->class->scanner);
2332         break;
2333     case synctex_node_type_hbox:
2334         proxy = _synctex_new_proxy_hbox(ref->class->scanner);
2335         break;
2336     default:
2337         _synctex_error("!  __synctex_new_proxy_from_ref_to. Unexpected form child (%s). Please report.", synctex_node_isa(to_node));
2338         return NULL;
2339     }
2340     if (!proxy) {
2341         _synctex_error("!  __synctex_new_proxy_from_ref_to. Internal error. Please report.");
2342         return NULL;
2343     }
2344     _synctex_data_set_h(proxy, _synctex_data_h(ref));
2345     _synctex_data_set_v(proxy, _synctex_data_v(ref));
2346     _synctex_tree_set_target(proxy, to_node);
2347 #if defined(SYNCTEX_USE_CHARINDEX)
2348     proxy->line_index = to_node ? to_node->line_index : 0;
2349     proxy->char_index = to_node ? to_node->char_index : 0;
2350 #endif
2351     return proxy;
2352 }
2353 /**
2354  *  The returned proxy will be the child or a sibling of owning_proxy.
2355  *  The returned proxy has no parent, nor child.
2356  *  Used only by synctex_node_child and synctex_node_sibling
2357  *  to create proxies on the fly.
2358  *  If the to_node has an already computed sibling,
2359  *  then the returned proxy has itself a sibling
2360  *  pointing to that already computed sibling.
2361  */
2362 SYNCTEX_INLINE static synctex_node_p __synctex_new_child_proxy_to(synctex_node_p owner, synctex_node_p to_node)
2363 {
2364     synctex_node_p proxy = NULL;
2365     synctex_node_p target = to_node;
2366     if (!owner) {
2367         return NULL;
2368     }
2369     switch (synctex_node_type(target)) {
2370     case synctex_node_type_vbox:
2371         if ((proxy = _synctex_new_proxy_vbox(owner->class->scanner))) {
2372         exit_standard:
2373             _synctex_data_set_h(proxy, _synctex_data_h(owner));
2374             _synctex_data_set_v(proxy, _synctex_data_v(owner));
2375         exit0:
2376             _synctex_tree_set_target(proxy, target);
2377 #if defined(SYNCTEX_USE_CHARINDEX)
2378             proxy->line_index = to_node ? to_node->line_index : 0;
2379             proxy->char_index = to_node ? to_node->char_index : 0;
2380 #endif
2381             return proxy;
2382         };
2383         break;
2384     case synctex_node_type_proxy_vbox:
2385         if ((proxy = _synctex_new_proxy_vbox(owner->class->scanner))) {
2386         exit_proxy:
2387             target = _synctex_tree_target(to_node);
2388             _synctex_data_set_h(proxy, _synctex_data_h(owner) + _synctex_data_h(to_node));
2389             _synctex_data_set_v(proxy, _synctex_data_v(owner) + _synctex_data_v(to_node));
2390             goto exit0;
2391         };
2392         break;
2393     case synctex_node_type_hbox:
2394         if ((proxy = _synctex_new_proxy_hbox(owner->class->scanner))) {
2395             goto exit_standard;
2396         };
2397         break;
2398     case synctex_node_type_proxy_hbox:
2399         if ((proxy = _synctex_new_proxy_hbox(owner->class->scanner))) {
2400             goto exit_proxy;
2401         };
2402         break;
2403     case synctex_node_type_proxy:
2404     case synctex_node_type_proxy_last:
2405         if ((proxy = _synctex_new_proxy(owner->class->scanner))) {
2406             goto exit_proxy;
2407         };
2408         break;
2409     default:
2410         if ((proxy = _synctex_new_proxy(owner->class->scanner))) {
2411             goto exit_standard;
2412         };
2413         break;
2414     }
2415     _synctex_error(
2416         "!  __synctex_new_child_proxy_to. "
2417         "Internal error. "
2418         "Please report.");
2419     return NULL;
2420 }
2421 SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_sibling);
2422 typedef struct synctex_nns_t {
2423     synctex_node_p first;
2424     synctex_node_p last;
2425     synctex_status_t status;
2426 } synctex_nns_s;
2427 /**
2428  *  Given a target node, create a list of proxies.
2429  *  The first proxy points to the target node,
2430  *  its sibling points to the target's sibling and so on.
2431  *  Returns the first created proxy, the last one and
2432  *  an error status.
2433  */
2434 SYNCTEX_INLINE static synctex_nns_s _synctex_new_child_proxies_to(synctex_node_p owner, synctex_node_p to_node)
2435 {
2436     synctex_nns_s nns = {NULL, NULL, SYNCTEX_STATUS_OK};
2437     if ((nns.first = nns.last = __synctex_new_child_proxy_to(owner, to_node))) {
2438         synctex_node_p to_next_sibling = __synctex_tree_sibling(to_node);
2439         synctex_node_p to_sibling;
2440         while ((to_sibling = to_next_sibling)) {
2441             synctex_node_p sibling;
2442             if ((to_next_sibling = __synctex_tree_sibling(to_sibling))) {
2443                 /*  This is not the last sibling */
2444                 if ((sibling = __synctex_new_child_proxy_to(owner, to_sibling))) {
2445                     _synctex_tree_set_sibling(nns.last, sibling);
2446                     nns.last = sibling;
2447                     continue;
2448                 } else {
2449                     _synctex_error(
2450                         "!  _synctex_new_child_proxy_to. "
2451                         "Internal error (1). "
2452                         "Please report.");
2453                     nns.status = SYNCTEX_STATUS_ERROR;
2454                 }
2455             } else if ((sibling = _synctex_new_proxy_last(owner->class->scanner))) {
2456                 _synctex_tree_set_sibling(nns.last, sibling);
2457                 nns.last = sibling;
2458                 _synctex_data_set_h(nns.last, _synctex_data_h(nns.first));
2459                 _synctex_data_set_v(nns.last, _synctex_data_v(nns.first));
2460                 _synctex_tree_set_target(nns.last, to_sibling);
2461 #if defined(SYNCTEX_USE_CHARINDEX)
2462                 nns.last->line_index = to_sibling->line_index;
2463                 nns.last->char_index = to_sibling->char_index;
2464 #endif
2465             } else {
2466                 _synctex_error(
2467                     "!  _synctex_new_child_proxy_to. "
2468                     "Internal error (2). "
2469                     "Please report.");
2470                 nns.status = SYNCTEX_STATUS_ERROR;
2471             }
2472             break;
2473         }
2474     }
2475     return nns;
2476 }
2477 static const char *_synctex_node_abstract(synctex_node_p node);
2478 SYNCTEX_INLINE static synctex_node_p synctex_tree_set_friend(synctex_node_p node, synctex_node_p new_friend)
2479 {
2480 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG
2481     synctex_node_p F = new_friend;
2482     while (F) {
2483         if (node == F) {
2484             printf("THIS IS AN ERROR\n");
2485             F = new_friend;
2486             while (F) {
2487                 printf("%s\n", _synctex_node_abstract(F));
2488                 if (node == F) {
2489                     return NULL;
2490                 }
2491                 F = _synctex_tree_friend(F);
2492             }
2493             return NULL;
2494         }
2495         F = _synctex_tree_friend(F);
2496     }
2497 #endif
2498     return new_friend ? _synctex_tree_set_friend(node, new_friend) : _synctex_tree_reset_friend(node);
2499 }
2500 /**
2501  *
2502  */
2503 SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend(synctex_node_p node, int i)
2504 {
2505     synctex_node_p old = NULL;
2506     if (i >= 0) {
2507         i = i % (node->class->scanner->number_of_lists);
2508         old = synctex_tree_set_friend(node, (node->class->scanner->lists_of_friends)[i]);
2509         (node->class->scanner->lists_of_friends)[i] = node;
2510 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
2511         printf("tl(%i)=>", i);
2512         synctex_node_log(node);
2513         if (synctex_node_parent_form(node)) {
2514             printf("!  ERROR. No registration expected!\n");
2515         }
2516 #endif
2517     }
2518     return old;
2519 }
2520 /**
2521  *  All proxies have tlc attributes, on behalf of their target.
2522  *  The purpose is to register all af them.
2523  *  - argument node: is the proxy, must not be NULL
2524  */
2525 SYNCTEX_INLINE static synctex_node_p __synctex_proxy_make_friend_and_next_hbox(synctex_node_p node)
2526 {
2527     synctex_node_p old = NULL;
2528     synctex_node_p target = _synctex_tree_target(node);
2529     if (target) {
2530         int i = _synctex_data_tag(target) + _synctex_data_line(target);
2531         old = __synctex_node_make_friend(node, i);
2532     } else {
2533         old = __synctex_tree_reset_friend(node);
2534     }
2535     if (synctex_node_type(node) == synctex_node_type_proxy_hbox) {
2536         synctex_node_p sheet = synctex_node_parent_sheet(node);
2537         if (sheet) {
2538             _synctex_tree_set_next_hbox(node, _synctex_tree_next_hbox(sheet));
2539             _synctex_tree_set_next_hbox(sheet, node);
2540         }
2541     }
2542     return old;
2543 }
2544 /**
2545  *  Register a node which have tag, line and column.
2546  *  - argument node: the node
2547  */
2548 SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend_tlc(synctex_node_p node)
2549 {
2550     int i = synctex_node_tag(node) + synctex_node_line(node);
2551     return __synctex_node_make_friend(node, i);
2552 }
2553 /**
2554  *  Register a node which have tag, line and column.
2555  *  Does nothing if the argument is NULL.
2556  *  Calls __synctex_node_make_friend_tlc.
2557  *  - argument node: the node
2558  */
2559 SYNCTEX_INLINE static void _synctex_node_make_friend_tlc(synctex_node_p node)
2560 {
2561     if (node) {
2562         __synctex_node_make_friend_tlc(node);
2563     }
2564 }
2565 static synctex_node_p _synctex_node_set_child(synctex_node_p node, synctex_node_p new_child);
2566 /**
2567  *  The (first) child of the node, if any, NULL otherwise.
2568  *  At parse time, non void box nodes have children.
2569  *  All other nodes have no children.
2570  *  In order to support pdf forms, proxies are created
2571  *  to place form nodes at real locations.
2572  *  Ref nodes are replaced by root proxies targeting
2573  *  form contents. If root proxies have no children,
2574  *  they are created on the fly as proxies to the
2575  *  children of the targeted box.
2576  *  As such, proxies created here are targeting a
2577  *  node that belongs to a form.
2578  *  This is the only place where child proxies are created.
2579  */
2580 synctex_node_p synctex_node_child(synctex_node_p node)
2581 {
2582     synctex_node_p child = NULL;
2583     synctex_node_p target = NULL;
2584     if ((child = _synctex_tree_child(node))) {
2585         return child;
2586     } else if ((target = _synctex_tree_target(node))) {
2587         if ((child = synctex_node_child(target))) {
2588             /*  This is a proxy with no child
2589              *  which target does have a child. */
2590             synctex_nns_s nns = _synctex_new_child_proxies_to(node, child);
2591             if (nns.first) {
2592                 _synctex_node_set_child(node, nns.first);
2593                 return nns.first;
2594             } else {
2595                 _synctex_error("!  synctex_node_child. Internal inconsistency. Please report.");
2596             }
2597         }
2598     }
2599     return NULL;
2600 }
2601 /*
2602  *  Set the parent/child bound.
2603  *  Things get complicated when new_child has siblings.
2604  *  The caller is responsible for releasing the returned value.
2605  */
2606 static synctex_node_p _synctex_node_set_child(synctex_node_p parent, synctex_node_p new_child)
2607 {
2608     if (parent) {
2609         synctex_node_p old = _synctex_tree_set_child(parent, new_child);
2610         synctex_node_p last_child = NULL;
2611         synctex_node_p child;
2612         if ((child = old)) {
2613             do {
2614                 _synctex_tree_reset_parent(child);
2615             } while ((child = __synctex_tree_sibling(child)));
2616         }
2617         if ((child = new_child)) {
2618             do {
2619                 _synctex_tree_set_parent(child, parent);
2620                 last_child = child;
2621             } while ((child = __synctex_tree_sibling(child)));
2622         }
2623         _synctex_tree_set_last(parent, last_child);
2624         return old;
2625     }
2626     return NULL;
2627 }
2628 
2629 /*  The last child of the given node, or NULL.
2630  */
2631 synctex_node_p synctex_node_last_child(synctex_node_p node)
2632 {
2633     return _synctex_tree_last(node);
2634 }
2635 /**
2636  *  All nodes siblings are properly set up at parse time
2637  *  except for non root proxies.
2638  */
2639 synctex_node_p synctex_node_sibling(synctex_node_p node)
2640 {
2641     return node ? __synctex_tree_sibling(node) : NULL;
2642 }
2643 /**
2644  *  All the _synctex_tree_... methods refer to the tree model.
2645  *  __synctex_tree_... methods are low level.
2646  */
2647 /**
2648  *  Replace the sibling.
2649  *  Connect to the arg_sibling of the new_sibling if relevant.
2650  *  - returns the old sibling.
2651  *  The caller is responsible for releasing the old sibling.
2652  *  The bound to the parent is managed below.
2653  */
2654 SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_sibling)
2655 {
2656     if (node == new_sibling) {
2657         printf("BOF\n");
2658     }
2659     synctex_node_p old = node ? __synctex_tree_set_sibling(node, new_sibling) : NULL;
2660     _synctex_tree_set_arg_sibling(new_sibling, node);
2661     return old;
2662 }
2663 /**
2664  *  Replace the sibling.
2665  *  Set the parent of the new sibling (and further siblings)
2666  *  to the parent of the receiver.
2667  *  Also set the last sibling of parent.
2668  *  - argument new_sibling: must not be NULL.
2669  *  - returns the old sibling.
2670  *  The caller is responsible for releasing the old sibling.
2671  */
2672 static synctex_node_p _synctex_node_set_sibling(synctex_node_p node, synctex_node_p new_sibling)
2673 {
2674     if (node && new_sibling) {
2675         synctex_node_p old = _synctex_tree_set_sibling(node, new_sibling);
2676         if (_synctex_tree_has_parent(node)) {
2677             synctex_node_p parent = __synctex_tree_parent(node);
2678             if (parent) {
2679                 synctex_node_p N = new_sibling;
2680                 while (synctex_YES) {
2681                     if (_synctex_tree_has_parent(N)) {
2682                         __synctex_tree_set_parent(N, parent);
2683                         _synctex_tree_set_last(parent, N);
2684                         N = __synctex_tree_sibling(N);
2685                         continue;
2686                     } else if (N) {
2687                         _synctex_error(
2688                             "!  synctex_node_sibling. "
2689                             "Internal inconsistency. "
2690                             "Please report.");
2691                     }
2692                     break;
2693                 }
2694             }
2695         }
2696         return old;
2697     }
2698     return NULL;
2699 }
2700 /**
2701  *  The last sibling of the given node, or NULL with node.
2702  */
2703 synctex_node_p synctex_node_last_sibling(synctex_node_p node)
2704 {
2705     synctex_node_p sibling;
2706     do {
2707         sibling = node;
2708     } while ((node = synctex_node_sibling(node)));
2709     return sibling;
2710 }
2711 /**
2712  *  The next nodes corresponds to a deep first tree traversal.
2713  *  Does not create child proxies as side effect contrary to
2714  *  the synctex_node_next method above.
2715  *  May loop infinitely many times if the tree
2716  *  is not properly built (contains loops).
2717  */
2718 SYNCTEX_INLINE static synctex_node_p _synctex_node_sibling_or_parents(synctex_node_p node)
2719 {
2720     while (node) {
2721         synctex_node_p N;
2722         if ((N = __synctex_tree_sibling(node))) {
2723             return N;
2724         } else if ((node = _synctex_tree_parent(node))) {
2725             if (synctex_node_type(node) == synctex_node_type_sheet) { /*  EXC_BAD_ACCESS? */
2726                 return NULL;
2727             } else if (synctex_node_type(node) == synctex_node_type_form) {
2728                 return NULL;
2729             }
2730         } else {
2731             return NULL;
2732         }
2733     }
2734     return NULL;
2735 }
2736 /**
2737  *  The next nodes corresponds to a deep first tree traversal.
2738  *  Creates child proxies as side effect.
2739  *  May loop infinitely many times if the tree
2740  *  is not properly built (contains loops).
2741  */
2742 synctex_node_p synctex_node_next(synctex_node_p node)
2743 {
2744     synctex_node_p N = synctex_node_child(node);
2745     if (N) {
2746         return N;
2747     }
2748     return _synctex_node_sibling_or_parents(node);
2749 }
2750 /**
2751  *  The next nodes corresponds to a deep first tree traversal.
2752  *  Does not create child proxies as side effect contrary to
2753  *  the synctex_node_next method above.
2754  *  May loop infinitely many times if the tree
2755  *  is not properly built (contains loops).
2756  */
2757 synctex_node_p _synctex_node_next(synctex_node_p node)
2758 {
2759     synctex_node_p N = _synctex_tree_child(node);
2760     if (N) {
2761         return N;
2762     }
2763     return _synctex_node_sibling_or_parents(node);
2764 }
2765 /**
2766  *  The node which argument is the sibling.
2767  *  - return: NULL if the argument has no parent or
2768  *      is the first child of its parent.
2769  *  - Input nodes have no arg siblings
2770  */
2771 synctex_node_p synctex_node_arg_sibling(synctex_node_p node)
2772 {
2773 #if 1
2774     return _synctex_tree_arg_sibling(node);
2775 #else
2776     synctex_node_p N = _synctex_tree_parent(node);
2777     if ((N = _synctex_tree_child(N))) {
2778         do {
2779             synctex_node_p NN = __synctex_tree_sibling(N);
2780             if (NN == node) {
2781                 return N;
2782             }
2783             N = NN;
2784         } while (N);
2785     }
2786     return N;
2787 #endif
2788 }
2789 #ifdef SYNCTEX_NOTHING
2790 #pragma mark -
2791 #pragma mark CLASS
2792 #endif
2793 
2794 /*  Public node accessor: the type  */
2795 synctex_node_type_t synctex_node_type(synctex_node_p node)
2796 {
2797     return node ? node->class->type : synctex_node_type_none;
2798 }
2799 
2800 /*  Public node accessor: the type  */
2801 synctex_node_type_t synctex_node_target_type(synctex_node_p node)
2802 {
2803     synctex_node_p target = _synctex_tree_target(node);
2804     if (target) {
2805         return (((target)->class))->type;
2806     } else if (node) {
2807         return (((node)->class))->type;
2808     }
2809     return synctex_node_type_none;
2810 }
2811 
2812 /*  Public node accessor: the human readable type  */
2813 const char *synctex_node_isa(synctex_node_p node)
2814 {
2815     static const char *isa[synctex_node_number_of_types] = {"Not a node", "input", "sheet", "form",     "ref",      "vbox",  "void vbox",  "hbox",       "void hbox",  "kern",
2816                                                             "glue",       "rule",  "math",  "boundary", "box_bdry", "proxy", "last proxy", "vbox proxy", "hbox proxy", "handle"};
2817     return isa[synctex_node_type(node)];
2818 }
2819 
2820 #ifdef SYNCTEX_NOTHING
2821 #pragma mark -
2822 #pragma mark LOG
2823 #endif
2824 
2825 /*  Public node logger  */
2826 void synctex_node_log(synctex_node_p node)
2827 {
2828     SYNCTEX_MSG_SEND(node, log);
2829 }
2830 
2831 static void _synctex_log_input(synctex_node_p node)
2832 {
2833     if (node) {
2834         printf("%s:%i,%s(%i)\n", synctex_node_isa(node), _synctex_data_tag(node), _synctex_data_name(node), _synctex_data_line(node));
2835         printf("SELF:%p\n", (void *)node);
2836         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2837     }
2838 }
2839 
2840 static void _synctex_log_sheet(synctex_node_p node)
2841 {
2842     if (node) {
2843         printf("%s:%i", synctex_node_isa(node), _synctex_data_page(node));
2844         SYNCTEX_PRINT_CHARINDEX_NL;
2845         printf("SELF:%p\n", (void *)node);
2846         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2847         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2848         printf("    CHILD:%p\n", (void *)_synctex_tree_child(node));
2849         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2850         printf("    NEXT_hbox:%p\n", (void *)_synctex_tree_next_hbox(node));
2851     }
2852 }
2853 
2854 static void _synctex_log_form(synctex_node_p node)
2855 {
2856     if (node) {
2857         printf("%s:%i", synctex_node_isa(node), _synctex_data_tag(node));
2858         SYNCTEX_PRINT_CHARINDEX_NL;
2859         printf("SELF:%p\n", (void *)node);
2860         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2861         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2862         printf("    CHILD:%p\n", (void *)_synctex_tree_child(node));
2863         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2864     }
2865 }
2866 
2867 static void _synctex_log_ref(synctex_node_p node)
2868 {
2869     if (node) {
2870         printf("%s:%i:%i,%i", synctex_node_isa(node), _synctex_data_tag(node), _synctex_data_h(node), _synctex_data_v(node));
2871         SYNCTEX_PRINT_CHARINDEX_NL;
2872         printf("SELF:%p\n", (void *)node);
2873         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2874         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2875     }
2876 }
2877 
2878 static void _synctex_log_tlchv_node(synctex_node_p node)
2879 {
2880     if (node) {
2881         printf("%s:%i,%i:%i,%i", synctex_node_isa(node), _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node));
2882         SYNCTEX_PRINT_CHARINDEX_NL;
2883         printf("SELF:%p\n", (void *)node);
2884         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2885         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2886         printf("    CHILD:%p\n", (void *)_synctex_tree_child(node));
2887         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2888     }
2889 }
2890 
2891 static void _synctex_log_kern_node(synctex_node_p node)
2892 {
2893     if (node) {
2894         printf("%s:%i,%i:%i,%i:%i", synctex_node_isa(node), _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node), _synctex_data_width(node));
2895         SYNCTEX_PRINT_CHARINDEX_NL;
2896         printf("SELF:%p\n", (void *)node);
2897         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2898         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2899         printf("    CHILD:%p\n", (void *)_synctex_tree_child(node));
2900         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2901     }
2902 }
2903 
2904 static void _synctex_log_rule(synctex_node_p node)
2905 {
2906     if (node) {
2907         printf("%s:%i,%i:%i,%i", synctex_node_isa(node), _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node));
2908         printf(":%i", _synctex_data_width(node));
2909         printf(",%i", _synctex_data_height(node));
2910         printf(",%i", _synctex_data_depth(node));
2911         SYNCTEX_PRINT_CHARINDEX_NL;
2912         printf("SELF:%p\n", (void *)node);
2913         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2914         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2915         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2916     }
2917 }
2918 
2919 static void _synctex_log_void_box(synctex_node_p node)
2920 {
2921     if (node) {
2922         printf("%s", synctex_node_isa(node));
2923         printf(":%i", _synctex_data_tag(node));
2924         printf(",%i", _synctex_data_line(node));
2925         printf(",%i", 0);
2926         printf(":%i", _synctex_data_h(node));
2927         printf(",%i", _synctex_data_v(node));
2928         printf(":%i", _synctex_data_width(node));
2929         printf(",%i", _synctex_data_height(node));
2930         printf(",%i", _synctex_data_depth(node));
2931         SYNCTEX_PRINT_CHARINDEX_NL;
2932         printf("SELF:%p\n", (void *)node);
2933         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2934         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2935         printf("    CHILD:%p\n", (void *)_synctex_tree_child(node));
2936         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2937     }
2938 }
2939 
2940 static void _synctex_log_vbox(synctex_node_p node)
2941 {
2942     if (node) {
2943         printf("%s", synctex_node_isa(node));
2944         printf(":%i", _synctex_data_tag(node));
2945         printf(",%i", _synctex_data_line(node));
2946         printf(",%i", 0);
2947         printf(":%i", _synctex_data_h(node));
2948         printf(",%i", _synctex_data_v(node));
2949         printf(":%i", _synctex_data_width(node));
2950         printf(",%i", _synctex_data_height(node));
2951         printf(",%i", _synctex_data_depth(node));
2952         SYNCTEX_PRINT_CHARINDEX_NL;
2953         printf("SELF:%p\n", (void *)node);
2954         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2955         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2956         printf("    CHILD:%p\n", (void *)_synctex_tree_child(node));
2957         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2958         printf("    NEXT_hbox:%p\n", (void *)_synctex_tree_next_hbox(node));
2959     }
2960 }
2961 
2962 static void _synctex_log_hbox(synctex_node_p node)
2963 {
2964     if (node) {
2965         printf("%s", synctex_node_isa(node));
2966         printf(":%i", _synctex_data_tag(node));
2967         printf(",%i~%i*%i", _synctex_data_line(node), _synctex_data_mean_line(node), _synctex_data_weight(node));
2968         printf(",%i", 0);
2969         printf(":%i", _synctex_data_h(node));
2970         printf(",%i", _synctex_data_v(node));
2971         printf(":%i", _synctex_data_width(node));
2972         printf(",%i", _synctex_data_height(node));
2973         printf(",%i", _synctex_data_depth(node));
2974         printf("/%i", _synctex_data_h_V(node));
2975         printf(",%i", _synctex_data_v_V(node));
2976         printf(":%i", _synctex_data_width_V(node));
2977         printf(",%i", _synctex_data_height_V(node));
2978         printf(",%i", _synctex_data_depth_V(node));
2979         SYNCTEX_PRINT_CHARINDEX_NL;
2980         printf("SELF:%p\n", (void *)node);
2981         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2982         printf("    PARENT:%p\n", (void *)_synctex_tree_parent(node));
2983         printf("    CHILD:%p\n", (void *)_synctex_tree_child(node));
2984         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2985         printf("    NEXT_hbox:%p\n", (void *)_synctex_tree_next_hbox(node));
2986     }
2987 }
2988 static void _synctex_log_proxy(synctex_node_p node)
2989 {
2990     if (node) {
2991         synctex_node_p N = _synctex_tree_target(node);
2992         printf("%s", synctex_node_isa(node));
2993         printf(":%i", _synctex_data_h(node));
2994         printf(",%i", _synctex_data_v(node));
2995         SYNCTEX_PRINT_CHARINDEX_NL;
2996         printf("SELF:%p\n", (void *)node);
2997         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
2998         printf("    LEFT:%p\n", (void *)_synctex_tree_friend(node));
2999         printf("    ->%s\n", _synctex_node_abstract(N));
3000     }
3001 }
3002 static void _synctex_log_handle(synctex_node_p node)
3003 {
3004     if (node) {
3005         synctex_node_p N = _synctex_tree_target(node);
3006         printf("%s", synctex_node_isa(node));
3007         SYNCTEX_PRINT_CHARINDEX_NL;
3008         printf("SELF:%p\n", (void *)node);
3009         printf("    SIBLING:%p\n", (void *)__synctex_tree_sibling(node));
3010         printf("    ->%s\n", _synctex_node_abstract(N));
3011     }
3012 }
3013 
3014 #ifdef SYNCTEX_NOTHING
3015 #pragma mark -
3016 #pragma mark SYNCTEX_DISPLAY
3017 #endif
3018 
3019 int synctex_scanner_display_switcher(synctex_scanner_p scanR)
3020 {
3021     return scanR->display_switcher;
3022 }
3023 void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher)
3024 {
3025     scanR->display_switcher = switcher;
3026 }
3027 static const char *const _synctex_display_prompt = "................................";
3028 
3029 static char *_synctex_scanner_display_prompt_down(synctex_scanner_p scanR)
3030 {
3031     if (scanR->display_prompt > _synctex_display_prompt) {
3032         --scanR->display_prompt;
3033     }
3034     return scanR->display_prompt;
3035 }
3036 static char *_synctex_scanner_display_prompt_up(synctex_scanner_p scanR)
3037 {
3038     if (scanR->display_prompt + 1 < _synctex_display_prompt + strlen(_synctex_display_prompt)) {
3039         ++scanR->display_prompt;
3040     }
3041     return scanR->display_prompt;
3042 }
3043 
3044 void synctex_node_display(synctex_node_p node)
3045 {
3046     if (node) {
3047         synctex_scanner_p scanR = node->class->scanner;
3048         if (scanR) {
3049             if (scanR->display_switcher < 0) {
3050                 SYNCTEX_MSG_SEND(node, display);
3051             } else if (scanR->display_switcher > 0 && --scanR->display_switcher > 0) {
3052                 SYNCTEX_MSG_SEND(node, display);
3053             } else if (scanR->display_switcher-- >= 0) {
3054                 printf("%s Next display skipped. Reset display switcher.\n", node->class->scanner->display_prompt);
3055             }
3056         } else {
3057             SYNCTEX_MSG_SEND(node, display);
3058         }
3059     }
3060 }
3061 static const char *_synctex_node_abstract(synctex_node_p node)
3062 {
3063     SYNCTEX_PARAMETER_ASSERT(node || node->class);
3064     return (node && node->class->abstract) ? node->class->abstract(node) : "none";
3065 }
3066 
3067 SYNCTEX_INLINE static void _synctex_display_child(synctex_node_p node)
3068 {
3069     synctex_node_p N = _synctex_tree_child(node);
3070     if (N) {
3071         _synctex_scanner_display_prompt_down(N->class->scanner);
3072         synctex_node_display(N);
3073         _synctex_scanner_display_prompt_up(N->class->scanner);
3074     }
3075 }
3076 
3077 SYNCTEX_INLINE static void _synctex_display_sibling(synctex_node_p node)
3078 {
3079     synctex_node_display(__synctex_tree_sibling(node));
3080 }
3081 #define SYNCTEX_ABSTRACT_MAX 128
3082 static char *_synctex_abstract_input(synctex_node_p node)
3083 {
3084     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3085     if (node) {
3086         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "Input:%i:%s(%i)" SYNCTEX_PRINT_CHARINDEX_FMT, _synctex_data_tag(node), _synctex_data_name(node), _synctex_data_line(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3087     }
3088     return abstract;
3089 }
3090 
3091 static void _synctex_display_input(synctex_node_p node)
3092 {
3093     if (node) {
3094         printf("Input:%i:%s(%i)" SYNCTEX_PRINT_CHARINDEX_FMT "\n", _synctex_data_tag(node), _synctex_data_name(node), _synctex_data_line(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3095         synctex_node_display(__synctex_tree_sibling(node));
3096     }
3097 }
3098 
3099 static char *_synctex_abstract_sheet(synctex_node_p node)
3100 {
3101     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3102     if (node) {
3103         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "{%i...}" SYNCTEX_PRINT_CHARINDEX_FMT, _synctex_data_page(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3104     }
3105     return abstract;
3106 }
3107 
3108 static void _synctex_display_sheet(synctex_node_p node)
3109 {
3110     if (node) {
3111         printf("%s{%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n", node->class->scanner->display_prompt, _synctex_data_page(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3112         _synctex_display_child(node);
3113         printf("%s}\n", node->class->scanner->display_prompt);
3114         _synctex_display_sibling(node);
3115     }
3116 }
3117 
3118 static char *_synctex_abstract_form(synctex_node_p node)
3119 {
3120     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3121     if (node) {
3122         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "<%i...>" SYNCTEX_PRINT_CHARINDEX_FMT, _synctex_data_tag(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3123         SYNCTEX_PRINT_CHARINDEX;
3124     }
3125     return abstract;
3126 }
3127 
3128 static void _synctex_display_form(synctex_node_p node)
3129 {
3130     if (node) {
3131         printf("%s<%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n", node->class->scanner->display_prompt, _synctex_data_tag(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3132         _synctex_display_child(node);
3133         printf("%s>\n", node->class->scanner->display_prompt);
3134         _synctex_display_sibling(node);
3135     }
3136 }
3137 
3138 static char *_synctex_abstract_vbox(synctex_node_p node)
3139 {
3140     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3141     if (node) {
3142         snprintf(abstract,
3143                  SYNCTEX_ABSTRACT_MAX,
3144                  "[%i,%i:%i,%i:%i,%i,%i...]" SYNCTEX_PRINT_CHARINDEX_FMT,
3145                  _synctex_data_tag(node),
3146                  _synctex_data_line(node),
3147                  _synctex_data_h(node),
3148                  _synctex_data_v(node),
3149                  _synctex_data_width(node),
3150                  _synctex_data_height(node),
3151                  _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3152     }
3153     return abstract;
3154 }
3155 
3156 static void _synctex_display_vbox(synctex_node_p node)
3157 {
3158     if (node) {
3159         printf("%s[%i,%i:%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3160                node->class->scanner->display_prompt,
3161                _synctex_data_tag(node),
3162                _synctex_data_line(node),
3163                _synctex_data_h(node),
3164                _synctex_data_v(node),
3165                _synctex_data_width(node),
3166                _synctex_data_height(node),
3167                _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3168         _synctex_display_child(node);
3169         printf("%s]\n%slast:%s\n", node->class->scanner->display_prompt, node->class->scanner->display_prompt, _synctex_node_abstract(_synctex_tree_last(node)));
3170         _synctex_display_sibling(node);
3171     }
3172 }
3173 
3174 static char *_synctex_abstract_hbox(synctex_node_p node)
3175 {
3176     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3177     if (node) {
3178         snprintf(abstract,
3179                  SYNCTEX_ABSTRACT_MAX,
3180                  "(%i,%i~%i*%i:%i,%i:%i,%i,%i...)" SYNCTEX_PRINT_CHARINDEX_FMT,
3181                  _synctex_data_tag(node),
3182                  _synctex_data_line(node),
3183                  _synctex_data_mean_line(node),
3184                  _synctex_data_weight(node),
3185                  _synctex_data_h(node),
3186                  _synctex_data_v(node),
3187                  _synctex_data_width(node),
3188                  _synctex_data_height(node),
3189                  _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3190     }
3191     return abstract;
3192 }
3193 
3194 static void _synctex_display_hbox(synctex_node_p node)
3195 {
3196     if (node) {
3197         printf("%s(%i,%i~%i*%i:%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3198                node->class->scanner->display_prompt,
3199                _synctex_data_tag(node),
3200                _synctex_data_line(node),
3201                _synctex_data_mean_line(node),
3202                _synctex_data_weight(node),
3203                _synctex_data_h(node),
3204                _synctex_data_v(node),
3205                _synctex_data_width(node),
3206                _synctex_data_height(node),
3207                _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3208         _synctex_display_child(node);
3209         printf("%s)\n%slast:%s\n", node->class->scanner->display_prompt, node->class->scanner->display_prompt, _synctex_node_abstract(_synctex_tree_last(node)));
3210         _synctex_display_sibling(node);
3211     }
3212 }
3213 
3214 static char *_synctex_abstract_void_vbox(synctex_node_p node)
3215 {
3216     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3217     if (node) {
3218         snprintf(abstract,
3219                  SYNCTEX_ABSTRACT_MAX,
3220                  "v%i,%i;%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3221                  _synctex_data_tag(node),
3222                  _synctex_data_line(node),
3223                  _synctex_data_h(node),
3224                  _synctex_data_v(node),
3225                  _synctex_data_width(node),
3226                  _synctex_data_height(node),
3227                  _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3228     }
3229     return abstract;
3230 }
3231 
3232 static void _synctex_display_void_vbox(synctex_node_p node)
3233 {
3234     if (node) {
3235         printf("%sv%i,%i;%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3236                node->class->scanner->display_prompt,
3237                _synctex_data_tag(node),
3238                _synctex_data_line(node),
3239                _synctex_data_h(node),
3240                _synctex_data_v(node),
3241                _synctex_data_width(node),
3242                _synctex_data_height(node),
3243                _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3244         _synctex_display_sibling(node);
3245     }
3246 }
3247 
3248 static char *_synctex_abstract_void_hbox(synctex_node_p node)
3249 {
3250     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3251     if (node) {
3252         snprintf(abstract,
3253                  SYNCTEX_ABSTRACT_MAX,
3254                  "h%i,%i:%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT,
3255                  _synctex_data_tag(node),
3256                  _synctex_data_line(node),
3257                  _synctex_data_h(node),
3258                  _synctex_data_v(node),
3259                  _synctex_data_width(node),
3260                  _synctex_data_height(node),
3261                  _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3262     }
3263     return abstract;
3264 }
3265 
3266 static void _synctex_display_void_hbox(synctex_node_p node)
3267 {
3268     if (node) {
3269         printf("%sh%i,%i:%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3270                node->class->scanner->display_prompt,
3271                _synctex_data_tag(node),
3272                _synctex_data_line(node),
3273                _synctex_data_h(node),
3274                _synctex_data_v(node),
3275                _synctex_data_width(node),
3276                _synctex_data_height(node),
3277                _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3278         _synctex_display_sibling(node);
3279     }
3280 }
3281 
3282 static char *_synctex_abstract_glue(synctex_node_p node)
3283 {
3284     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3285     if (node) {
3286         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "glue:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3287     }
3288     return abstract;
3289 }
3290 
3291 static void _synctex_display_glue(synctex_node_p node)
3292 {
3293     if (node) {
3294         printf("%sglue:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n", node->class->scanner->display_prompt, _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3295         _synctex_display_sibling(node);
3296     }
3297 }
3298 
3299 static char *_synctex_abstract_rule(synctex_node_p node)
3300 {
3301     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3302     if (node) {
3303         snprintf(abstract,
3304                  SYNCTEX_ABSTRACT_MAX,
3305                  "rule:%i,%i:%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT,
3306                  _synctex_data_tag(node),
3307                  _synctex_data_line(node),
3308                  _synctex_data_h(node),
3309                  _synctex_data_v(node),
3310                  _synctex_data_width(node),
3311                  _synctex_data_height(node),
3312                  _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3313     }
3314     return abstract;
3315 }
3316 
3317 static void _synctex_display_rule(synctex_node_p node)
3318 {
3319     if (node) {
3320         printf("%srule:%i,%i:%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3321                node->class->scanner->display_prompt,
3322                _synctex_data_tag(node),
3323                _synctex_data_line(node),
3324                _synctex_data_h(node),
3325                _synctex_data_v(node),
3326                _synctex_data_width(node),
3327                _synctex_data_height(node),
3328                _synctex_data_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3329         _synctex_display_sibling(node);
3330     }
3331 }
3332 
3333 static char *_synctex_abstract_math(synctex_node_p node)
3334 {
3335     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3336     if (node) {
3337         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "math:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3338     }
3339     return abstract;
3340 }
3341 
3342 static void _synctex_display_math(synctex_node_p node)
3343 {
3344     if (node) {
3345         printf("%smath:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n", node->class->scanner->display_prompt, _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3346         _synctex_display_sibling(node);
3347     }
3348 }
3349 
3350 static char *_synctex_abstract_kern(synctex_node_p node)
3351 {
3352     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3353     if (node) {
3354         snprintf(abstract,
3355                  SYNCTEX_ABSTRACT_MAX,
3356                  "kern:%i,%i:%i,%i:%i" SYNCTEX_PRINT_CHARINDEX_FMT,
3357                  _synctex_data_tag(node),
3358                  _synctex_data_line(node),
3359                  _synctex_data_h(node),
3360                  _synctex_data_v(node),
3361                  _synctex_data_width(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3362     }
3363     return abstract;
3364 }
3365 
3366 static void _synctex_display_kern(synctex_node_p node)
3367 {
3368     if (node) {
3369         printf("%skern:%i,%i:%i,%i:%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3370                node->class->scanner->display_prompt,
3371                _synctex_data_tag(node),
3372                _synctex_data_line(node),
3373                _synctex_data_h(node),
3374                _synctex_data_v(node),
3375                _synctex_data_width(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3376         _synctex_display_sibling(node);
3377     }
3378 }
3379 
3380 static char *_synctex_abstract_boundary(synctex_node_p node)
3381 {
3382     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3383     if (node) {
3384         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "boundary:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3385     }
3386     return abstract;
3387 }
3388 
3389 static void _synctex_display_boundary(synctex_node_p node)
3390 {
3391     if (node) {
3392         printf("%sboundary:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n", node->class->scanner->display_prompt, _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3393         _synctex_display_sibling(node);
3394     }
3395 }
3396 
3397 static char *_synctex_abstract_box_bdry(synctex_node_p node)
3398 {
3399     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3400     if (node) {
3401         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "box bdry:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3402     }
3403     return abstract;
3404 }
3405 
3406 static void _synctex_display_box_bdry(synctex_node_p node)
3407 {
3408     if (node) {
3409         printf("%sbox bdry:%i,%i:%i,%i", node->class->scanner->display_prompt, _synctex_data_tag(node), _synctex_data_line(node), _synctex_data_h(node), _synctex_data_v(node));
3410         SYNCTEX_PRINT_CHARINDEX_NL;
3411         _synctex_display_sibling(node);
3412     }
3413 }
3414 
3415 static char *_synctex_abstract_ref(synctex_node_p node)
3416 {
3417     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3418     if (node) {
3419         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "form ref:%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, _synctex_data_tag(node), _synctex_data_h(node), _synctex_data_v(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3420     }
3421     return abstract;
3422 }
3423 
3424 static void _synctex_display_ref(synctex_node_p node)
3425 {
3426     if (node) {
3427         printf("%sform ref:%i:%i,%i", node->class->scanner->display_prompt, _synctex_data_tag(node), _synctex_data_h(node), _synctex_data_v(node));
3428         SYNCTEX_PRINT_CHARINDEX_NL;
3429         _synctex_display_sibling(node);
3430     }
3431 }
3432 static char *_synctex_abstract_proxy(synctex_node_p node)
3433 {
3434     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3435     if (node) {
3436         synctex_node_p N = _synctex_tree_target(node);
3437         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "%s:%i,%i:%i,%i/%p%s", synctex_node_isa(node), synctex_node_tag(node), synctex_node_line(node), _synctex_data_h(node), _synctex_data_v(node), node, _synctex_node_abstract(N));
3438     }
3439     return abstract;
3440 }
3441 static void _synctex_display_proxy(synctex_node_p node)
3442 {
3443     if (node) {
3444         synctex_node_p N = _synctex_tree_target(node);
3445         printf("%s%s:%i,%i:%i,%i", node->class->scanner->display_prompt, synctex_node_isa(node), synctex_node_tag(node), synctex_node_line(node), _synctex_data_h(node), _synctex_data_v(node));
3446         if (N) {
3447             printf("=%i,%i:%i,%i,%i->%s", synctex_node_h(node), synctex_node_v(node), synctex_node_width(node), synctex_node_height(node), synctex_node_depth(node), _synctex_node_abstract(N));
3448         }
3449         printf("\n");
3450         _synctex_display_child(node);
3451         _synctex_display_sibling(node);
3452     }
3453 }
3454 static char *_synctex_abstract_proxy_vbox(synctex_node_p node)
3455 {
3456     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3457     if (node) {
3458         snprintf(abstract,
3459                  SYNCTEX_ABSTRACT_MAX,
3460                  "[*%i,%i:%i,%i:%i,%i,%i...*]" SYNCTEX_PRINT_CHARINDEX_FMT,
3461                  synctex_node_tag(node),
3462                  synctex_node_line(node),
3463                  synctex_node_h(node),
3464                  synctex_node_v(node),
3465                  synctex_node_width(node),
3466                  synctex_node_height(node),
3467                  synctex_node_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3468     }
3469     return abstract;
3470 }
3471 
3472 static void _synctex_display_proxy_vbox(synctex_node_p node)
3473 {
3474     if (node) {
3475         printf("%s[*%i,%i:%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3476                node->class->scanner->display_prompt,
3477                synctex_node_tag(node),
3478                synctex_node_line(node),
3479                synctex_node_h(node),
3480                synctex_node_v(node),
3481                synctex_node_width(node),
3482                synctex_node_height(node),
3483                synctex_node_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3484         _synctex_display_child(node);
3485         printf("%s*]\n%slast:%s\n", node->class->scanner->display_prompt, node->class->scanner->display_prompt, _synctex_node_abstract(_synctex_tree_last(node)));
3486         _synctex_display_sibling(node);
3487     }
3488 }
3489 
3490 static char *_synctex_abstract_proxy_hbox(synctex_node_p node)
3491 {
3492     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3493     if (node) {
3494         snprintf(abstract,
3495                  SYNCTEX_ABSTRACT_MAX,
3496                  "(*%i,%i~%i*%i:%i,%i:%i,%i,%i...*)/%p" SYNCTEX_PRINT_CHARINDEX_FMT,
3497                  synctex_node_tag(node),
3498                  synctex_node_line(node),
3499                  synctex_node_mean_line(node),
3500                  synctex_node_weight(node),
3501                  synctex_node_h(node),
3502                  synctex_node_v(node),
3503                  synctex_node_width(node),
3504                  synctex_node_height(node),
3505                  synctex_node_depth(node),
3506                  node SYNCTEX_PRINT_CHARINDEX_WHAT);
3507     }
3508     return abstract;
3509 }
3510 
3511 static void _synctex_display_proxy_hbox(synctex_node_p node)
3512 {
3513     if (node) {
3514         printf("%s(*%i,%i~%i*%i:%i,%i:%i,%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT "\n",
3515                node->class->scanner->display_prompt,
3516                synctex_node_tag(node),
3517                synctex_node_line(node),
3518                synctex_node_mean_line(node),
3519                synctex_node_weight(node),
3520                synctex_node_h(node),
3521                synctex_node_v(node),
3522                synctex_node_width(node),
3523                synctex_node_height(node),
3524                synctex_node_depth(node) SYNCTEX_PRINT_CHARINDEX_WHAT);
3525         _synctex_display_child(node);
3526         printf("%s*)\n%slast:%s\n", node->class->scanner->display_prompt, node->class->scanner->display_prompt, _synctex_node_abstract(_synctex_tree_last(node)));
3527         _synctex_display_sibling(node);
3528     }
3529 }
3530 
3531 static char *_synctex_abstract_handle(synctex_node_p node)
3532 {
3533     static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3534     if (node) {
3535         synctex_node_p N = _synctex_tree_target(node);
3536         if (N && !N->class) {
3537             exit(1);
3538         }
3539         snprintf(abstract, SYNCTEX_ABSTRACT_MAX, "%s:%s", synctex_node_isa(node), (N ? _synctex_node_abstract(N) : ""));
3540     }
3541     return abstract;
3542 }
3543 static void _synctex_display_handle(synctex_node_p node)
3544 {
3545     if (node) {
3546         synctex_node_p N = _synctex_tree_target(node);
3547         printf("%s%s:->%s\n", node->class->scanner->display_prompt, synctex_node_isa(node), _synctex_node_abstract(N));
3548         _synctex_display_child(node);
3549         _synctex_display_sibling(node);
3550     }
3551 }
3552 #ifdef SYNCTEX_NOTHING
3553 #pragma mark -
3554 #pragma mark STATUS
3555 #endif
3556 
3557 #ifdef SYNCTEX_NOTHING
3558 #pragma mark -
3559 #pragma mark Prototypes
3560 #endif
3561 typedef struct {
3562     size_t size;
3563     synctex_status_t status;
3564 } synctex_zs_s;
3565 static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t size);
3566 static synctex_status_t _synctex_next_line(synctex_scanner_p scanner);
3567 static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char *the_string);
3568 
3569 typedef struct synctex_ns_t {
3570     synctex_node_p node;
3571     synctex_status_t status;
3572 } synctex_ns_s;
3573 static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner);
3574 static synctex_status_t _synctex_scan_preamble(synctex_scanner_p scanner);
3575 typedef struct {
3576     float value;
3577     synctex_status_t status;
3578 } synctex_fs_s;
3579 static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner);
3580 static synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_p scanner);
3581 static synctex_status_t _synctex_scan_postamble(synctex_scanner_p scanner);
3582 static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box);
3583 static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner);
3584 int synctex_scanner_pre_x_offset(synctex_scanner_p scanner);
3585 int synctex_scanner_pre_y_offset(synctex_scanner_p scanner);
3586 const char *synctex_scanner_get_output_fmt(synctex_scanner_p scanner);
3587 
3588 #ifdef SYNCTEX_NOTHING
3589 #pragma mark -
3590 #pragma mark SCANNER UTILITIES
3591 #endif
3592 
3593 #define SYNCTEX_FILE (scanner->reader->file)
3594 
3595 /**
3596  *  Try to ensure that the buffer contains at least size bytes.
3597  *  Passing a huge size argument means the whole buffer length.
3598  *  Passing a 0 size argument means return the available buffer length, without reading the file.
3599  *  In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL.
3600  *  The size_t value returned is the number of bytes now available in the buffer. This is a nonnegative integer, it may take the value 0.
3601  *  It is the responsibility of the caller to test whether this size is conforming to its needs.
3602  *  Negative values may return in case of error, actually
3603  *  when there was an error reading the synctex file.
3604  *  - parameter scanner: The owning scanner. When NULL, returns SYNCTEX_STATUS_BAD_ARGUMENT.
3605  *  - parameter expected: expected number of bytes.
3606  *  - returns: a size and a status.
3607  */
3608 static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t expected)
3609 {
3610     size_t size = 0;
3611     if (NULL == scanner) {
3612         return (synctex_zs_s) {0, SYNCTEX_STATUS_BAD_ARGUMENT};
3613     }
3614     if (expected > scanner->reader->size) {
3615         expected = scanner->reader->size;
3616     }
3617     size = SYNCTEX_END - SYNCTEX_CUR; /*  available is the number of unparsed chars in the buffer */
3618     if (expected <= size) {
3619         /*  There are already sufficiently many characters in the buffer */
3620         return (synctex_zs_s) {size, SYNCTEX_STATUS_OK};
3621     }
3622     if (SYNCTEX_FILE) {
3623         /*  Copy the remaining part of the buffer to the beginning,
3624          *  then read the next part of the file */
3625         int already_read = 0;
3626 #if defined(SYNCTEX_USE_CHARINDEX)
3627         scanner->reader->charindex_offset += SYNCTEX_CUR - SYNCTEX_START;
3628 #endif
3629         if (size) {
3630             memmove(SYNCTEX_START, SYNCTEX_CUR, size);
3631         }
3632         SYNCTEX_CUR = SYNCTEX_START + size; /*  the next character after the move, will change. */
3633         /*  Fill the buffer up to its end */
3634         already_read = gzread(SYNCTEX_FILE, (void *)SYNCTEX_CUR, (int)(SYNCTEX_BUFFER_SIZE - size));
3635         if (already_read > 0) {
3636             /*  We assume that 0<already_read<=SYNCTEX_BUFFER_SIZE - size, such that
3637              *  SYNCTEX_CUR + already_read = SYNCTEX_START + size  + already_read <= SYNCTEX_START + SYNCTEX_BUFFER_SIZE */
3638             SYNCTEX_END = SYNCTEX_CUR + already_read;
3639             /*  If the end of the file was reached, all the required SYNCTEX_BUFFER_SIZE - available
3640              *  may not be filled with values from the file.
3641              *  In that case, the buffer should stop properly after already_read characters. */
3642             *SYNCTEX_END = '\0'; /* there is enough room */
3643             SYNCTEX_CUR = SYNCTEX_START;
3644             /*  May be available is less than size, the caller will have to test. */
3645             return (synctex_zs_s) {SYNCTEX_END - SYNCTEX_CUR, SYNCTEX_STATUS_OK};
3646         } else if (0 > already_read) {
3647             /*  There is a possible error in reading the file */
3648             int errnum = 0;
3649             const char *error_string = gzerror(SYNCTEX_FILE, &errnum);
3650             if (Z_ERRNO == errnum) {
3651                 /*  There is an error in zlib caused by the file system */
3652                 _synctex_error("gzread error from the file system (%i)", errno);
3653                 return (synctex_zs_s) {0, SYNCTEX_STATUS_ERROR};
3654             } else if (errnum) {
3655                 _synctex_error("gzread error (%i:%i,%s)", already_read, errnum, error_string);
3656                 return (synctex_zs_s) {0, SYNCTEX_STATUS_ERROR};
3657             }
3658         }
3659         /*  Nothing was read, we are at the end of the file. */
3660         gzclose(SYNCTEX_FILE);
3661         SYNCTEX_FILE = NULL;
3662         SYNCTEX_END = SYNCTEX_CUR;
3663         SYNCTEX_CUR = SYNCTEX_START;
3664         *SYNCTEX_END = '\0'; /*  Terminate the string properly.*/
3665         /*  there might be a bit of text left */
3666         return (synctex_zs_s) {SYNCTEX_END - SYNCTEX_CUR, SYNCTEX_STATUS_EOF};
3667     }
3668     /*  We cannot enlarge the buffer because the end of the file was reached. */
3669     return (synctex_zs_s) {size, SYNCTEX_STATUS_EOF};
3670 }
3671 
3672 /*  Used when parsing the synctex file.
3673  *  Advance to the next character starting a line.
3674  *  Actually, only '\n' is recognized as end of line marker.
3675  *  On normal completion, the returned value is the number of unparsed characters available in the buffer.
3676  *  In general, it is a positive value, 0 meaning that the end of file was reached.
3677  *  -1 is returned in case of error, actually because there was an error while feeding the buffer.
3678  *  When the function returns with no error, SYNCTEX_CUR points to the first character of the next line, if any.
3679  *  J. Laurens: Sat May 10 07:52:31 UTC 2008
3680  */
3681 static synctex_status_t _synctex_next_line(synctex_scanner_p scanner)
3682 {
3683     synctex_status_t status = SYNCTEX_STATUS_OK;
3684     if (NULL == scanner) {
3685         return SYNCTEX_STATUS_BAD_ARGUMENT;
3686     }
3687 infinite_loop:
3688     while (SYNCTEX_CUR < SYNCTEX_END) {
3689         if (*SYNCTEX_CUR == '\n') {
3690             ++SYNCTEX_CUR;
3691             ++scanner->reader->line_number;
3692             return _synctex_buffer_get_available_size(scanner, 1).status;
3693         }
3694         ++SYNCTEX_CUR;
3695     }
3696     /*  Here, we have SYNCTEX_CUR == SYNCTEX_END, such that the next call to _synctex_buffer_get_available_size
3697      *  will read another bunch of synctex file. Little by little, we advance to the end of the file. */
3698     status = _synctex_buffer_get_available_size(scanner, 1).status;
3699     if (status <= SYNCTEX_STATUS_EOF) {
3700         return status;
3701     }
3702     goto infinite_loop;
3703 }
3704 
3705 /*  Scan the given string.
3706  *  Both scanner and the_string must not be NULL, and the_string must not be 0 length.
3707  *  SYNCTEX_STATUS_OK is returned if the string is found,
3708  *  SYNCTEX_STATUS_EOF is returned when the EOF is reached,
3709  *  SYNCTEX_STATUS_NOT_OK is returned is the string is not found,
3710  *  an error status is returned otherwise.
3711  *  This is a critical method because buffering renders things more difficult.
3712  *  The given string might be as long as the maximum size_t value.
3713  *  As side effect, the buffer state may have changed if the given argument string can't fit into the buffer.
3714  */
3715 static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char *the_string)
3716 {
3717     size_t tested_len = 0;    /*  the number of characters at the beginning of the_string that match */
3718     size_t remaining_len = 0; /*  the number of remaining characters of the_string that should match */
3719     size_t available = 0;
3720     synctex_zs_s zs = {0, 0};
3721     if (NULL == scanner || NULL == the_string) {
3722         return SYNCTEX_STATUS_BAD_ARGUMENT;
3723     }
3724     remaining_len = strlen(the_string); /*  All the_string should match */
3725     if (0 == remaining_len) {
3726         return SYNCTEX_STATUS_BAD_ARGUMENT;
3727     }
3728     /*  How many characters available in the buffer? */
3729     zs = _synctex_buffer_get_available_size(scanner, remaining_len);
3730     if (zs.status < SYNCTEX_STATUS_EOF) {
3731         return zs.status;
3732     }
3733     /*  Maybe we have less characters than expected because the buffer is too small. */
3734     if (zs.size >= remaining_len) {
3735         /*  The buffer is sufficiently big to hold the expected number of characters. */
3736         if (strncmp((char *)SYNCTEX_CUR, the_string, remaining_len)) {
3737             return SYNCTEX_STATUS_NOT_OK;
3738         }
3739     return_OK:
3740         /*  Advance SYNCTEX_CUR to the next character after the_string. */
3741         SYNCTEX_CUR += remaining_len;
3742         return SYNCTEX_STATUS_OK;
3743     } else if (strncmp((char *)SYNCTEX_CUR, the_string, zs.size)) {
3744         /*  No need to go further, this is not the expected string in the buffer. */
3745         return SYNCTEX_STATUS_NOT_OK;
3746     } else if (SYNCTEX_FILE) {
3747         /*  The buffer was too small to contain remaining_len characters.
3748          *  We have to cut the string into pieces. */
3749         z_off_t offset = 0L;
3750         /*  the first part of the string is found, advance the_string to the next untested character. */
3751         the_string += zs.size;
3752         /*  update the remaining length and the parsed length. */
3753         remaining_len -= zs.size;
3754         tested_len += zs.size;
3755         SYNCTEX_CUR += zs.size; /*  We validate the tested characters. */
3756         if (0 == remaining_len) {
3757             /*  Nothing left to test, we have found the given string. */
3758             return SYNCTEX_STATUS_OK;
3759         }
3760         /*  We also have to record the current state of the file cursor because
3761          *  if the_string does not match, all this should be a totally blank operation,
3762          *  for which the file and buffer states should not be modified at all.
3763          *  In fact, the states of the buffer before and after this function are in general different
3764          *  but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR
3765          *  can be safely discarded.  */
3766         offset = gztell(SYNCTEX_FILE);
3767         /*  offset now corresponds to the first character of the file that was not buffered. */
3768         /*  SYNCTEX_CUR - SYNCTEX_START is the number of chars that where already buffered and
3769          *  that match the head of the_string. If in fine the_string does not match, all these chars must be recovered
3770          *  because the whole buffer contents is replaced in _synctex_buffer_get_available_size.
3771          *  They were buffered from offset-len location in the file. */
3772         offset -= SYNCTEX_CUR - SYNCTEX_START;
3773     more_characters:
3774         /*  There is still some work to be done, so read another bunch of file.
3775          *  This is the second call to _synctex_buffer_get_available_size,
3776          *  which means that the actual contents of the buffer will be discarded.
3777          *  We will definitely have to recover the previous state in case we do not find the expected string. */
3778         zs = _synctex_buffer_get_available_size(scanner, remaining_len);
3779         if (zs.status < SYNCTEX_STATUS_EOF) {
3780             return zs.status; /*  This is an error, no need to go further. */
3781         }
3782         if (zs.size == 0) {
3783             /*  Missing characters: recover the initial state of the file and return. */
3784         return_NOT_OK:
3785             if (offset != gzseek(SYNCTEX_FILE, offset, SEEK_SET)) {
3786                 /*  This is a critical error, we could not recover the previous state. */
3787                 _synctex_error("Can't seek file");
3788                 return SYNCTEX_STATUS_ERROR;
3789             }
3790             /*  Next time we are asked to fill the buffer,
3791              *  we will read a complete bunch of text from the file. */
3792             SYNCTEX_CUR = SYNCTEX_END;
3793             return SYNCTEX_STATUS_NOT_OK;
3794         }
3795         if (zs.size < remaining_len) {
3796             /*  We'll have to loop one more time. */
3797             if (strncmp((char *)SYNCTEX_CUR, the_string, zs.size)) {
3798                 /*  This is not the expected string, recover the previous state and return. */
3799                 goto return_NOT_OK;
3800             }
3801             /*  Advance the_string to the first untested character. */
3802             the_string += available;
3803             /*  update the remaining length and the parsed length. */
3804             remaining_len -= zs.size;
3805             tested_len += zs.size;
3806             SYNCTEX_CUR += zs.size; /*  We validate the tested characters. */
3807             goto more_characters;
3808         }
3809         /*  This is the last step. */
3810         if (strncmp((char *)SYNCTEX_CUR, the_string, remaining_len)) {
3811             /*  This is not the expected string, recover the previous state and return. */
3812             goto return_NOT_OK;
3813         }
3814         goto return_OK;
3815     } else {
3816         /*  The buffer can't contain the given string argument, and the EOF was reached */
3817         return SYNCTEX_STATUS_EOF;
3818     }
3819 }
3820 
3821 /*  Used when parsing the synctex file.
3822  *  Decode an integer.
3823  *  First, field separators, namely ':' and ',' characters are skipped
3824  *  The returned value is negative if there is an unrecoverable error.
3825  *  It is SYNCTEX_STATUS_NOT_OK if an integer could not be parsed, for example
3826  *  if the characters at the current cursor position are not digits or
3827  *  if the end of the file has been reached.
3828  *  It is SYNCTEX_STATUS_OK if an int has been successfully parsed.
3829  *  The given scanner argument must not be NULL, on the contrary, value_ref may be NULL.
3830  */
3831 static synctex_is_s _synctex_decode_int(synctex_scanner_p scanner)
3832 {
3833     char *ptr = NULL;
3834     char *end = NULL;
3835     synctex_zs_s zs = {0, 0};
3836     int result;
3837     if (NULL == scanner) {
3838         return (synctex_is_s) {0, SYNCTEX_STATUS_BAD_ARGUMENT};
3839     }
3840     zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE);
3841     if (zs.status < SYNCTEX_STATUS_EOF) {
3842         return (synctex_is_s) {0, zs.status};
3843     }
3844     if (zs.size == 0) {
3845         return (synctex_is_s) {0, SYNCTEX_STATUS_NOT_OK};
3846     }
3847     ptr = SYNCTEX_CUR;
3848     /*  Optionally parse the separator */
3849     if (*ptr == ':' || *ptr == ',') {
3850         ++ptr;
3851         --zs.size;
3852         if (zs.size == 0) {
3853             return (synctex_is_s) {0, SYNCTEX_STATUS_NOT_OK};
3854         }
3855     }
3856     result = (int)strtol(ptr, &end, 10);
3857     if (end > ptr) {
3858         SYNCTEX_CUR = end;
3859         return (synctex_is_s) {result, SYNCTEX_STATUS_OK};
3860     }
3861     return (synctex_is_s) {result, SYNCTEX_STATUS_NOT_OK};
3862 }
3863 static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value)
3864 {
3865     char *ptr = NULL;
3866     char *end = NULL;
3867     synctex_zs_s zs = {0, 0};
3868     if (NULL == scanner) {
3869         return (synctex_is_s) {default_value, SYNCTEX_STATUS_BAD_ARGUMENT};
3870     }
3871     zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE);
3872     if (zs.status < SYNCTEX_STATUS_EOF) {
3873         return (synctex_is_s) {default_value, zs.status};
3874     }
3875     if (zs.size == 0) {
3876         return (synctex_is_s) {default_value, SYNCTEX_STATUS_OK};
3877     }
3878     ptr = SYNCTEX_CUR;
3879     /*  Comma separator required */
3880     if (*ptr == ',') {
3881         int result;
3882         ++ptr;
3883         --zs.size;
3884         if (zs.size == 0) {
3885             return (synctex_is_s) {default_value, SYNCTEX_STATUS_NOT_OK};
3886         }
3887         result = (int)strtol(ptr, &end, 10);
3888         if (end > ptr) {
3889             SYNCTEX_CUR = end;
3890             return (synctex_is_s) {result, SYNCTEX_STATUS_OK};
3891         }
3892         return (synctex_is_s) {default_value, SYNCTEX_STATUS_NOT_OK};
3893     }
3894     return (synctex_is_s) {default_value, SYNCTEX_STATUS_OK};
3895 }
3896 /*  Used when parsing the synctex file.
3897  *  Decode an integer for a v field.
3898  *  Try the _synctex_decode_int version and set the last v field scanned.
3899  *  If it does not succeed, tries to match an '=' sign,
3900  *  which is a shortcut for the last v field scanned.
3901  */
3902 #define SYNCTEX_INPUT_COMEQUALS ",="
3903 static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner)
3904 {
3905     synctex_is_s is = _synctex_decode_int(scanner);
3906     if (SYNCTEX_STATUS_OK == is.status) {
3907         scanner->reader->lastv = is.integer;
3908         return is;
3909     }
3910     is.status = _synctex_match_string(scanner, SYNCTEX_INPUT_COMEQUALS);
3911     if (is.status < SYNCTEX_STATUS_OK) {
3912         return is;
3913     }
3914     is.integer = scanner->reader->lastv;
3915     return is;
3916 }
3917 
3918 /*  The purpose of this function is to read a string.
3919  *  A string is an array of characters from the current parser location
3920  *  and before the next '\n' character.
3921  *  If a string was properly decoded, it is returned in value_ref and
3922  *  the cursor points to the new line marker.
3923  *  The returned string was alloced on the heap, the caller is the owner and
3924  *  is responsible to free it in due time,
3925  *  unless it transfers the ownership to another object.
3926  *  If no string is parsed, * value_ref is undefined.
3927  *  The maximum length of a string that a scanner can decode is platform dependent, namely UINT_MAX.
3928  *  If you just want to blindly parse the file up to the end of the current line,
3929  *  use _synctex_next_line instead.
3930  *  On return, the scanner cursor is unchanged if a string could not be scanned or
3931  *  points to the terminating '\n' character otherwise. As a consequence,
3932  *  _synctex_next_line is necessary after.
3933  *  If either scanner or value_ref is NULL, it is considered as an error and
3934  *  SYNCTEX_STATUS_BAD_ARGUMENT is returned.
3935  */
3936 static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner)
3937 {
3938     char *end = NULL;
3939     size_t len = 0; /*  The number of bytes to copy */
3940     size_t already_len = 0;
3941     synctex_zs_s zs = {0, 0};
3942     char *string = NULL;
3943     if (NULL == scanner) {
3944         return (synctex_ss_s) {NULL, SYNCTEX_STATUS_BAD_ARGUMENT};
3945     }
3946     /*  The buffer must at least contain one character: the '\n' end of line marker */
3947     if (SYNCTEX_CUR >= SYNCTEX_END) {
3948     more_characters:
3949         zs = _synctex_buffer_get_available_size(scanner, 1);
3950         if (zs.status < SYNCTEX_STATUS_EOF) {
3951             return (synctex_ss_s) {NULL, zs.status};
3952         } else if (0 == zs.size) {
3953             return (synctex_ss_s) {NULL, SYNCTEX_STATUS_EOF};
3954         }
3955     }
3956     /*  Now we are sure that there is at least one available character, either because
3957      *  SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */
3958     /*  end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */
3959     end = SYNCTEX_CUR;
3960     /*  We scan all the characters up to the next '\n' */
3961     while (end < SYNCTEX_END && *end != '\n') {
3962         ++end;
3963     }
3964     /*  OK, we found where to stop:
3965      *      either end == SYNCTEX_END
3966      *      or *end == '\n' */
3967     len = end - SYNCTEX_CUR;
3968     if (len < UINT_MAX - already_len) {
3969         if ((string = realloc(string, len + already_len + 1)) != NULL) {
3970             if (memcpy(string + already_len, SYNCTEX_CUR, len)) {
3971                 already_len += len;
3972                 string[already_len] = '\0'; /*  Terminate the string */
3973                 SYNCTEX_CUR += len;         /*  Eventually advance to the terminating '\n' */
3974                 if (SYNCTEX_CUR == SYNCTEX_END) {
3975                     /* No \n found*/
3976                     goto more_characters;
3977                 }
3978                 /* trim the trailing whites */
3979                 len = already_len;
3980                 while (len > 0) {
3981                     already_len = len--;
3982                     if (string[len] != ' ') {
3983                         break;
3984                     }
3985                 }
3986                 string[already_len] = '\0';
3987                 return (synctex_ss_s) {string, SYNCTEX_STATUS_OK};
3988             }
3989             free(string);
3990             _synctex_error("could not copy memory (1).");
3991             return (synctex_ss_s) {NULL, SYNCTEX_STATUS_ERROR};
3992         }
3993     }
3994     _synctex_error("could not (re)allocate memory (1).");
3995     return (synctex_ss_s) {NULL, SYNCTEX_STATUS_ERROR};
3996 }
3997 
3998 /*  Used when parsing the synctex file.
3999  *  Read an Input record.
4000  *  - parameter scanner: non NULL scanner
4001  *  - returns SYNCTEX_STATUS_OK on successful completions, others values otherwise.
4002  */
4003 static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner)
4004 {
4005     synctex_node_p input = NULL;
4006     synctex_status_t status = SYNCTEX_STATUS_BAD_ARGUMENT;
4007     synctex_zs_s zs = {0, 0};
4008     if (NULL == scanner) {
4009         return (synctex_ns_s) {NULL, status};
4010     }
4011     if ((status = _synctex_match_string(scanner, SYNCTEX_INPUT_MARK)) < SYNCTEX_STATUS_OK) {
4012         return (synctex_ns_s) {NULL, status};
4013     }
4014     /*  Create a node */
4015     if (NULL == (input = _synctex_new_input(scanner))) {
4016         _synctex_error("Could not create an input node.");
4017         return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4018     }
4019     /*  Decode the tag  */
4020     if ((status = _synctex_data_decode_tag(input)) < SYNCTEX_STATUS_OK) {
4021         _synctex_error("Bad format of input node.");
4022         synctex_node_free(input);
4023         return (synctex_ns_s) {NULL, status};
4024     }
4025     /*  The next character is a field separator, we expect one character in the buffer. */
4026     zs = _synctex_buffer_get_available_size(scanner, 1);
4027     if (zs.status <= SYNCTEX_STATUS_ERROR) {
4028         return (synctex_ns_s) {NULL, status};
4029     }
4030     if (0 == zs.size) {
4031         return (synctex_ns_s) {NULL, SYNCTEX_STATUS_EOF};
4032     }
4033     /*  We can now safely advance to the next character, stepping over the field separator. */
4034     ++SYNCTEX_CUR;
4035     --zs.size;
4036     /*  Then we scan the file name */
4037     if ((status = _synctex_data_decode_name(input)) < SYNCTEX_STATUS_OK) {
4038         synctex_node_free(input);
4039         _synctex_next_line(scanner); /* Ignore this whole line */
4040         return (synctex_ns_s) {NULL, status};
4041     }
4042     /*  Prepend this input node to the input linked list of the scanner */
4043     __synctex_tree_set_sibling(input, scanner->input); /* input has no parent */
4044     scanner->input = input;
4045 #ifdef SYNCTEX_VERBOSE
4046     synctex_node_log(input);
4047 #endif
4048     return (synctex_ns_s) {input, _synctex_next_line(scanner)}; /*  read the line termination character, if any */
4049 }
4050 
4051 typedef synctex_is_s (*synctex_decoder_t)(synctex_scanner_p);
4052 
4053 /*  Used when parsing the synctex file.
4054  *  Read one of the settings.
4055  *  On normal completion, returns SYNCTEX_STATUS_OK.
4056  *  On error, returns SYNCTEX_STATUS_ERROR.
4057  *  Both arguments must not be NULL.
4058  *  On return, the scanner points to the next character after the decoded object whatever it is.
4059  *  It is the responsibility of the caller to prepare the scanner for the next line.
4060  */
4061 static synctex_status_t _synctex_scan_named(synctex_scanner_p scanner, const char *name)
4062 {
4063     synctex_status_t status = 0;
4064     if (NULL == scanner || NULL == name) {
4065         return SYNCTEX_STATUS_BAD_ARGUMENT;
4066     }
4067 not_found:
4068     status = _synctex_match_string(scanner, name);
4069     if (status < SYNCTEX_STATUS_NOT_OK) {
4070         return status;
4071     } else if (status == SYNCTEX_STATUS_NOT_OK) {
4072         status = _synctex_next_line(scanner);
4073         if (status < SYNCTEX_STATUS_OK) {
4074             return status;
4075         }
4076         goto not_found;
4077     }
4078     return SYNCTEX_STATUS_OK;
4079 }
4080 
4081 /*  Used when parsing the synctex file.
4082  *  Read the preamble.
4083  */
4084 static synctex_status_t _synctex_scan_preamble(synctex_scanner_p scanner)
4085 {
4086     synctex_status_t status = 0;
4087     synctex_is_s is = {0, 0};
4088     synctex_ss_s ss = {NULL, 0};
4089     if (NULL == scanner) {
4090         return SYNCTEX_STATUS_BAD_ARGUMENT;
4091     }
4092     status = _synctex_scan_named(scanner, "SyncTeX Version:");
4093     if (status < SYNCTEX_STATUS_OK) {
4094         return status;
4095     }
4096     is = _synctex_decode_int(scanner);
4097     if (is.status < SYNCTEX_STATUS_OK) {
4098         return is.status;
4099     }
4100     status = _synctex_next_line(scanner);
4101     if (status < SYNCTEX_STATUS_OK) {
4102         return status;
4103     }
4104     scanner->version = is.integer;
4105     /*  Read all the input records */
4106     do {
4107         status = __synctex_parse_new_input(scanner).status;
4108         if (status < SYNCTEX_STATUS_NOT_OK) {
4109             return status;
4110         }
4111     } while (status == SYNCTEX_STATUS_OK);
4112     /*  the loop exits when status == SYNCTEX_STATUS_NOT_OK */
4113     /*  Now read all the required settings. */
4114     if ((status = _synctex_scan_named(scanner, "Output:")) < SYNCTEX_STATUS_OK) {
4115         return status;
4116     }
4117     if ((ss = _synctex_decode_string(scanner)).status < SYNCTEX_STATUS_OK) {
4118         return is.status;
4119     }
4120     if ((status = _synctex_next_line(scanner)) < SYNCTEX_STATUS_OK) {
4121         return status;
4122     }
4123     scanner->output_fmt = ss.string;
4124     if ((status = _synctex_scan_named(scanner, "Magnification:")) < SYNCTEX_STATUS_OK) {
4125         return status;
4126     }
4127     if ((is = _synctex_decode_int(scanner)).status < SYNCTEX_STATUS_OK) {
4128         return is.status;
4129     }
4130     if ((status = _synctex_next_line(scanner)) < SYNCTEX_STATUS_OK) {
4131         return status;
4132     }
4133     scanner->pre_magnification = is.integer;
4134     if ((status = _synctex_scan_named(scanner, "Unit:")) < SYNCTEX_STATUS_OK) {
4135         return status;
4136     }
4137     if ((is = _synctex_decode_int(scanner)).status < SYNCTEX_STATUS_OK) {
4138         return is.status;
4139     }
4140     if ((status = _synctex_next_line(scanner)) < SYNCTEX_STATUS_OK) {
4141         return status;
4142     }
4143     scanner->pre_unit = is.integer;
4144     if ((status = _synctex_scan_named(scanner, "X Offset:")) < SYNCTEX_STATUS_OK) {
4145         return status;
4146     }
4147     if ((is = _synctex_decode_int(scanner)).status < SYNCTEX_STATUS_OK) {
4148         return is.status;
4149     }
4150     if ((status = _synctex_next_line(scanner)) < SYNCTEX_STATUS_OK) {
4151         return status;
4152     }
4153     scanner->pre_x_offset = is.integer;
4154     if ((status = _synctex_scan_named(scanner, "Y Offset:")) < SYNCTEX_STATUS_OK) {
4155         return status;
4156     }
4157     if ((is = _synctex_decode_int(scanner)).status < SYNCTEX_STATUS_OK) {
4158         return is.status;
4159     }
4160     if ((status = _synctex_next_line(scanner)) < SYNCTEX_STATUS_OK) {
4161         return status;
4162     }
4163     scanner->pre_y_offset = is.integer;
4164     return SYNCTEX_STATUS_OK;
4165 }
4166 
4167 /*  parse a float with a dimension */
4168 static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner)
4169 {
4170     synctex_fs_s fs = {0, 0};
4171     synctex_zs_s zs = {0, 0};
4172     char *endptr = NULL;
4173 #ifdef HAVE_SETLOCALE
4174     char *loc = setlocale(LC_NUMERIC, NULL);
4175 #endif
4176     if (NULL == scanner) {
4177         return (synctex_fs_s) {0, SYNCTEX_STATUS_BAD_ARGUMENT};
4178     }
4179     zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE);
4180     if (zs.status < SYNCTEX_STATUS_EOF) {
4181         _synctex_error("Problem with float.");
4182         return (synctex_fs_s) {0, zs.status};
4183     }
4184 #ifdef HAVE_SETLOCALE
4185     setlocale(LC_NUMERIC, "C");
4186 #endif
4187     fs.value = strtod(SYNCTEX_CUR, &endptr);
4188 #ifdef HAVE_SETLOCALE
4189     setlocale(LC_NUMERIC, loc);
4190 #endif
4191     if (endptr == SYNCTEX_CUR) {
4192         _synctex_error("A float was expected.");
4193         return (synctex_fs_s) {0, SYNCTEX_STATUS_ERROR};
4194     }
4195     SYNCTEX_CUR = endptr;
4196     if ((fs.status = _synctex_match_string(scanner, "in")) >= SYNCTEX_STATUS_OK) {
4197         fs.value *= 72.27f * 65536;
4198     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4199     report_unit_error:
4200         _synctex_error("problem with unit.");
4201         return fs;
4202     } else if ((fs.status = _synctex_match_string(scanner, "cm")) >= SYNCTEX_STATUS_OK) {
4203         fs.value *= 72.27f * 65536 / 2.54f;
4204     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4205         goto report_unit_error;
4206     } else if ((fs.status = _synctex_match_string(scanner, "mm")) >= SYNCTEX_STATUS_OK) {
4207         fs.value *= 72.27f * 65536 / 25.4f;
4208     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4209         goto report_unit_error;
4210     } else if ((fs.status = _synctex_match_string(scanner, "pt")) >= SYNCTEX_STATUS_OK) {
4211         fs.value *= 65536.0f;
4212     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4213         goto report_unit_error;
4214     } else if ((fs.status = _synctex_match_string(scanner, "bp")) >= SYNCTEX_STATUS_OK) {
4215         fs.value *= 72.27f / 72 * 65536.0f;
4216     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4217         goto report_unit_error;
4218     } else if ((fs.status = _synctex_match_string(scanner, "pc")) >= SYNCTEX_STATUS_OK) {
4219         fs.value *= 12.0 * 65536.0f;
4220     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4221         goto report_unit_error;
4222     } else if ((fs.status = _synctex_match_string(scanner, "sp")) >= SYNCTEX_STATUS_OK) {
4223         fs.value *= 1.0f;
4224     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4225         goto report_unit_error;
4226     } else if ((fs.status = _synctex_match_string(scanner, "dd")) >= SYNCTEX_STATUS_OK) {
4227         fs.value *= 1238.0f / 1157 * 65536.0f;
4228     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4229         goto report_unit_error;
4230     } else if ((fs.status = _synctex_match_string(scanner, "cc")) >= SYNCTEX_STATUS_OK) {
4231         fs.value *= 14856.0f / 1157 * 65536;
4232     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4233         goto report_unit_error;
4234     } else if ((fs.status = _synctex_match_string(scanner, "nd")) >= SYNCTEX_STATUS_OK) {
4235         fs.value *= 685.0f / 642 * 65536;
4236     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4237         goto report_unit_error;
4238     } else if ((fs.status = _synctex_match_string(scanner, "nc")) >= SYNCTEX_STATUS_OK) {
4239         fs.value *= 1370.0f / 107 * 65536;
4240     } else if (fs.status < SYNCTEX_STATUS_EOF) {
4241         goto report_unit_error;
4242     }
4243     return fs;
4244 }
4245 
4246 /*  parse the post scriptum
4247  *  SYNCTEX_STATUS_OK is returned on completion
4248  *  a negative error is returned otherwise */
4249 static synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_p scanner)
4250 {
4251     synctex_status_t status = 0;
4252     synctex_fs_s fs = {0, 0};
4253     char *endptr = NULL;
4254 #ifdef HAVE_SETLOCALE
4255     char *loc = setlocale(LC_NUMERIC, NULL);
4256 #endif
4257     if (NULL == scanner) {
4258         return SYNCTEX_STATUS_BAD_ARGUMENT;
4259     }
4260     /*  Scan the file until a post scriptum line is found */
4261 post_scriptum_not_found:
4262     status = _synctex_match_string(scanner, "Post scriptum:");
4263     if (status < SYNCTEX_STATUS_NOT_OK) {
4264         return status;
4265     }
4266     if (status == SYNCTEX_STATUS_NOT_OK) {
4267         status = _synctex_next_line(scanner);
4268         if (status < SYNCTEX_STATUS_EOF) {
4269             return status;
4270         } else if (status < SYNCTEX_STATUS_OK) {
4271             return SYNCTEX_STATUS_OK; /*  The EOF is found, we have properly scanned the file */
4272         }
4273         goto post_scriptum_not_found;
4274     }
4275     /*  We found the name, advance to the next line. */
4276 next_line:
4277     status = _synctex_next_line(scanner);
4278     if (status < SYNCTEX_STATUS_EOF) {
4279         return status;
4280     } else if (status < SYNCTEX_STATUS_OK) {
4281         return SYNCTEX_STATUS_OK; /*  The EOF is found, we have properly scanned the file */
4282     }
4283     /*  Scanning the information */
4284     status = _synctex_match_string(scanner, "Magnification:");
4285     if (status == SYNCTEX_STATUS_OK) {
4286 #ifdef HAVE_SETLOCALE
4287         setlocale(LC_NUMERIC, "C");
4288 #endif
4289         scanner->unit = strtod(SYNCTEX_CUR, &endptr);
4290 #ifdef HAVE_SETLOCALE
4291         setlocale(LC_NUMERIC, loc);
4292 #endif
4293         if (endptr == SYNCTEX_CUR) {
4294             _synctex_error("bad magnification in the post scriptum, a float was expected.");
4295             return SYNCTEX_STATUS_ERROR;
4296         }
4297         if (scanner->unit <= 0) {
4298             _synctex_error("bad magnification in the post scriptum, a positive float was expected.");
4299             return SYNCTEX_STATUS_ERROR;
4300         }
4301         SYNCTEX_CUR = endptr;
4302         goto next_line;
4303     }
4304     if (status < SYNCTEX_STATUS_EOF) {
4305     report_record_problem:
4306         _synctex_error("Problem reading the Post Scriptum records");
4307         return status; /*  echo the error. */
4308     }
4309     status = _synctex_match_string(scanner, "X Offset:");
4310     if (status == SYNCTEX_STATUS_OK) {
4311         fs = _synctex_scan_float_and_dimension(scanner);
4312         if (fs.status < SYNCTEX_STATUS_OK) {
4313             _synctex_error("Problem with X offset in the Post Scriptum.");
4314             return fs.status;
4315         }
4316         scanner->x_offset = fs.value;
4317         goto next_line;
4318     } else if (status < SYNCTEX_STATUS_EOF) {
4319         goto report_record_problem;
4320     }
4321     status = _synctex_match_string(scanner, "Y Offset:");
4322     if (status == SYNCTEX_STATUS_OK) {
4323         fs = _synctex_scan_float_and_dimension(scanner);
4324         if (fs.status < SYNCTEX_STATUS_OK) {
4325             _synctex_error("Problem with Y offset in the Post Scriptum.");
4326             return fs.status;
4327         }
4328         scanner->x_offset = fs.value;
4329         goto next_line;
4330     } else if (status < SYNCTEX_STATUS_EOF) {
4331         goto report_record_problem;
4332     }
4333     goto next_line;
4334 }
4335 
4336 /*  SYNCTEX_STATUS_OK is returned if the postamble is read
4337  *  SYNCTEX_STATUS_NOT_OK is returned if the postamble is not at the current location
4338  *  a negative error otherwise
4339  *  The postamble comprises the post scriptum section.
4340  */
4341 static synctex_status_t _synctex_scan_postamble(synctex_scanner_p scanner)
4342 {
4343     synctex_status_t status = 0;
4344     synctex_is_s is = {0, 0};
4345     if (NULL == scanner) {
4346         return SYNCTEX_STATUS_BAD_ARGUMENT;
4347     }
4348     if (!scanner->flags.postamble && (status = _synctex_match_string(scanner, "Postamble:")) < SYNCTEX_STATUS_OK) {
4349         return status;
4350     }
4351 count_again:
4352     if ((status = _synctex_next_line(scanner)) < SYNCTEX_STATUS_OK) {
4353         return status;
4354     }
4355     if ((status = _synctex_scan_named(scanner, "Count:")) < SYNCTEX_STATUS_EOF) {
4356         return status;                       /*  forward the error */
4357     } else if (status < SYNCTEX_STATUS_OK) { /*  No Count record found */
4358         goto count_again;
4359     }
4360     if ((is = _synctex_decode_int(scanner)).status < SYNCTEX_STATUS_OK) {
4361         return is.status;
4362     }
4363     if ((status = _synctex_next_line(scanner)) < SYNCTEX_STATUS_OK) {
4364         return status;
4365     }
4366     scanner->count = is.integer;
4367     /*  Now we scan the last part of the SyncTeX file: the Post Scriptum section. */
4368     return _synctex_scan_post_scriptum(scanner);
4369 }
4370 
4371 /*  Horizontal boxes also have visible size.
4372  *  Visible size are bigger than real size.
4373  *  For example 0 width boxes may contain text.
4374  *  At creation time, the visible size is set to the values of the real size.
4375  */
4376 static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box)
4377 {
4378     if (box) {
4379         switch (synctex_node_type(box)) {
4380         case synctex_node_type_hbox:
4381             _synctex_data_set_h_V(box, _synctex_data_h(box));
4382             _synctex_data_set_v_V(box, _synctex_data_v(box));
4383             _synctex_data_set_width_V(box, _synctex_data_width(box));
4384             _synctex_data_set_height_V(box, _synctex_data_height(box));
4385             _synctex_data_set_depth_V(box, _synctex_data_depth(box));
4386             return SYNCTEX_STATUS_OK;
4387         default:
4388             break;
4389         }
4390     }
4391     return SYNCTEX_STATUS_BAD_ARGUMENT;
4392 }
4393 
4394 /*  This method is sent to an horizontal box to setup the visible size
4395  *  Some box have 0 width but do contain text material.
4396  *  With this method, one can enlarge the box to contain the given point (h,v).
4397  */
4398 static synctex_status_t _synctex_make_hbox_contain_point(synctex_node_p node, synctex_point_s point)
4399 {
4400     int min, max, n;
4401     if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) {
4402         return SYNCTEX_STATUS_BAD_ARGUMENT;
4403     }
4404     if ((n = _synctex_data_width_V(node)) < 0) {
4405         max = _synctex_data_h_V(node);
4406         min = max + n;
4407         if (point.h < min) {
4408             _synctex_data_set_width_V(node, point.h - max);
4409         } else if (point.h > max) {
4410             _synctex_data_set_h_V(node, point.h);
4411             _synctex_data_set_width_V(node, min - point.h);
4412         }
4413     } else {
4414         min = _synctex_data_h_V(node);
4415         max = min + n;
4416         if (point.h < min) {
4417             _synctex_data_set_h_V(node, point.h);
4418             _synctex_data_set_width_V(node, max - point.h);
4419         } else if (point.h > max) {
4420             _synctex_data_set_width_V(node, point.h - min);
4421         }
4422     }
4423     n = _synctex_data_v_V(node);
4424     min = n - _synctex_data_height_V(node);
4425     max = n + _synctex_data_depth_V(node);
4426     if (point.v < min) {
4427         _synctex_data_set_height_V(node, n - point.v);
4428     } else if (point.v > max) {
4429         _synctex_data_set_depth_V(node, point.v - n);
4430     }
4431     return SYNCTEX_STATUS_OK;
4432 }
4433 static synctex_status_t _synctex_make_hbox_contain_box(synctex_node_p node, synctex_box_s box)
4434 {
4435     int min, max, n;
4436     if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) {
4437         return SYNCTEX_STATUS_BAD_ARGUMENT;
4438     }
4439     if ((n = _synctex_data_width_V(node)) < 0) {
4440         max = _synctex_data_h_V(node);
4441         min = max + n;
4442         if (box.min.h < min) {
4443             _synctex_data_set_width_V(node, box.min.h - max);
4444         } else if (box.max.h > max) {
4445             _synctex_data_set_h_V(node, box.max.h);
4446             _synctex_data_set_width_V(node, min - box.max.h);
4447         }
4448     } else {
4449         min = _synctex_data_h_V(node);
4450         max = min + n;
4451         if (box.min.h < min) {
4452             _synctex_data_set_h_V(node, box.min.h);
4453             _synctex_data_set_width_V(node, max - box.min.h);
4454         } else if (box.max.h > max) {
4455             _synctex_data_set_width_V(node, box.max.h - min);
4456         }
4457     }
4458     n = _synctex_data_v_V(node);
4459     min = n - _synctex_data_height_V(node);
4460     max = n + _synctex_data_depth_V(node);
4461     if (box.min.v < min) {
4462         _synctex_data_set_height_V(node, n - box.min.v);
4463     } else if (box.max.v > max) {
4464         _synctex_data_set_depth_V(node, box.max.v - n);
4465     }
4466     return SYNCTEX_STATUS_OK;
4467 }
4468 #ifdef SYNCTEX_NOTHING
4469 #pragma mark -
4470 #pragma mark SPECIAL CHARACTERS
4471 #endif
4472 
4473 /*  Here are the control characters that strat each line of the synctex output file.
4474  *  Their values define the meaning of the line.
4475  */
4476 #define SYNCTEX_CHAR_BEGIN_SHEET '{'
4477 #define SYNCTEX_CHAR_END_SHEET '}'
4478 #define SYNCTEX_CHAR_BEGIN_FORM '<'
4479 #define SYNCTEX_CHAR_END_FORM '>'
4480 #define SYNCTEX_CHAR_BEGIN_VBOX '['
4481 #define SYNCTEX_CHAR_END_VBOX ']'
4482 #define SYNCTEX_CHAR_BEGIN_HBOX '('
4483 #define SYNCTEX_CHAR_END_HBOX ')'
4484 #define SYNCTEX_CHAR_ANCHOR '!'
4485 #define SYNCTEX_CHAR_VOID_VBOX 'v'
4486 #define SYNCTEX_CHAR_VOID_HBOX 'h'
4487 #define SYNCTEX_CHAR_KERN 'k'
4488 #define SYNCTEX_CHAR_GLUE 'g'
4489 #define SYNCTEX_CHAR_RULE 'r'
4490 #define SYNCTEX_CHAR_MATH '$'
4491 #define SYNCTEX_CHAR_FORM_REF 'f'
4492 #define SYNCTEX_CHAR_BOUNDARY 'x'
4493 #define SYNCTEX_CHAR_CHARACTER 'c'
4494 #define SYNCTEX_CHAR_COMMENT '%'
4495 
4496 #define SYNCTEX_RETURN(STATUS) return STATUS;
4497 
4498 #ifdef SYNCTEX_NOTHING
4499 #pragma mark -
4500 #pragma mark SCANNERS & PARSERS
4501 #endif
4502 
4503 #define SYNCTEX_DECODE_FAILED(NODE, WHAT) (_synctex_data_decode_##WHAT(NODE) < SYNCTEX_STATUS_OK)
4504 #define SYNCTEX_DECODE_FAILED_V(NODE, WHAT) (_synctex_data_decode_##WHAT##_v(NODE) < SYNCTEX_STATUS_OK)
4505 
4506 #define SYNCTEX_NS_NULL                                                                                                                                                                                                                        \
4507     (synctex_ns_s)                                                                                                                                                                                                                             \
4508     {                                                                                                                                                                                                                                          \
4509         NULL, SYNCTEX_STATUS_NOT_OK                                                                                                                                                                                                            \
4510     }
4511 static synctex_ns_s _synctex_parse_new_sheet(synctex_scanner_p scanner)
4512 {
4513     synctex_node_p node;
4514     if ((node = _synctex_new_sheet(scanner))) {
4515         if (SYNCTEX_DECODE_FAILED(node, page)) {
4516             _synctex_error("Bad sheet record.");
4517         } else if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4518             _synctex_error("Missing end of sheet.");
4519         } else {
4520             /* Now set the owner */
4521             if (scanner->sheet) {
4522                 synctex_node_p last_sheet = scanner->sheet;
4523                 synctex_node_p next_sheet = NULL;
4524                 while ((next_sheet = __synctex_tree_sibling(last_sheet))) {
4525                     last_sheet = next_sheet;
4526                 }
4527                 __synctex_tree_set_sibling(last_sheet, node); /* sheets have no parent */
4528             } else {
4529                 scanner->sheet = node;
4530             }
4531             return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4532         }
4533         _synctex_free_node(node);
4534     }
4535     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4536 }
4537 /**
4538  *  - requirement: scanner != NULL
4539  */
4540 static synctex_ns_s _synctex_parse_new_form(synctex_scanner_p scanner)
4541 {
4542     synctex_node_p node;
4543     if ((node = _synctex_new_form(scanner))) {
4544         if (SYNCTEX_DECODE_FAILED(node, tag)) {
4545             _synctex_error("Bad sheet record.");
4546         } else if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4547             _synctex_error("Missing end of form.");
4548         } else {
4549             /* Now set the owner */
4550             if (scanner->form) {
4551                 synctex_node_p last_form = scanner->form;
4552                 synctex_node_p next_form = NULL;
4553                 while ((next_form = __synctex_tree_sibling(last_form))) {
4554                     last_form = next_form;
4555                 }
4556                 __synctex_tree_set_sibling(last_form, node);
4557             } else {
4558                 scanner->form = node;
4559             }
4560             return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4561         }
4562         _synctex_free_node(node);
4563     }
4564     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4565 }
4566 #define SYNCTEX_SHOULD_DECODE_FAILED(NODE, WHAT) (_synctex_data_has_##WHAT(NODE) && (_synctex_data_decode_##WHAT(NODE) < SYNCTEX_STATUS_OK))
4567 #define SYNCTEX_SHOULD_DECODE_FAILED_V(NODE, WHAT) (_synctex_data_has_##WHAT(NODE) && (_synctex_data_decode_##WHAT##_v(NODE) < SYNCTEX_STATUS_OK))
4568 
4569 static synctex_status_t _synctex_data_decode_tlchvwhd(synctex_node_p node)
4570 {
4571     return SYNCTEX_SHOULD_DECODE_FAILED(node, tag) || SYNCTEX_SHOULD_DECODE_FAILED(node, line) || SYNCTEX_SHOULD_DECODE_FAILED(node, column) || SYNCTEX_SHOULD_DECODE_FAILED(node, h) || SYNCTEX_SHOULD_DECODE_FAILED_V(node, v) ||
4572         SYNCTEX_SHOULD_DECODE_FAILED(node, width) || SYNCTEX_SHOULD_DECODE_FAILED(node, height) || SYNCTEX_SHOULD_DECODE_FAILED(node, depth);
4573 }
4574 static synctex_ns_s _synctex_parse_new_vbox(synctex_scanner_p scanner)
4575 {
4576     synctex_node_p node;
4577     if ((node = _synctex_new_vbox(scanner))) {
4578         if (_synctex_data_decode_tlchvwhd(node)) {
4579             _synctex_error("Bad vbox record.");
4580             _synctex_next_line(scanner);
4581         out:
4582             _synctex_free_node(node);
4583             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4584         }
4585         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4586             _synctex_error("Missing end of vbox.");
4587             goto out;
4588         }
4589         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4590     }
4591     _synctex_next_line(scanner);
4592     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4593 }
4594 SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend_tlc(synctex_node_p node);
4595 static synctex_ns_s _synctex_parse_new_hbox(synctex_scanner_p scanner)
4596 {
4597     synctex_node_p node;
4598     if ((node = _synctex_new_hbox(scanner))) {
4599         if (_synctex_data_decode_tlchvwhd(node)) {
4600             _synctex_error("Bad hbox record.");
4601             _synctex_next_line(scanner);
4602         out:
4603             _synctex_free_node(node);
4604             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4605         }
4606         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4607             _synctex_error("Missing end of hbox.");
4608             goto out;
4609         }
4610         if (_synctex_setup_visible_hbox(node) < SYNCTEX_STATUS_OK) {
4611             _synctex_error("Unexpected error (_synctex_parse_new_hbox).");
4612             goto out;
4613         }
4614         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4615     }
4616     _synctex_next_line(scanner);
4617     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4618 }
4619 static synctex_ns_s _synctex_parse_new_void_vbox(synctex_scanner_p scanner)
4620 {
4621     synctex_node_p node;
4622     if ((node = _synctex_new_void_vbox(scanner))) {
4623         if (_synctex_data_decode_tlchvwhd(node)) {
4624             _synctex_error("Bad void vbox record.");
4625             _synctex_next_line(scanner);
4626         out:
4627             _synctex_free_node(node);
4628             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4629         }
4630         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4631             _synctex_error("Missing end of container.");
4632             goto out;
4633         }
4634         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4635     }
4636     _synctex_next_line(scanner);
4637     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4638 }
4639 static synctex_ns_s _synctex_parse_new_void_hbox(synctex_scanner_p scanner)
4640 {
4641     synctex_node_p node;
4642     if ((node = _synctex_new_void_hbox(scanner))) {
4643         if (_synctex_data_decode_tlchvwhd(node)) {
4644             _synctex_error("Bad void hbox record.");
4645             _synctex_next_line(scanner);
4646         out:
4647             _synctex_free_node(node);
4648             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4649         }
4650         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4651             _synctex_error("Missing end of container.");
4652             goto out;
4653         }
4654         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4655     }
4656     _synctex_next_line(scanner);
4657     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4658 }
4659 static synctex_ns_s _synctex_parse_new_kern(synctex_scanner_p scanner)
4660 {
4661     synctex_node_p node;
4662     if ((node = _synctex_new_kern(scanner))) {
4663         if (_synctex_data_decode_tlchvwhd(node)) {
4664             _synctex_error("Bad kern record.");
4665             _synctex_next_line(scanner);
4666         out:
4667             _synctex_free_node(node);
4668             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4669         }
4670         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4671             _synctex_error("Missing end of container.");
4672             goto out;
4673         }
4674         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4675     }
4676     _synctex_next_line(scanner);
4677     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4678 }
4679 static synctex_ns_s _synctex_parse_new_glue(synctex_scanner_p scanner)
4680 {
4681     synctex_node_p node;
4682     if ((node = _synctex_new_glue(scanner))) {
4683         if (_synctex_data_decode_tlchvwhd(node)) {
4684             _synctex_error("Bad glue record.");
4685             _synctex_next_line(scanner);
4686         out:
4687             _synctex_free_node(node);
4688             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4689         }
4690         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4691             _synctex_error("Missing end of container.");
4692             goto out;
4693         }
4694         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4695     }
4696     _synctex_next_line(scanner);
4697     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4698 }
4699 static synctex_ns_s _synctex_parse_new_rule(synctex_scanner_p scanner)
4700 {
4701     synctex_node_p node;
4702     if ((node = _synctex_new_rule(scanner))) {
4703         if (_synctex_data_decode_tlchvwhd(node)) {
4704             _synctex_error("Bad rule record.");
4705             _synctex_next_line(scanner);
4706         out:
4707             _synctex_free_node(node);
4708             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4709         }
4710         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4711             _synctex_error("Missing end of container.");
4712             goto out;
4713         }
4714         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4715     }
4716     _synctex_next_line(scanner);
4717     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4718 }
4719 static synctex_ns_s _synctex_parse_new_math(synctex_scanner_p scanner)
4720 {
4721     synctex_node_p node;
4722     if ((node = _synctex_new_math(scanner))) {
4723         if (_synctex_data_decode_tlchvwhd(node)) {
4724             _synctex_error("Bad math record.");
4725             _synctex_next_line(scanner);
4726         out:
4727             _synctex_free_node(node);
4728             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4729         }
4730         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4731             _synctex_error("Missing end of container.");
4732             goto out;
4733         }
4734         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4735     }
4736     _synctex_next_line(scanner);
4737     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4738 }
4739 static synctex_ns_s _synctex_parse_new_boundary(synctex_scanner_p scanner)
4740 {
4741     synctex_node_p node;
4742     if ((node = _synctex_new_boundary(scanner))) {
4743         if (_synctex_data_decode_tlchvwhd(node)) {
4744             _synctex_error("Bad boundary record.");
4745             _synctex_next_line(scanner);
4746         out:
4747             _synctex_free_node(node);
4748             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4749         }
4750         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4751             _synctex_error("Missing end of container.");
4752             goto out;
4753         }
4754         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4755     }
4756     _synctex_next_line(scanner);
4757     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4758 }
4759 SYNCTEX_INLINE static synctex_ns_s _synctex_parse_new_ref(synctex_scanner_p scanner)
4760 {
4761     synctex_node_p node;
4762     if ((node = _synctex_new_ref(scanner))) {
4763         if (SYNCTEX_DECODE_FAILED(node, tag) || SYNCTEX_DECODE_FAILED(node, h) || SYNCTEX_DECODE_FAILED_V(node, v)) {
4764             _synctex_error("Bad form ref record.");
4765             _synctex_next_line(scanner);
4766         out:
4767             _synctex_free_node(node);
4768             return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4769         }
4770         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4771             _synctex_error("Missing end of container.");
4772             goto out;
4773         }
4774         return (synctex_ns_s) {node, SYNCTEX_STATUS_OK};
4775     }
4776     _synctex_next_line(scanner);
4777     return (synctex_ns_s) {NULL, SYNCTEX_STATUS_ERROR};
4778 }
4779 #undef SYNCTEX_DECODE_FAILED
4780 #undef SYNCTEX_DECODE_FAILED_V
4781 
4782 SYNCTEX_INLINE static synctex_point_s _synctex_data_point(synctex_node_p node);
4783 SYNCTEX_INLINE static synctex_point_s _synctex_data_point_V(synctex_node_p node);
4784 SYNCTEX_INLINE static synctex_point_s _synctex_data_set_point(synctex_node_p node, synctex_point_s point);
4785 SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node);
4786 SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node);
4787 SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node);
4788 
4789 SYNCTEX_INLINE static synctex_node_p _synctex_input_register_line(synctex_node_p input, synctex_node_p node)
4790 {
4791     if (node && _synctex_data_tag(input) != _synctex_data_tag(node)) {
4792         input = synctex_scanner_input_with_tag(node->class->scanner, _synctex_data_tag(node));
4793     }
4794     if (_synctex_data_line(node) > _synctex_data_line(input)) {
4795         _synctex_data_set_line(input, _synctex_data_line(node));
4796     }
4797     return input;
4798 }
4799 /**
4800  *  Scan sheets, forms and input records.
4801  *  - parameter scanner: owning scanner
4802  *  - returns: status
4803  */
4804 static synctex_status_t __synctex_parse_sfi(synctex_scanner_p scanner)
4805 {
4806     synctex_status_t status = SYNCTEX_STATUS_OK;
4807     synctex_zs_s zs = {0, 0};
4808     synctex_ns_s input = SYNCTEX_NS_NULL;
4809     synctex_node_p sheet = NULL;
4810     synctex_node_p form = NULL;
4811     synctex_node_p parent = NULL;
4812     synctex_node_p child = NULL;
4813     synctex_ns_s ns = SYNCTEX_NS_NULL;
4814     int form_depth = 0;
4815     int ignored_form_depth = 0;
4816     synctex_bool_t try_input = synctex_YES;
4817 #ifdef SYNCTEX_NOTHING
4818 #pragma mark MAIN LOOP
4819 #endif
4820 main_loop:
4821     status = SYNCTEX_STATUS_OK;
4822     sheet = form = parent = child = NULL;
4823 #define SYNCTEX_START_SCAN(WHAT) (*SYNCTEX_CUR == SYNCTEX_CHAR_##WHAT)
4824     if (SYNCTEX_CUR < SYNCTEX_END) {
4825         if (SYNCTEX_START_SCAN(BEGIN_FORM)) {
4826 #ifdef SYNCTEX_NOTHING
4827 #pragma mark + SCAN FORM
4828 #endif
4829         scan_form:
4830             ns = _synctex_parse_new_form(scanner);
4831             if (ns.status == SYNCTEX_STATUS_OK) {
4832                 ++form_depth;
4833                 if (_synctex_tree_parent(form)) {
4834                     /* This form is already being parsed */
4835                     ++ignored_form_depth;
4836                     goto ignore_loop;
4837                 }
4838                 _synctex_tree_set_parent(ns.node, form);
4839                 form = ns.node;
4840                 parent = form;
4841                 child = NULL;
4842                 goto content_loop;
4843             }
4844             if (form || sheet) {
4845                 goto content_loop;
4846             }
4847             try_input = synctex_YES;
4848             goto main_loop;
4849         } else if (SYNCTEX_START_SCAN(BEGIN_SHEET)) {
4850 #ifdef SYNCTEX_NOTHING
4851 #pragma mark + SCAN SHEET
4852 #endif
4853             try_input = synctex_YES;
4854             ns = _synctex_parse_new_sheet(scanner);
4855             if (ns.status == SYNCTEX_STATUS_OK) {
4856                 sheet = ns.node;
4857                 parent = sheet;
4858                 goto content_loop;
4859             }
4860             goto main_loop;
4861         } else if (SYNCTEX_START_SCAN(ANCHOR)) {
4862 #ifdef SYNCTEX_NOTHING
4863 #pragma mark + SCAN ANCHOR
4864 #endif
4865         scan_anchor:
4866             ++SYNCTEX_CUR;
4867             if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4868                 _synctex_error("Missing anchor.");
4869                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
4870             }
4871             if (form || sheet) {
4872                 goto content_loop;
4873             }
4874             try_input = synctex_YES;
4875             goto main_loop;
4876         } else if (SYNCTEX_START_SCAN(ANCHOR)) {
4877 #ifdef SYNCTEX_NOTHING
4878 #pragma mark + SCAN COMMENT
4879 #endif
4880             ++SYNCTEX_CUR;
4881             _synctex_next_line(scanner);
4882             try_input = synctex_YES;
4883             goto main_loop;
4884         } else if (try_input) {
4885 #ifdef SYNCTEX_NOTHING
4886 #pragma mark + SCAN INPUT
4887 #endif
4888             try_input = synctex_NO;
4889             do {
4890                 input = __synctex_parse_new_input(scanner);
4891             } while (input.status == SYNCTEX_STATUS_OK);
4892             goto main_loop;
4893         }
4894         status = _synctex_match_string(scanner, "Postamble:");
4895         if (status == SYNCTEX_STATUS_OK) {
4896             scanner->flags.postamble = 1;
4897             return status;
4898         }
4899         status = _synctex_next_line(scanner);
4900         if (status < SYNCTEX_STATUS_OK) {
4901             return status;
4902         }
4903     }
4904     /* At least 1 more character */
4905     zs = _synctex_buffer_get_available_size(scanner, 1);
4906     if (zs.size == 0) {
4907         _synctex_error("Uncomplete synctex file, postamble missing.");
4908         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
4909     }
4910     goto main_loop;
4911     /*  Unreachable. */
4912 #ifdef SYNCTEX_NOTHING
4913 #pragma mark IGNORE LOOP
4914 #endif
4915 ignore_loop:
4916     ns = SYNCTEX_NS_NULL;
4917     if (SYNCTEX_CUR < SYNCTEX_END) {
4918         if (SYNCTEX_START_SCAN(BEGIN_FORM)) {
4919             ++ignored_form_depth;
4920         } else if (SYNCTEX_START_SCAN(END_FORM)) {
4921             --ignored_form_depth;
4922         }
4923         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4924             _synctex_error("Uncomplete container.");
4925             SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
4926         }
4927     } else {
4928         zs = _synctex_buffer_get_available_size(scanner, 1);
4929         if (zs.size == 0) {
4930             _synctex_error("Uncomplete synctex file, postamble missing.");
4931             SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
4932         }
4933     }
4934     if (ignored_form_depth) {
4935         goto ignore_loop;
4936     } else {
4937         goto content_loop;
4938     }
4939 
4940 #ifdef SYNCTEX_NOTHING
4941 #pragma mark CONTENT LOOP
4942 #endif
4943 content_loop:
4944     /*  Either in a form, a sheet or a box.
4945      *  - in a sheet, "{" is not possible, only boxes and "}" at top level.
4946      *  - in a form, "{" is not possible, only boxes, "<" and ">" at top level.
4947      *  - in a box, the unique possibility is '<', '[', '(' or ">".
4948      *  We still keep the '(' for a sheet, because that dos not cost too much.
4949      *  We must also consider void boxes as children.
4950      */
4951     /* forms are everywhere */
4952     ns = SYNCTEX_NS_NULL;
4953 #ifdef SYNCTEX_VERBOSE
4954     synctex_scanner_set_display_switcher(scanner, -1);
4955     printf("NEW CONTENT LOOP\n");
4956 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
4957     synctex_node_display(sheet);
4958 #endif
4959 #endif
4960     if (SYNCTEX_CUR < SYNCTEX_END) {
4961         if (SYNCTEX_START_SCAN(BEGIN_FORM)) {
4962             goto scan_form;
4963         } else if (SYNCTEX_START_SCAN(BEGIN_VBOX)) {
4964 #ifdef SYNCTEX_NOTHING
4965 #pragma mark + SCAN VBOX
4966 #endif
4967             ns = _synctex_parse_new_vbox(scanner);
4968             if (ns.status == SYNCTEX_STATUS_OK) {
4969                 if (child) {
4970                     _synctex_node_set_sibling(child, ns.node);
4971                 } else {
4972                     _synctex_node_set_child(parent, ns.node);
4973                 }
4974                 parent = ns.node;
4975                 child = _synctex_tree_last(parent);
4976 #ifdef SYNCTEX_VERBOSE
4977                 synctex_node_log(parent);
4978 #endif
4979                 input.node = _synctex_input_register_line(input.node, parent);
4980                 goto content_loop;
4981             }
4982         } else if (SYNCTEX_START_SCAN(END_VBOX)) {
4983             if (synctex_node_type(parent) == synctex_node_type_vbox) {
4984 #ifdef SYNCTEX_NOTHING
4985 #pragma mark + SCAN XOBV
4986 #endif
4987                 ++SYNCTEX_CUR;
4988                 if (NULL == _synctex_tree_child(parent) && !form) {
4989                     /*  only void v boxes are friends */
4990                     _synctex_node_make_friend_tlc(parent);
4991                 }
4992                 child = parent;
4993                 parent = _synctex_tree_parent(child);
4994 #ifdef SYNCTEX_VERBOSE
4995                 synctex_node_log(child);
4996 #endif
4997                 if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
4998                     _synctex_error("Uncomplete container.");
4999                     SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5000                 }
5001                 goto content_loop;
5002             }
5003         } else if (SYNCTEX_START_SCAN(BEGIN_HBOX)) {
5004 #ifdef SYNCTEX_NOTHING
5005 #pragma mark + SCAN HBOX
5006 #endif
5007 #if defined(SYNCTEX_USE_CHARINDEX)
5008             synctex_charindex_t char_index = (synctex_charindex_t)(scanner->reader->charindex_offset + SYNCTEX_CUR - SYNCTEX_START);
5009             synctex_lineindex_t line_index = scanner->reader->line_number;
5010 #endif
5011             ns = _synctex_parse_new_hbox(scanner);
5012             if (ns.status == SYNCTEX_STATUS_OK) {
5013                 if (child) {
5014                     _synctex_node_set_sibling(child, ns.node);
5015                 } else {
5016                     _synctex_node_set_child(parent, ns.node);
5017                 }
5018                 parent = ns.node;
5019                 /*  add a box boundary node at the start */
5020                 if ((child = _synctex_new_box_bdry(scanner))) {
5021 #if defined(SYNCTEX_USE_CHARINDEX)
5022                     child->line_index = line_index;
5023                     child->char_index = char_index;
5024 #endif
5025                     _synctex_node_set_child(parent, child);
5026                     _synctex_data_set_tag(child, _synctex_data_tag(parent));
5027                     _synctex_data_set_line(child, _synctex_data_line(parent));
5028                     _synctex_data_set_h(child, _synctex_data_h(parent));
5029                     _synctex_data_set_v(child, _synctex_data_v(parent));
5030                     if (!form) {
5031                         __synctex_node_make_friend_tlc(child);
5032                     }
5033                 } else {
5034                     _synctex_error("Can't create box bdry record.");
5035                 }
5036 #ifdef SYNCTEX_VERBOSE
5037                 synctex_node_log(parent);
5038 #endif
5039                 input.node = _synctex_input_register_line(input.node, parent);
5040                 goto content_loop;
5041             }
5042         } else if (SYNCTEX_START_SCAN(END_HBOX)) {
5043             if (synctex_node_type(parent) == synctex_node_type_hbox) {
5044 #ifdef SYNCTEX_NOTHING
5045 #pragma mark + SCAN XOBH
5046 #endif
5047                 ++SYNCTEX_CUR;
5048                 {
5049                     /*  setting the next horizontal box at the end ensures
5050                      * that a child is recorded before any of its ancestors.
5051                      */
5052                     if (form == NULL /* && sheet != NULL*/) {
5053                         _synctex_tree_set_next_hbox(parent, _synctex_tree_next_hbox(sheet));
5054                         _synctex_tree_set_next_hbox(sheet, parent);
5055                     }
5056                     /*  Update the mean line number */
5057                     synctex_node_p node = _synctex_tree_child(parent);
5058                     synctex_node_p sibling = NULL;
5059                     /*  Ignore the first node (a box_bdry) */
5060                     if (node && (node = __synctex_tree_sibling(node))) {
5061                         unsigned int node_weight = 0;
5062                         unsigned int cumulated_line_numbers = 0;
5063                         do {
5064                             if (synctex_node_type(node) == synctex_node_type_hbox) {
5065                                 if (_synctex_data_weight(node)) {
5066                                     node_weight += _synctex_data_weight(node);
5067                                     cumulated_line_numbers += _synctex_data_mean_line(node) * _synctex_data_weight(node);
5068                                 } else {
5069                                     ++node_weight;
5070                                     cumulated_line_numbers += _synctex_data_mean_line(node);
5071                                 }
5072                             } else {
5073                                 ++node_weight;
5074                                 cumulated_line_numbers += synctex_node_line(node);
5075                             }
5076                         } while ((node = __synctex_tree_sibling(node)));
5077                         _synctex_data_set_mean_line(parent, (cumulated_line_numbers + node_weight / 2) / node_weight);
5078                         _synctex_data_set_weight(parent, node_weight);
5079                     } else {
5080                         _synctex_data_set_mean_line(parent, _synctex_data_line(parent));
5081                         _synctex_data_set_weight(parent, 1);
5082                     }
5083                     if ((sibling = _synctex_new_box_bdry(scanner))) {
5084 #if defined(SYNCTEX_USE_CHARINDEX)
5085                         sibling->line_index = child->line_index;
5086                         sibling->char_index = child->char_index;
5087 #endif
5088                         _synctex_node_set_sibling(child, sibling);
5089                         {
5090                             synctex_node_p N = child;
5091                             while (synctex_node_type(N) == synctex_node_type_ref) {
5092                                 N = _synctex_tree_arg_sibling(N);
5093                             }
5094                             _synctex_data_set_tag(sibling, _synctex_data_tag(N));
5095                             _synctex_data_set_line(sibling, _synctex_data_line(N));
5096                         }
5097                         _synctex_data_set_h(sibling, _synctex_data_h_V(parent) + _synctex_data_width_V(parent));
5098                         _synctex_data_set_v(sibling, _synctex_data_v_V(parent));
5099                         child = sibling;
5100                     } else {
5101                         _synctex_error("Can't create box bdry record.");
5102                     }
5103                     sibling = _synctex_tree_child(parent);
5104                     _synctex_data_set_point(sibling, _synctex_data_point_V(parent));
5105                     child = parent;
5106                     parent = _synctex_tree_parent(child);
5107                     _synctex_make_hbox_contain_box(parent, _synctex_data_box_V(child));
5108 #ifdef SYNCTEX_VERBOSE
5109                     synctex_node_log(child);
5110 #endif
5111                 }
5112                 if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
5113                     _synctex_error("Uncomplete container.");
5114                     SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5115                 }
5116                 goto content_loop;
5117             }
5118         } else if (SYNCTEX_START_SCAN(VOID_VBOX)) {
5119 #ifdef SYNCTEX_NOTHING
5120 #pragma mark + SCAN VOID VBOX
5121 #endif
5122             ns = _synctex_parse_new_void_vbox(scanner);
5123             if (ns.status == SYNCTEX_STATUS_OK) {
5124                 if (child) {
5125                     _synctex_node_set_sibling(child, ns.node);
5126                 } else {
5127                     _synctex_node_set_child(parent, ns.node);
5128                 }
5129                 child = ns.node;
5130 #ifdef SYNCTEX_VERBOSE
5131                 synctex_node_log(child);
5132 #endif
5133                 input.node = _synctex_input_register_line(input.node, child);
5134                 goto content_loop;
5135             }
5136         } else if (SYNCTEX_START_SCAN(VOID_HBOX)) {
5137 #ifdef SYNCTEX_NOTHING
5138 #pragma mark + SCAN VOID HBOX
5139 #endif
5140             ns = _synctex_parse_new_void_hbox(scanner);
5141             if (ns.status == SYNCTEX_STATUS_OK) {
5142                 if (_synctex_data_width(ns.node) < 0) {
5143                     printf("Negative width\n");
5144                 }
5145                 if (child) {
5146                     _synctex_node_set_sibling(child, ns.node);
5147                 } else {
5148                     _synctex_node_set_child(parent, ns.node);
5149                 }
5150                 child = ns.node;
5151                 _synctex_make_hbox_contain_box(parent, _synctex_data_box(child));
5152 #ifdef SYNCTEX_VERBOSE
5153                 synctex_node_log(child);
5154 #endif
5155                 input.node = _synctex_input_register_line(input.node, child);
5156                 goto content_loop;
5157             }
5158         } else if (SYNCTEX_START_SCAN(KERN)) {
5159 #ifdef SYNCTEX_NOTHING
5160 #pragma mark + SCAN KERN
5161 #endif
5162             ns = _synctex_parse_new_kern(scanner);
5163             /* continue_scan: */
5164             if (ns.status == SYNCTEX_STATUS_OK) {
5165                 if (child) {
5166                     _synctex_node_set_sibling(child, ns.node);
5167                 } else {
5168                     _synctex_node_set_child(parent, ns.node);
5169                 }
5170                 child = ns.node;
5171                 if (!form) {
5172                     __synctex_node_make_friend_tlc(child);
5173                 }
5174                 _synctex_make_hbox_contain_box(parent, _synctex_data_xob(child));
5175 #ifdef SYNCTEX_VERBOSE
5176                 synctex_node_log(child);
5177 #endif
5178                 input.node = _synctex_input_register_line(input.node, child);
5179                 goto content_loop;
5180             }
5181         } else if (SYNCTEX_START_SCAN(GLUE)) {
5182 #ifdef SYNCTEX_NOTHING
5183 #pragma mark + SCAN GLUE
5184 #endif
5185             ns = _synctex_parse_new_glue(scanner);
5186             if (ns.status == SYNCTEX_STATUS_OK) {
5187                 if (child) {
5188                     _synctex_node_set_sibling(child, ns.node);
5189                 } else {
5190                     _synctex_node_set_child(parent, ns.node);
5191                 }
5192                 child = ns.node;
5193                 if (!form) {
5194                     __synctex_node_make_friend_tlc(child);
5195                 }
5196                 _synctex_make_hbox_contain_point(parent, _synctex_data_point(child));
5197 #ifdef SYNCTEX_VERBOSE
5198                 synctex_node_log(child);
5199 #endif
5200                 input.node = _synctex_input_register_line(input.node, child);
5201                 goto content_loop;
5202             }
5203         } else if (SYNCTEX_START_SCAN(RULE)) {
5204 #ifdef SYNCTEX_NOTHING
5205 #pragma mark + SCAN RULE
5206 #endif
5207             ns = _synctex_parse_new_rule(scanner);
5208             if (ns.status == SYNCTEX_STATUS_OK) {
5209                 if (child) {
5210                     _synctex_node_set_sibling(child, ns.node);
5211                 } else {
5212                     _synctex_node_set_child(parent, ns.node);
5213                 }
5214                 child = ns.node;
5215                 if (!form) {
5216                     __synctex_node_make_friend_tlc(child);
5217                 }
5218                 /* Rules are sometimes far too big
5219 _synctex_make_hbox_contain_box(parent,_synctex_data_box(child));
5220                  */
5221 #ifdef SYNCTEX_VERBOSE
5222                 synctex_node_log(child);
5223 #endif
5224                 input.node = _synctex_input_register_line(input.node, child);
5225                 goto content_loop;
5226             }
5227         } else if (SYNCTEX_START_SCAN(MATH)) {
5228 #ifdef SYNCTEX_NOTHING
5229 #pragma mark + SCAN MATH
5230 #endif
5231             ns = _synctex_parse_new_math(scanner);
5232             if (ns.status == SYNCTEX_STATUS_OK) {
5233                 if (child) {
5234                     _synctex_node_set_sibling(child, ns.node);
5235                 } else {
5236                     _synctex_node_set_child(parent, ns.node);
5237                 }
5238                 child = ns.node;
5239                 if (!form) {
5240                     __synctex_node_make_friend_tlc(child);
5241                 }
5242                 _synctex_make_hbox_contain_point(parent, _synctex_data_point(child));
5243 #ifdef SYNCTEX_VERBOSE
5244                 synctex_node_log(child);
5245 #endif
5246                 input.node = _synctex_input_register_line(input.node, child);
5247                 goto content_loop;
5248             }
5249         } else if (SYNCTEX_START_SCAN(FORM_REF)) {
5250 #ifdef SYNCTEX_NOTHING
5251 #pragma mark + SCAN FORM REF
5252 #endif
5253 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5254             synctex_node_display(parent);
5255             synctex_node_display(child);
5256 #endif
5257             ns = _synctex_parse_new_ref(scanner);
5258             if (ns.status == SYNCTEX_STATUS_OK) {
5259                 if (child) {
5260                     _synctex_node_set_sibling(child, ns.node);
5261                 } else {
5262                     _synctex_node_set_child(parent, ns.node);
5263                 }
5264                 child = ns.node;
5265                 if (form) {
5266                     if (scanner->ref_in_form) {
5267                         synctex_tree_set_friend(child, scanner->ref_in_form);
5268                     }
5269                     scanner->ref_in_form = child;
5270                 } else {
5271                     if (scanner->ref_in_sheet) {
5272                         synctex_tree_set_friend(child, scanner->ref_in_sheet);
5273                     }
5274                     scanner->ref_in_sheet = child;
5275                 }
5276 #ifdef SYNCTEX_VERBOSE
5277                 synctex_node_log(child);
5278 #endif
5279                 goto content_loop;
5280             }
5281         } else if (SYNCTEX_START_SCAN(BOUNDARY)) {
5282 #ifdef SYNCTEX_NOTHING
5283 #pragma mark + SCAN BOUNDARY
5284 #endif
5285             ns = _synctex_parse_new_boundary(scanner);
5286             if (ns.status == SYNCTEX_STATUS_OK) {
5287                 if (child) {
5288                     _synctex_node_set_sibling(child, ns.node);
5289                 } else {
5290                     _synctex_node_set_child(parent, ns.node);
5291                 }
5292                 child = ns.node;
5293                 if (!form) {
5294                     __synctex_node_make_friend_tlc(child);
5295                 }
5296                 _synctex_make_hbox_contain_point(parent, _synctex_data_point(child));
5297 #ifdef SYNCTEX_VERBOSE
5298                 synctex_node_log(child);
5299 #endif
5300                 input.node = _synctex_input_register_line(input.node, child);
5301                 goto content_loop;
5302             }
5303         } else if (SYNCTEX_START_SCAN(CHARACTER)) {
5304 #ifdef SYNCTEX_NOTHING
5305 #pragma mark + SCAN CHARACTER
5306 #endif
5307             ++SYNCTEX_CUR;
5308             if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
5309                 _synctex_error("Missing end of container.");
5310                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5311             }
5312             goto content_loop;
5313         } else if (SYNCTEX_START_SCAN(ANCHOR)) {
5314 #ifdef SYNCTEX_NOTHING
5315 #pragma mark + SCAN ANCHOR
5316 #endif
5317             goto scan_anchor;
5318         } else if (SYNCTEX_START_SCAN(END_SHEET)) {
5319             if (sheet && parent == sheet) {
5320 #ifdef SYNCTEX_NOTHING
5321 #pragma mark + SCAN TEEHS
5322 #endif
5323                 ++SYNCTEX_CUR;
5324                 if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
5325                     _synctex_error("Missing anchor.");
5326                 }
5327                 parent = sheet = NULL;
5328                 goto main_loop;
5329             }
5330         } else if (SYNCTEX_START_SCAN(END_FORM)) {
5331             if (parent == form && form_depth > 0) {
5332 #ifdef SYNCTEX_NOTHING
5333 #pragma mark + SCAN MROF
5334 #endif
5335                 ++SYNCTEX_CUR;
5336                 --form_depth;
5337                 if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK && (form_depth || sheet)) {
5338                     _synctex_error("Missing end of container.");
5339                     return SYNCTEX_STATUS_ERROR;
5340                 }
5341                 if ((parent = _synctex_tree_parent(form))) {
5342                     _synctex_tree_reset_parent(form);
5343                     child = form;
5344                     form = parent;
5345                     goto content_loop;
5346                 } else if (sheet) {
5347                     form = NULL;
5348                     parent = sheet;
5349                     child = synctex_node_last_sibling(child);
5350                     goto content_loop;
5351                 }
5352                 goto main_loop;
5353             }
5354         }
5355         _synctex_error("Ignored record <%.20s...>(line %i)\n", SYNCTEX_CUR, scanner->reader->line_number + 1);
5356         if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
5357             _synctex_error("Missing end of sheet/form.");
5358             SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5359         }
5360         goto content_loop;
5361     }
5362     zs = _synctex_buffer_get_available_size(scanner, 1);
5363     if (zs.size == 0) {
5364         _synctex_error("Uncomplete synctex file, postamble missing.");
5365         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5366     }
5367     goto content_loop;
5368 }
5369 /**
5370  *  Replace ref in its tree hierarchy by a single box
5371  *  proxy to the contents of the associated form.
5372  *  - argument ref: a ref node with no friend
5373  *  - return the proxy created.
5374  *  - note: Does nothing if ref is not owned.
5375  *  - note: On return, ref will have no parent nor sibling.
5376  *      The caller is responsible for releasing ref.
5377  *  - note: this is where root proxies are created.
5378  *  - note: the target of the root proxy is the content
5379  *      of a form.
5380  */
5381 SYNCTEX_INLINE static synctex_ns_s __synctex_replace_ref(synctex_node_p ref)
5382 {
5383     synctex_ns_s ns = {NULL, SYNCTEX_STATUS_OK};
5384     synctex_node_p parent;
5385     if ((parent = _synctex_tree_parent(ref))) {
5386         synctex_node_p sibling = __synctex_tree_reset_sibling(ref);
5387         synctex_node_p arg_sibling = synctex_node_arg_sibling(ref);
5388         /*  arg_sibling != NULL because the child of a box
5389          *  is always a box boundary, not a ref. */
5390         synctex_node_p target = synctex_form_content(ref->class->scanner, _synctex_data_tag(ref));
5391         /*  The target is a single node (box)
5392          *  with children and no siblings. */
5393         if ((ns.node = __synctex_new_proxy_from_ref_to(ref, target))) {
5394             /*  Insert this proxy instead of ref. */
5395             _synctex_node_set_sibling(arg_sibling, ns.node);
5396             /*  Then append the original sibling of ref. */
5397             _synctex_node_set_sibling(ns.node, sibling);
5398 #if defined(SYNCTEX_USE_CHARINDEX)
5399             if (synctex_node_type(sibling) == synctex_node_type_box_bdry) {
5400                 /*  The sibling is the last box boundary
5401                  *  which may have a less accurate information */
5402                 sibling->char_index = arg_sibling->char_index;
5403                 sibling->line_index = arg_sibling->line_index;
5404             }
5405 #endif
5406 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5407             printf("!  Ref replacement:\n");
5408             synctex_node_log(ref);
5409             synctex_node_display(synctex_node_sibling(ref));
5410 #endif
5411         } else /*  simply remove ref */ {
5412             _synctex_tree_set_sibling(arg_sibling, sibling);
5413         }
5414         __synctex_tree_reset_parent(ref);
5415     } else {
5416         _synctex_error(
5417             "!  Missing parent in __synctex_replace_ref. "
5418             "Please report.");
5419         ns.status = SYNCTEX_STATUS_BAD_ARGUMENT;
5420     }
5421     return ns;
5422 }
5423 /**
5424  *  - argument ref: is the starting point of a linked list
5425  *      of refs. The link is made through the friend field.
5426  *  - returns: the status and the list of all the proxies
5427  *      created. The link is made through the friend field.
5428  *  - note: All refs are freed
5429  */
5430 SYNCTEX_INLINE static synctex_ns_s _synctex_post_process_ref(synctex_node_p ref)
5431 {
5432     synctex_ns_s ns = {NULL, SYNCTEX_STATUS_OK};
5433     while (ref) {
5434         synctex_node_p next_ref = _synctex_tree_reset_friend(ref);
5435         synctex_ns_s sub_ns = __synctex_replace_ref(ref);
5436         if (sub_ns.status < ns.status) {
5437             ns.status = sub_ns.status;
5438         } else {
5439             /*  Insert all the created proxies in the list
5440              *  sub_ns.node is the last friend,
5441              */
5442             synctex_tree_set_friend(sub_ns.node, ns.node);
5443             ns.node = sub_ns.node;
5444         }
5445         synctex_node_free(ref);
5446         ref = next_ref;
5447     }
5448     return ns;
5449 }
5450 typedef synctex_node_p (*synctex_processor_f)(synctex_node_p node);
5451 /**
5452  *  Apply the processor f to the tree hierarchy rooted at proxy.
5453  *  proxy has replaced a form ref, no children yet.
5454  *  As a side effect all the hierarchy of nodes will be created.
5455  */
5456 SYNCTEX_INLINE static synctex_status_t _synctex_post_process_proxy(synctex_node_p proxy, synctex_processor_f f)
5457 {
5458     while (proxy) {
5459         synctex_node_p next_proxy = _synctex_tree_friend(proxy);
5460         synctex_node_p halt = __synctex_tree_sibling(proxy);
5461         /*  if proxy is the last sibling, halt is NULL.
5462          *  Find what should be a next node,
5463          *  without creating new nodes. */
5464         if (!halt) {
5465             synctex_node_p parent = _synctex_tree_parent(proxy);
5466             halt = __synctex_tree_sibling(parent);
5467             while (!halt && parent) {
5468                 parent = _synctex_tree_parent(parent);
5469                 halt = __synctex_tree_sibling(parent);
5470             }
5471         }
5472         do {
5473 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5474             printf("POST PROCESSING %s\n", _synctex_node_abstract(proxy));
5475             {
5476                 int i, j = 0;
5477                 for (i = 0; i < proxy->class->scanner->number_of_lists; ++i) {
5478                     synctex_node_p N = proxy->class->scanner->lists_of_friends[i];
5479                     do {
5480                         if (N == proxy) {
5481                             ++j;
5482                             printf("%s", _synctex_node_abstract(N));
5483                         }
5484                     } while ((N = _synctex_tree_friend(N)));
5485                 }
5486                 if (j) {
5487                     printf("\nBeforehand %i match\n", j);
5488                 }
5489             }
5490 #endif
5491             f(proxy);
5492 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5493             {
5494                 int i, j = 0;
5495                 for (i = 0; i < proxy->class->scanner->number_of_lists; ++i) {
5496                     synctex_node_p N = proxy->class->scanner->lists_of_friends[i];
5497                     do {
5498                         if (N == proxy) {
5499                             ++j;
5500                             printf("%s", _synctex_node_abstract(N));
5501                         }
5502                     } while ((N = _synctex_tree_friend(N)));
5503                 }
5504                 if (j) {
5505                     printf("\n%i match\n", j);
5506                 }
5507             }
5508 #endif
5509             /*  Side effect: create the hierarchy on the fly */
5510             proxy = synctex_node_next(proxy); /*  Change is here */
5511 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5512             if (proxy) {
5513                 int i, j = 0;
5514                 for (i = 0; i < proxy->class->scanner->number_of_lists; ++i) {
5515                     synctex_node_p N = proxy->class->scanner->lists_of_friends[i];
5516                     do {
5517                         if (N == proxy) {
5518                             ++j;
5519                             printf("%s", _synctex_node_abstract(N));
5520                         }
5521                     } while ((N = _synctex_tree_friend(N)));
5522                 }
5523                 if (j) {
5524                     printf("\nnext %i match\n", j);
5525                 }
5526             }
5527 #endif
5528         } while (proxy && proxy != halt);
5529         proxy = next_proxy;
5530     }
5531     return SYNCTEX_STATUS_OK;
5532 }
5533 /**
5534  *  Replace all the form refs by root box proxies.
5535  *  Create the node hierarchy and update the friends.
5536  *  On entry, the refs are collected as a friend list
5537  *  in either a form or a sheet
5538  *  - parameter: the owning scanner
5539  */
5540 SYNCTEX_INLINE static synctex_status_t _synctex_post_process(synctex_scanner_p scanner)
5541 {
5542     synctex_status_t status = SYNCTEX_STATUS_OK;
5543     synctex_ns_s ns = {NULL, SYNCTEX_STATUS_NOT_OK};
5544 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5545     printf("!  entering _synctex_post_process.\n");
5546     synctex_node_display(scanner->sheet);
5547     synctex_node_display(scanner->form);
5548 #endif
5549     /*  replace form refs inside forms by box proxies */
5550     ns = _synctex_post_process_ref(scanner->ref_in_form);
5551     scanner->ref_in_form = NULL; /*  it was just released */
5552     if (ns.status < status) {
5553         status = ns.status;
5554     }
5555 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5556     printf("!  ref replaced in form _synctex_post_process.\n");
5557     synctex_node_display(scanner->form);
5558 #endif
5559     /*  Create all the form proxy nodes on the fly.
5560      *  ns.node is the root of the list of
5561      *  newly created proxies.
5562      *  There might be a problem with cascading proxies.
5563      *  In order to be properly managed, the data must
5564      *  be organized in the right way.
5565      *  The inserted form must be defined before
5566      *  the inserting one. *TeX will take care of that.   */
5567     ns.status = _synctex_post_process_proxy(ns.node, &_synctex_tree_reset_friend);
5568     if (ns.status < status) {
5569         status = ns.status;
5570     }
5571     /*  replace form refs inside sheets by box proxies */
5572     ns = _synctex_post_process_ref(scanner->ref_in_sheet);
5573     if (ns.status < status) {
5574         status = ns.status;
5575     }
5576     scanner->ref_in_sheet = NULL;
5577 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5578     printf("!  ref replaced in sheet _synctex_post_process.\n");
5579     synctex_node_display(scanner->sheet);
5580 #endif
5581 
5582 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 10000
5583     {
5584         int i;
5585         for (i = 0; i < scanner->number_of_lists; ++i) {
5586             synctex_node_p P = scanner->lists_of_friends[i];
5587             int j = 0;
5588             while (P) {
5589                 ++j;
5590                 synctex_node_log(P);
5591                 P = _synctex_tree_friend(P);
5592             }
5593             if (j) {
5594                 printf("friends %i -> # %i\n", i, j);
5595             }
5596         }
5597     }
5598 #endif
5599     ns.status = _synctex_post_process_proxy(ns.node, &__synctex_proxy_make_friend_and_next_hbox);
5600     if (ns.status < status) {
5601         status = ns.status;
5602     }
5603 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5604     printf("!  exiting _synctex_post_process.\n");
5605     synctex_node_display(scanner->sheet);
5606     synctex_node_display(scanner->form);
5607     printf("!  display all.\n");
5608     synctex_node_display(scanner->sheet);
5609     synctex_node_display(scanner->form);
5610 #endif
5611     return status;
5612 }
5613 /*  Used when parsing the synctex file
5614  */
5615 static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner)
5616 {
5617     scanner->reader->lastv = -1;
5618     synctex_status_t status = 0;
5619     if (NULL == scanner) {
5620         return SYNCTEX_STATUS_BAD_ARGUMENT;
5621     }
5622     /*  Find where this section starts */
5623 content_not_found:
5624     status = _synctex_match_string(scanner, "Content:");
5625     if (status < SYNCTEX_STATUS_EOF) {
5626         return status;
5627     }
5628     if (_synctex_next_line(scanner) < SYNCTEX_STATUS_OK) {
5629         _synctex_error("Uncomplete Content.");
5630         return SYNCTEX_STATUS_ERROR;
5631     }
5632     if (status == SYNCTEX_STATUS_NOT_OK) {
5633         goto content_not_found;
5634     }
5635     status = __synctex_parse_sfi(scanner);
5636     if (status == SYNCTEX_STATUS_OK) {
5637         status = _synctex_post_process(scanner);
5638     }
5639     return status;
5640 }
5641 synctex_scanner_p synctex_scanner_new()
5642 {
5643     synctex_scanner_p scanner = (synctex_scanner_p)_synctex_malloc(sizeof(synctex_scanner_s));
5644     if (scanner) {
5645         if (!(scanner->reader = _synctex_malloc(sizeof(synctex_reader_s)))) {
5646             _synctex_free(scanner);
5647             return NULL;
5648         }
5649 #ifdef SYNCTEX_NOTHING
5650 #pragma mark -
5651 #endif
5652 #define DEFINE_synctex_scanner_class(NAME)                                                                                                                                                                                                     \
5653     scanner->class[synctex_node_type_##NAME] = synctex_class_##NAME;                                                                                                                                                                           \
5654     (scanner->class[synctex_node_type_##NAME]).scanner = scanner
5655         DEFINE_synctex_scanner_class(input);
5656         DEFINE_synctex_scanner_class(sheet);
5657         DEFINE_synctex_scanner_class(form);
5658         DEFINE_synctex_scanner_class(hbox);
5659         DEFINE_synctex_scanner_class(void_hbox);
5660         DEFINE_synctex_scanner_class(vbox);
5661         DEFINE_synctex_scanner_class(void_vbox);
5662         DEFINE_synctex_scanner_class(kern);
5663         DEFINE_synctex_scanner_class(glue);
5664         DEFINE_synctex_scanner_class(rule);
5665         DEFINE_synctex_scanner_class(math);
5666         DEFINE_synctex_scanner_class(boundary);
5667         DEFINE_synctex_scanner_class(box_bdry);
5668         DEFINE_synctex_scanner_class(ref);
5669         DEFINE_synctex_scanner_class(proxy_hbox);
5670         DEFINE_synctex_scanner_class(proxy_vbox);
5671         DEFINE_synctex_scanner_class(proxy);
5672         DEFINE_synctex_scanner_class(proxy_last);
5673         DEFINE_synctex_scanner_class(handle);
5674         /*  set up the lists of friends */
5675         scanner->number_of_lists = 1024;
5676         scanner->lists_of_friends = (synctex_node_r)_synctex_malloc(scanner->number_of_lists * sizeof(synctex_node_p));
5677         if (NULL == scanner->lists_of_friends) {
5678             synctex_scanner_free(scanner);
5679             _synctex_error("malloc:2");
5680             return NULL;
5681         }
5682         scanner->display_switcher = 100;
5683         scanner->display_prompt = (char *)_synctex_display_prompt + strlen(_synctex_display_prompt) - 1;
5684     }
5685     return scanner;
5686 }
5687 /*  Where the synctex scanner is created. */
5688 synctex_scanner_p synctex_scanner_new_with_output_file(const char *output, const char *build_directory, int parse)
5689 {
5690     synctex_scanner_p scanner = synctex_scanner_new();
5691     if (NULL == scanner) {
5692         _synctex_error("malloc problem");
5693         return NULL;
5694     }
5695     if ((scanner->reader = synctex_reader_init_with_output_file(scanner->reader, output, build_directory))) {
5696         return parse ? synctex_scanner_parse(scanner) : scanner;
5697     }
5698 #if defined(SYNCTEX_DEBUG)
5699     _synctex_error("No file?");
5700 #endif
5701     synctex_scanner_free(scanner);
5702     return NULL;
5703 }
5704 
5705 /*  The scanner destructor
5706  */
5707 int synctex_scanner_free(synctex_scanner_p scanner)
5708 {
5709     int node_count = 0;
5710     if (scanner) {
5711         if (scanner->reader && SYNCTEX_FILE) {
5712             gzclose(SYNCTEX_FILE);
5713             SYNCTEX_FILE = NULL;
5714         }
5715         synctex_node_free(scanner->sheet);
5716         synctex_node_free(scanner->form);
5717         synctex_node_free(scanner->input);
5718         synctex_reader_free(scanner->reader);
5719         SYNCTEX_SCANNER_FREE_HANDLE(scanner);
5720         synctex_iterator_free(scanner->iterator);
5721         free(scanner->output_fmt);
5722         free(scanner->lists_of_friends);
5723 #if defined SYNCTEX_USE_NODE_COUNT && SYNCTEX_USE_NODE_COUNT > 0
5724         node_count = scanner->node_count;
5725 #endif
5726         free(scanner);
5727     }
5728     return node_count;
5729 }
5730 
5731 /*  Where the synctex scanner parses the contents of the file. */
5732 synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner)
5733 {
5734     synctex_status_t status = 0;
5735     if (!scanner || scanner->flags.has_parsed) {
5736         return scanner;
5737     }
5738     scanner->flags.has_parsed = 1;
5739     scanner->pre_magnification = 1000;
5740     scanner->pre_unit = 8192;
5741     scanner->pre_x_offset = scanner->pre_y_offset = 578;
5742     /*  initialize the offset with a fake unprobable value,
5743      *  If there is a post scriptum section, this value will be overridden by the real life value */
5744     scanner->x_offset = scanner->y_offset = 6.027e23f;
5745     scanner->reader->line_number = 1;
5746 
5747     /* TODO: cleanup
5748      * In some (all?) cases SYNCTEX_START is already initialized
5749      * in synctex_reader_init_with_output_file(). Much of the
5750      * following code seems like a duplicate and is perhaps a
5751      * candidate for deletion. To be on the safe side though, we
5752      * keep it for now and just free() any prior malloc() if
5753      * existing. */
5754     _synctex_free(SYNCTEX_START);
5755 
5756     SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE + 1); /*  one more character for null termination */
5757     if (NULL == SYNCTEX_START) {
5758         _synctex_error("!  malloc error in synctex_scanner_parse.");
5759     bailey:
5760 #ifdef SYNCTEX_DEBUG
5761         return scanner;
5762 #else
5763         synctex_scanner_free(scanner);
5764         return NULL;
5765 #endif
5766     }
5767     synctex_scanner_set_display_switcher(scanner, 1000);
5768     SYNCTEX_END = SYNCTEX_START + SYNCTEX_BUFFER_SIZE;
5769     /*  SYNCTEX_END always points to a null terminating character.
5770      *  Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1.
5771      *  At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */
5772     *SYNCTEX_END = '\0';
5773     SYNCTEX_CUR = SYNCTEX_END;
5774 #if defined(SYNCTEX_USE_CHARINDEX)
5775     scanner->reader->charindex_offset = -SYNCTEX_BUFFER_SIZE;
5776 #endif
5777     status = _synctex_scan_preamble(scanner);
5778     if (status < SYNCTEX_STATUS_OK) {
5779         _synctex_error("Bad preamble\n");
5780         goto bailey;
5781     }
5782     status = _synctex_scan_content(scanner);
5783     if (status < SYNCTEX_STATUS_OK) {
5784         _synctex_error("Bad content\n");
5785         goto bailey;
5786     }
5787     status = _synctex_scan_postamble(scanner);
5788     if (status < SYNCTEX_STATUS_OK) {
5789         _synctex_error("Bad postamble. Ignored\n");
5790     }
5791 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
5792     synctex_scanner_set_display_switcher(scanner, 100);
5793     synctex_node_display(scanner->sheet);
5794     synctex_node_display(scanner->form);
5795 #endif
5796     synctex_scanner_set_display_switcher(scanner, 1000);
5797     /*  Everything is finished, free the buffer, close the file */
5798     free((void *)SYNCTEX_START);
5799     SYNCTEX_START = SYNCTEX_CUR = SYNCTEX_END = NULL;
5800     gzclose(SYNCTEX_FILE);
5801     SYNCTEX_FILE = NULL;
5802     /*  Final tuning: set the default values for various parameters */
5803     /*  1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp
5804      * 1 pt = 65536 sp */
5805     if (scanner->pre_unit <= 0) {
5806         scanner->pre_unit = 8192;
5807     }
5808     if (scanner->pre_magnification <= 0) {
5809         scanner->pre_magnification = 1000;
5810     }
5811     if (scanner->unit <= 0) {
5812         /*  no post magnification */
5813         scanner->unit = scanner->pre_unit / 65781.76; /*  65781.76 or 65536.0*/
5814     } else {
5815         /*  post magnification */
5816         scanner->unit *= scanner->pre_unit / 65781.76;
5817     }
5818     scanner->unit *= scanner->pre_magnification / 1000.0;
5819     if (scanner->x_offset > 6e23) {
5820         /*  no post offset */
5821         scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76);
5822         scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76);
5823     } else {
5824         /*  post offset */
5825         scanner->x_offset /= 65781.76f;
5826         scanner->y_offset /= 65781.76f;
5827     }
5828     return scanner;
5829 #undef SYNCTEX_FILE
5830 }
5831 
5832 /*  Scanner accessors.
5833  */
5834 int synctex_scanner_pre_x_offset(synctex_scanner_p scanner)
5835 {
5836     return scanner ? scanner->pre_x_offset : 0;
5837 }
5838 int synctex_scanner_pre_y_offset(synctex_scanner_p scanner)
5839 {
5840     return scanner ? scanner->pre_y_offset : 0;
5841 }
5842 int synctex_scanner_x_offset(synctex_scanner_p scanner)
5843 {
5844     return scanner ? scanner->x_offset : 0;
5845 }
5846 int synctex_scanner_y_offset(synctex_scanner_p scanner)
5847 {
5848     return scanner ? scanner->y_offset : 0;
5849 }
5850 float synctex_scanner_magnification(synctex_scanner_p scanner)
5851 {
5852     return scanner ? scanner->unit : 1;
5853 }
5854 void synctex_scanner_display(synctex_scanner_p scanner)
5855 {
5856     if (NULL == scanner) {
5857         return;
5858     }
5859     printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n", scanner->reader->output, scanner->output_fmt, scanner->version);
5860     printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n", scanner->pre_unit, scanner->pre_x_offset, scanner->pre_y_offset);
5861     printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n", scanner->count, scanner->unit, scanner->x_offset, scanner->y_offset);
5862     printf("The input:\n");
5863     synctex_node_display(scanner->input);
5864     if (scanner->count < 1000) {
5865         printf("The sheets:\n");
5866         synctex_node_display(scanner->sheet);
5867         printf("The friends:\n");
5868         if (scanner->lists_of_friends) {
5869             int i = scanner->number_of_lists;
5870             synctex_node_p node;
5871             while (i--) {
5872                 printf("Friend index:%i\n", i);
5873                 node = (scanner->lists_of_friends)[i];
5874                 while (node) {
5875                     printf("%s:%i,%i\n", synctex_node_isa(node), _synctex_data_tag(node), _synctex_data_line(node));
5876                     node = _synctex_tree_friend(node);
5877                 }
5878             }
5879         }
5880     } else {
5881         printf("SyncTeX Warning: Too many objects\n");
5882     }
5883 }
5884 /*  Public */
5885 const char *synctex_scanner_get_name(synctex_scanner_p scanner, int tag)
5886 {
5887     synctex_node_p input = NULL;
5888     if (NULL == scanner) {
5889         return NULL;
5890     }
5891     if ((input = scanner->input)) {
5892         ;
5893         do {
5894             if (tag == _synctex_data_tag(input)) {
5895                 return (_synctex_data_name(input));
5896             }
5897         } while ((input = __synctex_tree_sibling(input)));
5898     }
5899     return NULL;
5900 }
5901 const char *synctex_node_get_name(synctex_node_p node)
5902 {
5903     if (node) {
5904         return synctex_scanner_get_name(node->class->scanner, _synctex_data_tag(node));
5905     }
5906     return NULL;
5907 }
5908 
5909 static int _synctex_scanner_get_tag(synctex_scanner_p scanner, const char *name);
5910 static int _synctex_scanner_get_tag(synctex_scanner_p scanner, const char *name)
5911 {
5912     synctex_node_p input = NULL;
5913     if (NULL == scanner) {
5914         return 0;
5915     }
5916     if ((input = scanner->input)) {
5917         do {
5918             if (_synctex_is_equivalent_file_name(name, (_synctex_data_name(input)))) {
5919                 return _synctex_data_tag(input);
5920             }
5921         } while ((input = __synctex_tree_sibling(input)));
5922     }
5923     /* 2011 version */
5924     name = _synctex_base_name(name);
5925     if ((input = scanner->input)) {
5926         do {
5927             if (_synctex_is_equivalent_file_name(name, _synctex_base_name(_synctex_data_name(input)))) {
5928                 synctex_node_p other_input = input;
5929                 while ((other_input = __synctex_tree_sibling(other_input))) {
5930                     if (_synctex_is_equivalent_file_name(name, _synctex_base_name(_synctex_data_name(other_input))) &&
5931                         (strlen(_synctex_data_name(input)) != strlen(_synctex_data_name(other_input)) || strncmp(_synctex_data_name(other_input), _synctex_data_name(input), strlen(_synctex_data_name(input))))) {
5932                         /* There is a second possible candidate */
5933                         return 0;
5934                     }
5935                 }
5936                 return _synctex_data_tag(input);
5937             }
5938         } while ((input = __synctex_tree_sibling(input)));
5939     }
5940     return 0;
5941 }
5942 
5943 int synctex_scanner_get_tag(synctex_scanner_p scanner, const char *name)
5944 {
5945     size_t char_index = strlen(name);
5946     if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) {
5947         /*  the name is not void */
5948         char_index -= 1;
5949         if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) {
5950             /*  the last character of name is not a path separator */
5951             int result = _synctex_scanner_get_tag(scanner, name);
5952             if (result) {
5953                 return result;
5954             } else {
5955                 /*  the given name was not the one known by TeX
5956                  *  try a name relative to the enclosing directory of the scanner->output file */
5957                 const char *relative = name;
5958                 const char *ptr = scanner->reader->output;
5959                 while ((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr)) {
5960                     relative += 1;
5961                     ptr += 1;
5962                 }
5963                 /*  Find the last path separator before relative */
5964                 while (relative > name) {
5965                     if (SYNCTEX_IS_PATH_SEPARATOR(*(relative - 1))) {
5966                         break;
5967                     }
5968                     relative -= 1;
5969                 }
5970                 if ((relative > name) && (result = _synctex_scanner_get_tag(scanner, relative))) {
5971                     return result;
5972                 }
5973                 if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) {
5974                     /*  No tag found for the given absolute name,
5975                      *  Try each relative path starting from the shortest one */
5976                     while (0 < char_index) {
5977                         char_index -= 1;
5978                         if (SYNCTEX_IS_PATH_SEPARATOR(name[char_index]) && (result = _synctex_scanner_get_tag(scanner, name + char_index + 1))) {
5979                             return result;
5980                         }
5981                     }
5982                 }
5983             }
5984             return result;
5985         }
5986     }
5987     return 0;
5988 }
5989 synctex_node_p synctex_scanner_input(synctex_scanner_p scanner)
5990 {
5991     return scanner ? scanner->input : NULL;
5992 }
5993 synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner, int tag)
5994 {
5995     synctex_node_p input = scanner ? scanner->input : NULL;
5996     while (_synctex_data_tag(input) != tag) {
5997         if ((input = __synctex_tree_sibling(input))) {
5998             continue;
5999         }
6000         break;
6001     }
6002     return input;
6003 }
6004 const char *synctex_scanner_get_output_fmt(synctex_scanner_p scanner)
6005 {
6006     return NULL != scanner && scanner->output_fmt ? scanner->output_fmt : "";
6007 }
6008 const char *synctex_scanner_get_output(synctex_scanner_p scanner)
6009 {
6010     return NULL != scanner && scanner->reader->output ? scanner->reader->output : "";
6011 }
6012 const char *synctex_scanner_get_synctex(synctex_scanner_p scanner)
6013 {
6014     return NULL != scanner && scanner->reader->synctex ? scanner->reader->synctex : "";
6015 }
6016 #ifdef SYNCTEX_NOTHING
6017 #pragma mark -
6018 #pragma mark Public node attributes
6019 #endif
6020 
6021 #define SYNCTEX_DEFINE_NODE_HVWHD(WHAT)                                                                                                                                                                                                        \
6022     int synctex_node_##WHAT(synctex_node_p node)                                                                                                                                                                                               \
6023     {                                                                                                                                                                                                                                          \
6024         return (node && node->class->inspector->WHAT) ? node->class->inspector->WHAT(node) : 0;                                                                                                                                                \
6025     }
6026 #define SYNCTEX_DEFINE_PROXY_HV(WHAT)                                                                                                                                                                                                          \
6027     static int _synctex_proxy_##WHAT(synctex_proxy_p proxy)                                                                                                                                                                                    \
6028     {                                                                                                                                                                                                                                          \
6029         synctex_node_p target = _synctex_tree_target(proxy);                                                                                                                                                                                   \
6030         if (target) {                                                                                                                                                                                                                          \
6031             return _synctex_data_##WHAT(proxy) + synctex_node_##WHAT(target);                                                                                                                                                                  \
6032         } else {                                                                                                                                                                                                                               \
6033             return proxy ? _synctex_data_##WHAT(proxy) : 0;                                                                                                                                                                                    \
6034         }                                                                                                                                                                                                                                      \
6035     }
6036 #define SYNCTEX_DEFINE_PROXY_TLCWVD(WHAT)                                                                                                                                                                                                      \
6037     static int _synctex_proxy_##WHAT(synctex_proxy_p proxy)                                                                                                                                                                                    \
6038     {                                                                                                                                                                                                                                          \
6039         synctex_node_p target = _synctex_tree_target(proxy);                                                                                                                                                                                   \
6040         return target ? synctex_node_##WHAT(target) : 0;                                                                                                                                                                                       \
6041     }
6042 
6043 /**
6044  *  The horizontal location of the node.
6045  *  Idem for v, width, height and depth.
6046  *  - parameter node: a node with geometrical information.
6047  *  - returns: an integer.
6048  *  - requires: every proxy node has a target.
6049  *  - note: recursive call if the parameter has a proxy.
6050  *  - author: JL
6051  */
6052 SYNCTEX_DEFINE_NODE_HVWHD(h)
6053 SYNCTEX_DEFINE_NODE_HVWHD(v)
6054 SYNCTEX_DEFINE_NODE_HVWHD(width)
6055 SYNCTEX_DEFINE_NODE_HVWHD(height)
6056 SYNCTEX_DEFINE_NODE_HVWHD(depth)
6057 SYNCTEX_DEFINE_PROXY_TLCWVD(tag)
6058 SYNCTEX_DEFINE_PROXY_TLCWVD(line)
6059 SYNCTEX_DEFINE_PROXY_TLCWVD(column)
6060 SYNCTEX_DEFINE_PROXY_HV(h)
6061 SYNCTEX_DEFINE_PROXY_HV(v)
6062 SYNCTEX_DEFINE_PROXY_TLCWVD(width)
6063 SYNCTEX_DEFINE_PROXY_TLCWVD(height)
6064 SYNCTEX_DEFINE_PROXY_TLCWVD(depth)
6065 
6066 /**
6067  *  Whether the argument is a box,
6068  *  either vertical or horizontal,
6069  *  either void or not,
6070  *  or a proxy to such a box.
6071  *  - parameter NODE: of type synctex_node_p
6072  *  - returns: yorn
6073  */
6074 
6075 SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_box(synctex_node_p node)
6076 {
6077     return node &&
6078         (node->class->type == synctex_node_type_hbox || node->class->type == synctex_node_type_void_hbox || node->class->type == synctex_node_type_vbox || node->class->type == synctex_node_type_void_vbox ||
6079          _synctex_node_is_box(_synctex_tree_target(node)));
6080 }
6081 
6082 /**
6083  *  Whether the argument is a handle.
6084  *  Handles are similar to proxies because they have a target.
6085  *  They are used for query results.
6086  *  - parameter NODE: of type synctex_node_p
6087  *  - returns: yorn
6088  */
6089 
6090 SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_handle(synctex_node_p node)
6091 {
6092     return node && (node->class->type == synctex_node_type_handle);
6093 }
6094 
6095 /**
6096  *  Resolves handle indirection.
6097  *  - parameter node: of type synctex_node_p
6098  *  - returns: node if it is not a handle,
6099  *  its target otherwise.
6100  */
6101 
6102 SYNCTEX_INLINE static synctex_node_p _synctex_node_or_handle_target(synctex_node_p node)
6103 {
6104     return _synctex_node_is_handle(node) ? _synctex_tree_target(node) : node;
6105 }
6106 
6107 /**
6108  *  Whether the argument is an hbox.
6109  *  - parameter NODE: of type synctex_node_p
6110  *  - returns: yorn
6111  */
6112 
6113 SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_hbox(synctex_node_p node)
6114 {
6115     return node && (node->class->type == synctex_node_type_hbox || node->class->type == synctex_node_type_void_hbox || _synctex_node_is_hbox(_synctex_tree_target(node)));
6116 }
6117 
6118 /**
6119  *  The horizontal location of the first box enclosing node.
6120  *  - parameter node: a node with geometrical information.
6121  *  - returns: an integer.
6122  *  - author: JL
6123  */
6124 int synctex_node_box_h(synctex_node_p node)
6125 {
6126     if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6127         return synctex_node_h(node);
6128     }
6129     return 0;
6130 }
6131 /**
6132  *  The vertical location of the first box enclosing node.
6133  *  - parameter node: a node with geometrical information.
6134  *  - returns: an integer.
6135  *  - author: JL
6136  */
6137 int synctex_node_box_v(synctex_node_p node)
6138 {
6139     if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6140         return synctex_node_v(node);
6141     }
6142     return 0;
6143 }
6144 /**
6145  *  The width of the first box enclosing node.
6146  *  - parameter node: a node with geometrical information.
6147  *  - returns: an integer.
6148  *  - author: JL
6149  */
6150 int synctex_node_box_width(synctex_node_p node)
6151 {
6152     if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6153         return synctex_node_width(node);
6154     }
6155     return 0;
6156 }
6157 /**
6158  *  The height of the first box enclosing node.
6159  *  - parameter node: a node with geometrical information.
6160  *  - returns: an integer.
6161  *  - author: JL
6162  */
6163 int synctex_node_box_height(synctex_node_p node)
6164 {
6165     if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6166         return synctex_node_height(node);
6167     }
6168     return 0;
6169 }
6170 /**
6171  *  The depth of the first box enclosing node.
6172  *  - parameter node: a node with geometrical information.
6173  *  - returns: an integer.
6174  *  - author: JL
6175  */
6176 int synctex_node_box_depth(synctex_node_p node)
6177 {
6178     if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6179         return synctex_node_depth(node);
6180     }
6181     return 0;
6182 }
6183 /**
6184  *  The horizontal location of an hbox, corrected with contents.
6185  *  - parameter node: an hbox node.
6186  *  - returns: an integer, 0 if node is not an hbox or an hbox proxy.
6187  *  - note: recursive call when node is an hbox proxy.
6188  *  - author: JL
6189  */
6190 int synctex_node_hbox_h(synctex_node_p node)
6191 {
6192     switch (synctex_node_type(node)) {
6193     case synctex_node_type_hbox:
6194         return _synctex_data_h_V(node);
6195     case synctex_node_type_proxy_hbox:
6196         return _synctex_data_h(node) + synctex_node_hbox_h(_synctex_tree_target(node));
6197     default:
6198         return 0;
6199     }
6200 }
6201 /**
6202  *  The vertical location of an hbox, corrected with contents.
6203  *  - parameter node: an hbox node.
6204  *  - returns: an integer, 0 if node is not an hbox or an hbox proxy.
6205  *  - note: recursive call when node is an hbox proxy.
6206  *  - author: JL
6207  */
6208 int synctex_node_hbox_v(synctex_node_p node)
6209 {
6210     switch (synctex_node_type(node)) {
6211     case synctex_node_type_hbox:
6212         return _synctex_data_v_V(node);
6213     case synctex_node_type_proxy_hbox:
6214         return _synctex_data_v(node) + synctex_node_hbox_v(_synctex_tree_target(node));
6215     default:
6216         return 0;
6217     }
6218 }
6219 /**
6220  *  The width of an hbox, corrected with contents.
6221  *  - parameter node: an hbox node, 0 if node is not an hbox or an hbox proxy.
6222  *  - returns: an integer.
6223  *  - author: JL
6224  */
6225 int synctex_node_hbox_width(synctex_node_p node)
6226 {
6227     synctex_node_p target = _synctex_tree_target(node);
6228     if (target) {
6229         node = target;
6230     }
6231     return synctex_node_type(node) == synctex_node_type_hbox ? _synctex_data_width_V(node) : 0;
6232 }
6233 /**
6234  *  The height of an hbox, corrected with contents.
6235  *  - parameter node: an hbox node.
6236  *  - returns: an integer, 0 if node is not an hbox or an hbox proxy.
6237  *  - author: JL
6238  */
6239 int synctex_node_hbox_height(synctex_node_p node)
6240 {
6241     synctex_node_p target = _synctex_tree_target(node);
6242     if (target) {
6243         node = target;
6244     }
6245     return synctex_node_type(node) == synctex_node_type_hbox ? _synctex_data_height_V(node) : 0;
6246 }
6247 /**
6248  *  The depth of an hbox, corrected with contents.
6249  *  - parameter node: an hbox node.
6250  *  - returns: an integer, 0 if node is not an hbox or an hbox proxy.
6251  *  - note: recursive call when node is an hbox proxy.
6252  *  - author: JL
6253  */
6254 int synctex_node_hbox_depth(synctex_node_p node)
6255 {
6256     synctex_node_p target = _synctex_tree_target(node);
6257     if (target) {
6258         node = target;
6259     }
6260     return synctex_node_type(node) == synctex_node_type_hbox ? _synctex_data_depth_V(node) : 0;
6261 }
6262 #ifdef SYNCTEX_NOTHING
6263 #pragma mark -
6264 #pragma mark Public node visible attributes
6265 #endif
6266 
6267 #define SYNCTEX_VISIBLE_SIZE(node, s) (s) * node->class->scanner->unit
6268 #define SYNCTEX_VISIBLE_DISTANCE_h(node, d) ((d)*node->class->scanner->unit + node->class->scanner->x_offset)
6269 #define SYNCTEX_VISIBLE_DISTANCE_v(node, d) ((d)*node->class->scanner->unit + node->class->scanner->y_offset)
6270 static float __synctex_node_visible_h(synctex_node_p node)
6271 {
6272     return SYNCTEX_VISIBLE_DISTANCE_h(node, synctex_node_h(node));
6273 }
6274 static float __synctex_node_visible_v(synctex_node_p node)
6275 {
6276     return SYNCTEX_VISIBLE_DISTANCE_v(node, synctex_node_v(node));
6277 }
6278 static float __synctex_node_visible_width(synctex_node_p node)
6279 {
6280     return SYNCTEX_VISIBLE_SIZE(node, synctex_node_width(node));
6281 }
6282 static float __synctex_node_visible_height(synctex_node_p node)
6283 {
6284     return SYNCTEX_VISIBLE_SIZE(node, synctex_node_height(node));
6285 }
6286 static float __synctex_node_visible_depth(synctex_node_p node)
6287 {
6288     return SYNCTEX_VISIBLE_SIZE(node, synctex_node_depth(node));
6289 }
6290 static float __synctex_proxy_visible_h(synctex_node_p node)
6291 {
6292     return SYNCTEX_VISIBLE_DISTANCE_h(node, synctex_node_h(node));
6293 }
6294 static float __synctex_proxy_visible_v(synctex_node_p node)
6295 {
6296     return SYNCTEX_VISIBLE_DISTANCE_v(node, synctex_node_v(node));
6297 }
6298 static float __synctex_proxy_visible_width(synctex_node_p node)
6299 {
6300     synctex_node_p target = _synctex_tree_target(node);
6301     return __synctex_node_visible_width(target);
6302 }
6303 static float __synctex_proxy_visible_height(synctex_node_p node)
6304 {
6305     synctex_node_p target = _synctex_tree_target(node);
6306     return __synctex_node_visible_height(target);
6307 }
6308 static float __synctex_proxy_visible_depth(synctex_node_p node)
6309 {
6310     synctex_node_p target = _synctex_tree_target(node);
6311     return __synctex_node_visible_depth(target);
6312 }
6313 static float __synctex_kern_visible_h(synctex_noxy_p noxy)
6314 {
6315     int h = _synctex_data_h(noxy);
6316     int width = _synctex_data_width(noxy);
6317     return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width > 0 ? h - width : h);
6318 }
6319 static float __synctex_kern_visible_width(synctex_noxy_p noxy)
6320 {
6321     int width = _synctex_data_width(noxy);
6322     return SYNCTEX_VISIBLE_SIZE(noxy, width > 0 ? width : -width);
6323 }
6324 static float __synctex_rule_visible_h(synctex_noxy_p noxy)
6325 {
6326     int h = _synctex_data_h(noxy);
6327     int width = _synctex_data_width(noxy);
6328     return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width > 0 ? h : h - width);
6329 }
6330 static float __synctex_rule_visible_width(synctex_noxy_p noxy)
6331 {
6332     int width = _synctex_data_width(noxy);
6333     return SYNCTEX_VISIBLE_SIZE(noxy, width > 0 ? width : -width);
6334 }
6335 static float __synctex_rule_visible_v(synctex_noxy_p noxy)
6336 {
6337     return __synctex_node_visible_v(noxy);
6338 }
6339 static float __synctex_rule_visible_height(synctex_noxy_p noxy)
6340 {
6341     return __synctex_node_visible_height(noxy);
6342 }
6343 static float __synctex_rule_visible_depth(synctex_noxy_p noxy)
6344 {
6345     return __synctex_node_visible_depth(noxy);
6346 }
6347 
6348 /**
6349  *  The horizontal location of node, in page coordinates.
6350  *  - parameter node: a node.
6351  *  - returns: a float.
6352  *  - author: JL
6353  */
6354 float synctex_node_visible_h(synctex_node_p node)
6355 {
6356     return node ? node->class->vispector->h(node) : 0;
6357 }
6358 /**
6359  *  The vertical location of node, in page coordinates.
6360  *  - parameter node: a node.
6361  *  - returns: a float.
6362  *  - author: JL
6363  */
6364 float synctex_node_visible_v(synctex_node_p node)
6365 {
6366     return node ? node->class->vispector->v(node) : 0;
6367 }
6368 /**
6369  *  The width of node, in page coordinates.
6370  *  - parameter node: a node.
6371  *  - returns: a float.
6372  *  - author: JL
6373  */
6374 float synctex_node_visible_width(synctex_node_p node)
6375 {
6376     return node ? node->class->vispector->width(node) : 0;
6377 }
6378 /**
6379  *  The height of node, in page coordinates.
6380  *  - parameter node: a node.
6381  *  - returns: a float.
6382  *  - author: JL
6383  */
6384 float synctex_node_visible_height(synctex_node_p node)
6385 {
6386     return node ? node->class->vispector->height(node) : 0;
6387 }
6388 /**
6389  *  The depth of node, in page coordinates.
6390  *  - parameter node: a node.
6391  *  - returns: a float.
6392  *  - author: JL
6393  */
6394 float synctex_node_visible_depth(synctex_node_p node)
6395 {
6396     return node ? node->class->vispector->depth(node) : 0;
6397 }
6398 
6399 /**
6400  *  The V variant of geometrical information.
6401  *  - parameter node: a node.
6402  *  - returns: an integer.
6403  *  - author: JL
6404  */
6405 #define SYNCTEX_DEFINE_V(WHAT)                                                                                                                                                                                                                 \
6406     SYNCTEX_INLINE static int _synctex_node_##WHAT##_V(synctex_node_p node)                                                                                                                                                                    \
6407     {                                                                                                                                                                                                                                          \
6408         synctex_node_p target = _synctex_tree_target(node);                                                                                                                                                                                    \
6409         if (target) {                                                                                                                                                                                                                          \
6410             return _synctex_data_##WHAT(node) + _synctex_node_##WHAT##_V(target);                                                                                                                                                              \
6411         } else if (_synctex_data_has_##WHAT##_V(node)) {                                                                                                                                                                                       \
6412             return _synctex_data_##WHAT##_V(node);                                                                                                                                                                                             \
6413         } else {                                                                                                                                                                                                                               \
6414             return _synctex_data_##WHAT(node);                                                                                                                                                                                                 \
6415         }                                                                                                                                                                                                                                      \
6416     }
6417 SYNCTEX_DEFINE_V(h)
6418 SYNCTEX_DEFINE_V(v)
6419 SYNCTEX_DEFINE_V(width)
6420 SYNCTEX_DEFINE_V(height)
6421 SYNCTEX_DEFINE_V(depth)
6422 
6423 SYNCTEX_INLINE static synctex_point_s _synctex_data_point(synctex_node_p node)
6424 {
6425     return (synctex_point_s) {synctex_node_h(node), synctex_node_v(node)};
6426 }
6427 SYNCTEX_INLINE static synctex_point_s _synctex_data_point_V(synctex_node_p node)
6428 {
6429     return (synctex_point_s) {_synctex_node_h_V(node), _synctex_node_v_V(node)};
6430 }
6431 SYNCTEX_INLINE static synctex_point_s _synctex_data_set_point(synctex_node_p node, synctex_point_s point)
6432 {
6433     synctex_point_s old = _synctex_data_point(node);
6434     _synctex_data_set_h(node, point.h);
6435     _synctex_data_set_v(node, point.v);
6436     return old;
6437 }
6438 SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node)
6439 {
6440     synctex_box_s box = {{0, 0}, {0, 0}};
6441     int n;
6442     n = synctex_node_width(node);
6443     if (n < 0) {
6444         box.max.h = synctex_node_h(node);
6445         box.min.h = box.max.h + n;
6446     } else {
6447         box.min.h = synctex_node_h(node);
6448         box.max.h = box.min.h + n;
6449     }
6450     n = synctex_node_v(node);
6451     box.min.v = n - synctex_node_height(node);
6452     box.max.v = n + synctex_node_depth(node);
6453     return box;
6454 }
6455 SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node)
6456 {
6457     synctex_box_s box = {{0, 0}, {0, 0}};
6458     int n;
6459     n = synctex_node_width(node);
6460     if (n > 0) {
6461         box.max.h = synctex_node_h(node);
6462         box.min.h = box.max.h - n;
6463     } else {
6464         box.min.h = synctex_node_h(node);
6465         box.max.h = box.min.h - n;
6466     }
6467     n = synctex_node_v(node);
6468     box.min.v = n - synctex_node_height(node);
6469     box.max.v = n + synctex_node_depth(node);
6470     return box;
6471 }
6472 SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node)
6473 {
6474     synctex_box_s box = {{0, 0}, {0, 0}};
6475     int n;
6476     n = _synctex_node_width_V(node);
6477     if (n < 0) {
6478         box.max.h = _synctex_node_h_V(node);
6479         box.min.h = box.max.h + n;
6480     } else {
6481         box.min.h = _synctex_node_h_V(node);
6482         box.max.h = box.min.h + n;
6483     }
6484     n = _synctex_node_v_V(node);
6485     box.min.v = n - _synctex_node_height_V(node);
6486     box.max.v = n + _synctex_node_depth_V(node);
6487     return box;
6488 }
6489 
6490 /**
6491  *  The higher box node in the parent hierarchy which
6492  *  mean line number is the one of node ±1.
6493  *  This enclosing box is computed as follows
6494  *  1) get the first hbox in the parent linked list
6495  *  starting at node.
6496  *  If there is none, simply return the parent of node.
6497  *  2) compute the mean line number
6498  *  3) scans up the tree for the higher hbox with
6499  *  the same mean line number, ±1 eventually
6500  *  - parameter node: a node.
6501  *  - returns: a (proxy to a) box node.
6502  *  - author: JL
6503  */
6504 static synctex_node_p _synctex_node_box_visible(synctex_node_p node)
6505 {
6506     if ((node = _synctex_node_or_handle_target(node))) {
6507         int mean = 0;
6508         int bound = 1500000 / (node->class->scanner->pre_magnification / 1000);
6509         synctex_node_p parent = NULL;
6510         /*  get the first enclosing parent
6511          *  then get the highest enclosing parent with the same mean line ±1 */
6512         node = _synctex_node_or_handle_target(node);
6513         if (!_synctex_node_is_box(node)) {
6514             if ((parent = _synctex_tree_parent(node))) {
6515                 node = parent;
6516             } else if ((node = _synctex_tree_target(node))) {
6517                 if (!_synctex_node_is_box(node)) {
6518                     if ((parent = _synctex_tree_parent(node))) {
6519                         node = parent;
6520                     } else {
6521                         return NULL;
6522                     }
6523                 }
6524             }
6525         }
6526         parent = node;
6527         mean = synctex_node_mean_line(node);
6528         while ((parent = _synctex_tree_parent(parent))) {
6529             if (_synctex_node_is_hbox(parent)) {
6530                 if (_synctex_abs(mean - synctex_node_mean_line(parent)) > 1) {
6531                     return node;
6532                 } else if (synctex_node_width(parent) > bound) {
6533                     return parent;
6534                 } else if (synctex_node_height(parent) + synctex_node_depth(parent) > bound) {
6535                     return parent;
6536                 }
6537                 node = parent;
6538             }
6539         }
6540     }
6541     return node;
6542 }
6543 /**
6544  *  The horizontal location of the first box enclosing node, in page coordinates.
6545  *  - parameter node: a node.
6546  *  - returns: a float.
6547  *  - author: JL
6548  */
6549 float synctex_node_box_visible_h(synctex_node_p node)
6550 {
6551     return SYNCTEX_VISIBLE_DISTANCE_h(node, _synctex_node_h_V(_synctex_node_box_visible(node)));
6552 }
6553 /**
6554  *  The vertical location of the first box enclosing node, in page coordinates.
6555  *  - parameter node: a node.
6556  *  - returns: a float.
6557  *  - author: JL
6558  */
6559 float synctex_node_box_visible_v(synctex_node_p node)
6560 {
6561     return SYNCTEX_VISIBLE_DISTANCE_v(node, _synctex_node_v_V(_synctex_node_box_visible(node)));
6562 }
6563 /**
6564  *  The width of the first box enclosing node, in page coordinates.
6565  *  - parameter node: a node.
6566  *  - returns: a float.
6567  *  - author: JL
6568  */
6569 float synctex_node_box_visible_width(synctex_node_p node)
6570 {
6571     return SYNCTEX_VISIBLE_SIZE(node, _synctex_node_width_V(_synctex_node_box_visible(node)));
6572 }
6573 /**
6574  *  The height of the first box enclosing node, in page coordinates.
6575  *  - parameter node: a node.
6576  *  - returns: a float.
6577  *  - author: JL
6578  */
6579 float synctex_node_box_visible_height(synctex_node_p node)
6580 {
6581     return SYNCTEX_VISIBLE_SIZE(node, _synctex_node_height_V(_synctex_node_box_visible(node)));
6582 }
6583 /**
6584  *  The depth of the first box enclosing node, in page coordinates.
6585  *  - parameter node: a node.
6586  *  - returns: a float.
6587  *  - author: JL
6588  */
6589 float synctex_node_box_visible_depth(synctex_node_p node)
6590 {
6591     return SYNCTEX_VISIBLE_SIZE(node, _synctex_node_depth_V(_synctex_node_box_visible(node)));
6592 }
6593 #ifdef SYNCTEX_NOTHING
6594 #pragma mark -
6595 #pragma mark Other public node attributes
6596 #endif
6597 
6598 /**
6599  *  The page number of the sheet enclosing node.
6600  *  - parameter node: a node.
6601  *  - returns: the page number or -1 if node does not belong to a sheet tree.
6602  *  - note: a proxy target does not belong to a sheet
6603  *      but a form, its page number is always -1.
6604  *  - note: a handles does not belong to a sheet not a form.
6605  *      its page number is -1.
6606  *  - author: JL
6607  */
6608 int synctex_node_page(synctex_node_p node)
6609 {
6610     synctex_node_p parent = NULL;
6611     while ((parent = _synctex_tree_parent(node))) {
6612         node = parent;
6613     }
6614     if (synctex_node_type(node) == synctex_node_type_sheet) {
6615         return _synctex_data_page(node);
6616     }
6617     return -1;
6618 }
6619 /**
6620  *  The page number of the target.
6621  *  - author: JL
6622  */
6623 SYNCTEX_INLINE static int _synctex_node_target_page(synctex_node_p node)
6624 {
6625     return synctex_node_page(_synctex_tree_target(node));
6626 }
6627 
6628 #if defined(SYNCTEX_USE_CHARINDEX)
6629 synctex_charindex_t synctex_node_charindex(synctex_node_p node)
6630 {
6631     synctex_node_p target = _synctex_tree_target(node);
6632     return target ? SYNCTEX_CHARINDEX(target) : (node ? SYNCTEX_CHARINDEX(node) : 0);
6633 }
6634 #endif
6635 
6636 /**
6637  *  The tag of the node.
6638  *  - parameter node: a node.
6639  *  - returns: the tag or -1 if node is NULL.
6640  *  - author: JL
6641  */
6642 int synctex_node_tag(synctex_node_p node)
6643 {
6644     return node ? node->class->tlcpector->tag(node) : -1;
6645 }
6646 /**
6647  *  The line of the node.
6648  *  - parameter node: a node.
6649  *  - returns: the line or -1 if node is NULL.
6650  *  - author: JL
6651  */
6652 int synctex_node_line(synctex_node_p node)
6653 {
6654     return node ? node->class->tlcpector->line(node) : -1;
6655 }
6656 /**
6657  *  The column of the node.
6658  *  - parameter node: a node.
6659  *  - returns: the column or -1 if node is NULL.
6660  *  - author: JL
6661  */
6662 int synctex_node_column(synctex_node_p node)
6663 {
6664     return node ? node->class->tlcpector->column(node) : -1;
6665 }
6666 /**
6667  *  The mean line number of the node.
6668  *  - parameter node: a node.
6669  *  - returns: the mean line or -1 if node is NULL.
6670  *  - author: JL
6671  */
6672 int synctex_node_mean_line(synctex_node_p node)
6673 {
6674     synctex_node_p target = _synctex_tree_target(node);
6675     if (target) {
6676         node = target;
6677     }
6678     return _synctex_data_has_mean_line(node) ? _synctex_data_mean_line(node) : _synctex_data_line(node);
6679 }
6680 /**
6681  *  The weight of the node.
6682  *  - parameter node: a node.
6683  *  - returns: the weight or -1 if node is NULL.
6684  *  - author: JL
6685  */
6686 int synctex_node_weight(synctex_node_p node)
6687 {
6688     synctex_node_p target = _synctex_tree_target(node);
6689     if (target) {
6690         node = target;
6691     }
6692     return node ? (synctex_node_type(node) == synctex_node_type_hbox ? _synctex_data_weight(node) : 0) : -1;
6693 }
6694 /**
6695  *  The number of children of the node.
6696  *  - parameter node: a node.
6697  *  - returns: the count or -1 if node is NULL.
6698  *  - author: JL
6699  */
6700 int synctex_node_child_count(synctex_node_p node)
6701 {
6702     synctex_node_p target = _synctex_tree_target(node);
6703     if (target) {
6704         node = target;
6705     }
6706     return node ? (synctex_node_type(node) == synctex_node_type_hbox ? _synctex_data_weight(node) : 0) : -1;
6707 }
6708 #ifdef SYNCTEX_NOTHING
6709 #pragma mark -
6710 #pragma mark Sheet & Form
6711 #endif
6712 
6713 /**
6714  *  The sheet of the scanner with a given page number.
6715  *  - parameter scanner: a scanner.
6716  *  - parameter page: a 1 based page number.
6717  *      If page == 0, returns the first sheet.
6718  *  - returns: a sheet or NULL.
6719  *  - author: JL
6720  */
6721 synctex_node_p synctex_sheet(synctex_scanner_p scanner, int page)
6722 {
6723     if (scanner) {
6724         synctex_node_p sheet = scanner->sheet;
6725         while (sheet) {
6726             if (page == _synctex_data_page(sheet)) {
6727                 return sheet;
6728             }
6729             sheet = __synctex_tree_sibling(sheet);
6730         }
6731         if (page == 0) {
6732             return scanner->sheet;
6733         }
6734     }
6735     return NULL;
6736 }
6737 /**
6738  *  The form of the scanner with a given tag.
6739  *  - parameter scanner: a scanner.
6740  *  - parameter tag: an integer identifier.
6741  *      If tag == 0, returns the first form.
6742  *  - returns: a form.
6743  *  - author: JL
6744  */
6745 synctex_node_p synctex_form(synctex_scanner_p scanner, int tag)
6746 {
6747     if (scanner) {
6748         synctex_node_p form = scanner->form;
6749         while (form) {
6750             if (tag == _synctex_data_tag(form)) {
6751                 return form;
6752             }
6753             form = __synctex_tree_sibling(form);
6754         }
6755         if (tag == 0) {
6756             return scanner->form;
6757         }
6758     }
6759     return NULL;
6760 }
6761 
6762 /**
6763  *  The content of the sheet with given page number.
6764  *  - parameter scanner: a scanner.
6765  *  - parameter page: a 1 based page number.
6766  *  - returns: a (vertical) box node.
6767  *  - author: JL
6768  */
6769 synctex_node_p synctex_sheet_content(synctex_scanner_p scanner, int page)
6770 {
6771     if (scanner) {
6772         return _synctex_tree_child(synctex_sheet(scanner, page));
6773     }
6774     return NULL;
6775 }
6776 
6777 /**
6778  *  The content of the sheet with given page number.
6779  *  - parameter scanner: a scanner.
6780  *  - parameter tag: an integer identifier.
6781  *  - returns: a box node.
6782  *  - author: JL
6783  */
6784 synctex_node_p synctex_form_content(synctex_scanner_p scanner, int tag)
6785 {
6786     if (scanner) {
6787         return _synctex_tree_child(synctex_form(scanner, tag));
6788     }
6789     return NULL;
6790 }
6791 
6792 SYNCTEX_INLINE static synctex_node_p _synctex_scanner_friend(synctex_scanner_p scanner, int i)
6793 {
6794     if (i >= 0) {
6795         i = _synctex_abs(i) % (scanner->number_of_lists);
6796         return (scanner->lists_of_friends)[i];
6797     }
6798     return NULL;
6799 }
6800 SYNCTEX_INLINE static synctex_bool_t _synctex_nodes_are_friend(synctex_node_p left, synctex_node_p right)
6801 {
6802     return synctex_node_tag(left) == synctex_node_tag(right) && synctex_node_line(left) == synctex_node_line(right);
6803 }
6804 SYNCTEX_INLINE static synctex_node_p _synctex_vertically_sorted_v2(synctex_node_p sibling)
6805 {
6806     synctex_node_p child = NULL;
6807     synctex_node_p best_child = sibling;
6808     synctex_node_p next_child = _synctex_tree_reset_child(best_child);
6809     synctex_node_p target = _synctex_tree_target(best_child);
6810     synctex_node_p parent = _synctex_tree_parent(target);
6811     unsigned int best_count = 0;
6812     unsigned int count = 0;
6813     synctex_node_p N = _synctex_tree_child(parent);
6814     do {
6815         if (_synctex_nodes_are_friend(N, best_child)) {
6816             ++best_count;
6817         }
6818     } while ((N = __synctex_tree_sibling(N)));
6819     /*  Navigate through the other children */
6820     while ((child = next_child)) {
6821         next_child = _synctex_tree_reset_child(child);
6822         target = _synctex_tree_target(child);
6823         parent = _synctex_tree_parent(target);
6824         count = 0;
6825         N = _synctex_tree_child(parent);
6826         do {
6827             if (_synctex_nodes_are_friend(N, best_child)) {
6828                 ++count;
6829             }
6830         } while ((N = __synctex_tree_sibling(N)));
6831         if (count > best_count) {
6832             best_count = count;
6833             synctex_node_free(best_child);
6834             best_child = child;
6835         } else {
6836             synctex_node_free(child);
6837         }
6838     }
6839     return best_child;
6840 }
6841 
6842 SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hitP, synctex_node_p node);
6843 
6844 /*  This struct records distances, the left one is non negative and the right one is non positive.
6845  *  When comparing the locations of 2 different graphical objects on the page, we will have to also record the
6846  *  horizontal distance as signed to keep track of the typesetting order.*/
6847 
6848 typedef struct {
6849     synctex_node_p node;
6850     int distance;
6851 } synctex_nd_s;
6852 
6853 #define SYNCTEX_ND_0                                                                                                                                                                                                                           \
6854     (synctex_nd_s)                                                                                                                                                                                                                             \
6855     {                                                                                                                                                                                                                                          \
6856         NULL, INT_MAX                                                                                                                                                                                                                          \
6857     }
6858 
6859 typedef synctex_nd_s *synctex_nd_p;
6860 
6861 typedef struct {
6862     synctex_nd_s l;
6863     synctex_nd_s r;
6864 } synctex_nd_lr_s;
6865 
6866 /*  The best container is the deeper box that contains the hit point (H,V).
6867  *  _synctex_eq_deepest_container_v2 starts with node whereas
6868  *  _synctex_box_child_deepest starts with node's children, if any
6869  *  if node is not a box, or a void box, NULL is returned.
6870  *  We traverse the node tree in a deep first manner and stop as soon as a result is found. */
6871 static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hitP, synctex_node_p node);
6872 
6873 SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node);
6874 
6875 /*  Closest child, recursive.  */
6876 static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node);
6877 
6878 /*  The smallest container between two has the smallest width or height.
6879  *  This comparison is used when there are 2 overlapping boxes that contain the hit point.
6880  *  For ConTeXt, the problem appears at each page.
6881  *  The chosen box is the one with the smallest height, then the smallest width. */
6882 SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node);
6883 
6884 /*  Returns the distance between the hit point hit point=(H,V) and the given node. */
6885 
6886 static int _synctex_point_node_distance_v2(synctex_point_p hitP, synctex_node_p node);
6887 
6888 /*  The closest container is the box that is the one closest to the given point.
6889  *  The "visible" version takes into account the visible dimensions instead of the real ones given by TeX. */
6890 static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node);
6891 
6892 #ifdef SYNCTEX_NOTHING
6893 #pragma mark -
6894 #pragma mark Queries
6895 #endif
6896 
6897 struct synctex_iterator_t {
6898     synctex_node_p seed;
6899     synctex_node_p next;
6900     int count0;
6901     int count;
6902 };
6903 
6904 SYNCTEX_INLINE static synctex_iterator_p _synctex_iterator_new(synctex_node_p result, int count)
6905 {
6906     synctex_iterator_p iterator;
6907     if ((iterator = _synctex_malloc(sizeof(synctex_iterator_s)))) {
6908         iterator->seed = iterator->next = result;
6909         iterator->count0 = iterator->count = count;
6910     }
6911     return iterator;
6912 };
6913 
6914 void synctex_iterator_free(synctex_iterator_p iterator)
6915 {
6916     if (iterator) {
6917         synctex_node_free(iterator->seed);
6918         _synctex_free(iterator);
6919     }
6920 }
6921 synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator)
6922 {
6923     return iterator ? iterator->count > 0 : 0;
6924 }
6925 int synctex_iterator_count(synctex_iterator_p iterator)
6926 {
6927     return iterator ? iterator->count : 0;
6928 }
6929 
6930 /**
6931  *  The next result of the iterator.
6932  *  Internally, the iterator stores handles to nodes.
6933  *  Externally, it returns the targets,
6934  *  such that the caller only sees nodes.
6935  */
6936 synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator)
6937 {
6938     if (iterator && iterator->count > 0) {
6939         synctex_node_p N = iterator->next;
6940         iterator->next = __synctex_tree_sibling(N);
6941         --iterator->count;
6942         return _synctex_tree_target(N);
6943     }
6944     return NULL;
6945 }
6946 int synctex_iterator_reset(synctex_iterator_p iterator)
6947 {
6948     if (iterator) {
6949         iterator->next = iterator->seed;
6950         return iterator->count = iterator->count0;
6951     }
6952     return 0;
6953 }
6954 
6955 synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner, int page, float h, float v)
6956 {
6957     if (scanner) {
6958         synctex_node_p sheet = NULL;
6959         synctex_point_s hit;
6960         synctex_node_p node = NULL;
6961         synctex_nd_lr_s nds = {{NULL, 0}, {NULL, 0}};
6962         if (NULL == (scanner = synctex_scanner_parse(scanner)) || 0 >= scanner->unit) { /*  scanner->unit must be >0 */
6963             return NULL;
6964         }
6965         /*  Find the proper sheet */
6966         sheet = synctex_sheet(scanner, page);
6967         if (NULL == sheet) {
6968             return NULL;
6969         }
6970         /*  Now sheet points to the sheet node with proper page number. */
6971         /*  Now that scanner has been initialized, we can convert
6972          *  the given point to scanner integer coordinates */
6973         hit = (synctex_point_s) {(h - scanner->x_offset) / scanner->unit, (v - scanner->y_offset) / scanner->unit};
6974         /*  At first, we browse all the horizontal boxes of the sheet
6975          *  until we find one containing the hit point. */
6976         if ((node = _synctex_tree_next_hbox(sheet))) {
6977             do {
6978                 if (_synctex_point_in_box_v2(&hit, node)) {
6979                     /*  Maybe the hit point belongs to a contained vertical box.
6980                      *  This is the most likely situation.
6981                      */
6982                     synctex_node_p next = node;
6983 #if defined(SYNCTEX_DEBUG)
6984                     printf("--- We are lucky\n");
6985 #endif
6986                     /*  This trick is for catching overlapping boxes */
6987                     while ((next = _synctex_tree_next_hbox(next))) {
6988                         if (_synctex_point_in_box_v2(&hit, next)) {
6989                             node = _synctex_smallest_container_v2(next, node);
6990                         }
6991                     }
6992                     /*  node is the smallest horizontal box that contains hit,
6993                      *  unless there is no hbox at all.
6994                      */
6995                     node = _synctex_eq_deepest_container_v2(&hit, node);
6996                     nds = _synctex_eq_get_closest_children_in_box_v2(&hit, node);
6997                 end:
6998                     if (nds.r.node && nds.l.node) {
6999                         if ((_synctex_data_tag(nds.r.node) != _synctex_data_tag(nds.l.node)) || (_synctex_data_line(nds.r.node) != _synctex_data_line(nds.l.node)) || (_synctex_data_column(nds.r.node) != _synctex_data_column(nds.l.node))) {
7000                             if (nds.l.distance > nds.r.distance) {
7001                                 node = nds.r.node;
7002                                 nds.r.node = nds.l.node;
7003                                 nds.l.node = node;
7004                             }
7005                             if ((node = _synctex_new_handle_with_target(nds.l.node))) {
7006                                 synctex_node_p other_handle;
7007                                 if ((other_handle = _synctex_new_handle_with_target(nds.r.node))) {
7008                                     _synctex_tree_set_sibling(node, other_handle);
7009                                     return _synctex_iterator_new(node, 2);
7010                                 }
7011                                 return _synctex_iterator_new(node, 1);
7012                             }
7013                             return NULL;
7014                         }
7015                         /*  both nodes have the same input coordinates
7016                          *  We choose the one closest to the hit point  */
7017                         if (nds.l.distance > nds.r.distance) {
7018                             nds.l.node = nds.r.node;
7019                         }
7020                         nds.r.node = NULL;
7021                     } else if (nds.r.node) {
7022                         nds.l = nds.r;
7023                     } else if (!nds.l.node) {
7024                         nds.l.node = node;
7025                     }
7026                     if ((node = _synctex_new_handle_with_target(nds.l.node))) {
7027                         return _synctex_iterator_new(node, 1);
7028                     }
7029                     return 0;
7030                 }
7031             } while ((node = _synctex_tree_next_hbox(node)));
7032             /*  All the horizontal boxes have been tested,
7033              *  None of them contains the hit point.
7034              */
7035         }
7036         /*  We are not lucky,
7037          *  we test absolutely all the node
7038          *  to find the closest... */
7039         if ((node = _synctex_tree_child(sheet))) {
7040 #if defined(SYNCTEX_DEBUG)
7041             printf("--- We are not lucky\n");
7042 #endif
7043             nds.l = __synctex_closest_deep_child_v2(&hit, node);
7044 #if defined(SYNCTEX_DEBUG)
7045             printf("Edit query best: %i\n", nds.l.distance);
7046 #endif
7047             goto end;
7048         }
7049     }
7050     return NULL;
7051 }
7052 
7053 /**
7054  *  Loop the candidate friendly list to find the ones with the proper
7055  *  tag and line.
7056  *  Returns a tree of results targeting the found candidates.
7057  *  At the top level each sibling has its own page number.
7058  *  All the results with the same page number are linked by child/parent entry.
7059  *  - parameter candidate: a friendly list of candidates
7060  */
7061 static synctex_node_p _synctex_display_query_v2(synctex_node_p target, int tag, int line, synctex_bool_t exclude_box)
7062 {
7063     synctex_node_p first_handle = NULL;
7064     /*  Search the first match */
7065     if (target == NULL) {
7066         return first_handle;
7067     }
7068     do {
7069         int page;
7070         if ((exclude_box && _synctex_node_is_box(target)) || (tag != synctex_node_tag(target)) || (line != synctex_node_line(target))) {
7071             continue;
7072         }
7073         /*  We found a first match, create
7074          *  a result handle targeting that candidate. */
7075         first_handle = _synctex_new_handle_with_target(target);
7076         if (first_handle == NULL) {
7077             return first_handle;
7078         }
7079         /*  target is either a node,
7080          *  or a proxy to some node, in which case,
7081          *  the target's target belongs to a form,
7082          *  not a sheet. */
7083         page = synctex_node_page(target);
7084         /*  Now create all the other results  */
7085         while ((target = _synctex_tree_friend(target))) {
7086             synctex_node_p result = NULL;
7087             if ((exclude_box && _synctex_node_is_box(target)) || (tag != synctex_node_tag(target)) || (line != synctex_node_line(target))) {
7088                 continue;
7089             }
7090             /*  Another match, same page number ? */
7091             result = _synctex_new_handle_with_target(target);
7092             if (NULL == result) {
7093                 return first_handle;
7094             }
7095             /*  is it the same page number ? */
7096             if (synctex_node_page(target) == page) {
7097                 __synctex_tree_set_child(result, first_handle);
7098                 first_handle = result;
7099             } else {
7100                 /*  We have 2 page numbers involved */
7101                 __synctex_tree_set_sibling(first_handle, result);
7102                 while ((target = _synctex_tree_friend(target))) {
7103                     synctex_node_p same_page_node;
7104                     if ((exclude_box && _synctex_node_is_box(target)) || (tag != synctex_node_tag(target)) || (line != synctex_node_line(target))) {
7105                         continue;
7106                     }
7107                     /*  New match found, which page? */
7108                     result = _synctex_new_handle_with_target(target);
7109                     if (NULL == result) {
7110                         return first_handle;
7111                     }
7112                     same_page_node = first_handle;
7113                     page = synctex_node_page(target);
7114                     /*  Find a result with the same page number */;
7115                     do {
7116                         if (_synctex_node_target_page(same_page_node) == page) {
7117                             _synctex_tree_set_child(result, _synctex_tree_set_child(same_page_node, result));
7118                         } else if ((same_page_node = __synctex_tree_sibling(same_page_node))) {
7119                             continue;
7120                         } else {
7121                             /*  This is a new page number */
7122                             __synctex_tree_set_sibling(result, first_handle);
7123                             first_handle = result;
7124                         }
7125                         break;
7126                     } while (synctex_YES);
7127                 }
7128                 return first_handle;
7129             }
7130         }
7131     } while ((target = _synctex_tree_friend(target)));
7132     return first_handle;
7133 }
7134 synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner, const char *name, int line, int column, int page_hint)
7135 {
7136     (void)column; /* unused */
7137     if (scanner) {
7138         int tag = synctex_scanner_get_tag(scanner, name); /* parse if necessary */
7139         int max_line = 0;
7140         int line_offset = 1;
7141         int try_count = 100;
7142         synctex_node_p node = NULL;
7143         synctex_node_p result = NULL;
7144         if (tag == 0) {
7145             printf("SyncTeX Warning: No tag for %s\n", name);
7146             return NULL;
7147         }
7148         node = synctex_scanner_input_with_tag(scanner, tag);
7149         max_line = _synctex_data_line(node);
7150         /*  node = NULL; */
7151         if (line > max_line) {
7152             line = max_line;
7153         }
7154         while (try_count--) {
7155             if (line <= max_line) {
7156                 /*  This loop will only be performed once for advanced viewers */
7157                 synctex_node_p friend = _synctex_scanner_friend(scanner, tag + line);
7158                 if ((node = friend)) {
7159                     result = _synctex_display_query_v2(node, tag, line, synctex_YES);
7160                     if (!result) {
7161                         /*  We did not find any matching boundary, retry including boxes */
7162                         node = friend; /*  no need to test it again, already done */
7163                         result = _synctex_display_query_v2(node, tag, line, synctex_NO);
7164                     }
7165                     /*  Now reverse the order to have nodes in display order, and then keep just a few nodes.
7166                      *  Order first the best node. */
7167                     /*  The result is a tree. At the root level, all nodes
7168                      *  correspond to different page numbers.
7169                      *  Each node has a child which corresponds to the same
7170                      *  page number if relevant.
7171                      *  Then reorder the nodes to put first the one which fits best.
7172                      *  The idea is to count the number of nodes
7173                      *  with the same tag and line number in the parents
7174                      *  and choose the one with the biggest count.
7175                      */
7176                     if (result) {
7177                         /*  navigate through siblings,
7178                          then children   */
7179                         int count = 1;
7180                         synctex_node_p next_sibling = __synctex_tree_reset_sibling(result);
7181                         int best_match = abs(page_hint - _synctex_node_target_page(result));
7182                         synctex_node_p sibling;
7183                         int match;
7184                         result = _synctex_vertically_sorted_v2(result);
7185                         while ((sibling = next_sibling)) {
7186                             /* What is next? Do not miss that step! */
7187                             next_sibling = __synctex_tree_reset_sibling(sibling);
7188                             sibling = _synctex_vertically_sorted_v2(sibling);
7189                             match = abs(page_hint - _synctex_node_target_page(sibling));
7190                             if (match < best_match) {
7191                                 /*  Order this node first */
7192                                 __synctex_tree_set_sibling(sibling, result);
7193                                 result = sibling;
7194                                 best_match = match;
7195                             } else /*if (match>best_match)*/ {
7196                                 __synctex_tree_set_sibling(sibling, __synctex_tree_sibling(result));
7197                                 __synctex_tree_set_sibling(result, sibling);
7198                             }
7199                             ++count;
7200                         }
7201                         /*  Now order first the result closest to the page hint */
7202                         return _synctex_iterator_new(result, count);
7203                     }
7204                 }
7205 #if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__)
7206                 break;
7207 #else
7208                 line += line_offset;
7209                 line_offset = line_offset < 0 ? -(line_offset - 1) : -(line_offset + 1);
7210                 if (line <= 0) {
7211                     line += line_offset;
7212                     line_offset = line_offset < 0 ? -(line_offset - 1) : -(line_offset + 1);
7213                 }
7214 #endif
7215             }
7216         }
7217     }
7218     return NULL;
7219 }
7220 synctex_status_t synctex_display_query(synctex_scanner_p scanner, const char *name, int line, int column, int page_hint)
7221 {
7222     if (scanner) {
7223         synctex_iterator_free(scanner->iterator);
7224         scanner->iterator = synctex_iterator_new_display(scanner, name, line, column, page_hint);
7225         return synctex_iterator_count(scanner->iterator);
7226     }
7227     return SYNCTEX_STATUS_ERROR;
7228 }
7229 synctex_status_t synctex_edit_query(synctex_scanner_p scanner, int page, float h, float v)
7230 {
7231     if (scanner) {
7232         synctex_iterator_free(scanner->iterator);
7233         scanner->iterator = synctex_iterator_new_edit(scanner, page, h, v);
7234         return synctex_iterator_count(scanner->iterator);
7235     }
7236     return SYNCTEX_STATUS_ERROR;
7237 }
7238 /**
7239  *  The next result of a query.
7240  */
7241 synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner)
7242 {
7243     return scanner ? synctex_iterator_next_result(scanner->iterator) : NULL;
7244 }
7245 synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner)
7246 {
7247     return scanner ? synctex_iterator_reset(scanner->iterator) : SYNCTEX_STATUS_ERROR;
7248 }
7249 
7250 synctex_node_p synctex_node_target(synctex_node_p node)
7251 {
7252     return _synctex_tree_target(node);
7253 }
7254 
7255 #ifdef SYNCTEX_NOTHING
7256 #pragma mark -
7257 #pragma mark Geometric utilities
7258 #endif
7259 
7260 /** Rougly speaking, this is:
7261  *  node's h coordinate - hit point's h coordinate.
7262  *  If node is to the right of the hit point, then this distance is positive,
7263  *  if node is to the left of the hit point, this distance is negative.
7264  *  If the argument is a pdf form reference, then the child is used and returned instead.
7265  *  Last Revision: Mon Apr 24 07:05:27 UTC 2017
7266  */
7267 static synctex_nd_s _synctex_point_h_ordered_distance_v2(synctex_point_p hit, synctex_node_p node)
7268 {
7269     synctex_nd_s nd = {node, INT_MAX};
7270     if (node) {
7271         int min, med, max, width;
7272         switch (synctex_node_type(node)) {
7273             /*  The distance between a point and a box is special.
7274              *  It is not the euclidian distance, nor something similar.
7275              *  We have to take into account the particular layout,
7276              *  and the box hierarchy.
7277              *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
7278              *  The origin being at the top left corner of the page,
7279              *  we also give names to the vertices of the box.
7280              *
7281              *   1 | 2 | 3
7282              *  ---A---B--->
7283              *   4 | 5 | 6
7284              *  ---C---D--->
7285              *   7 | 8 | 9
7286              *     v   v
7287              */
7288         case synctex_node_type_vbox:
7289         case synctex_node_type_void_vbox:
7290         case synctex_node_type_void_hbox:
7291             /*  getting the box bounds, taking into account negative width, height and depth. */
7292             width = _synctex_data_width(node);
7293             min = _synctex_data_h(node);
7294             max = min + (width > 0 ? width : -width);
7295             /*  We always have min <= max */
7296             if (hit->h < min) {
7297                 nd.distance = min - hit->h; /*  regions 1+4+7, result is > 0 */
7298             } else if (hit->h > max) {
7299                 nd.distance = max - hit->h; /*  regions 3+6+9, result is < 0 */
7300             } else {
7301                 nd.distance = 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
7302             }
7303             break;
7304         case synctex_node_type_proxy_vbox:
7305             /*  getting the box bounds, taking into account negative width, height and depth. */
7306             width = synctex_node_width(node);
7307             min = synctex_node_h(node);
7308             max = min + (width > 0 ? width : -width);
7309             /*  We always have min <= max */
7310             if (hit->h < min) {
7311                 nd.distance = min - hit->h; /*  regions 1+4+7, result is > 0 */
7312             } else if (hit->h > max) {
7313                 nd.distance = max - hit->h; /*  regions 3+6+9, result is < 0 */
7314             } else {
7315                 nd.distance = 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
7316             }
7317             break;
7318         case synctex_node_type_hbox:
7319         case synctex_node_type_proxy_hbox:
7320             /*  getting the box bounds, taking into account negative width, height and depth. */
7321             width = synctex_node_hbox_width(node);
7322             min = synctex_node_hbox_h(node);
7323             max = min + (width > 0 ? width : -width);
7324             /*  We always have min <= max */
7325             if (hit->h < min) {
7326                 nd.distance = min - hit->h; /*  regions 1+4+7, result is > 0 */
7327             } else if (hit->h > max) {
7328                 nd.distance = max - hit->h; /*  regions 3+6+9, result is < 0 */
7329             } else {
7330                 nd.distance = 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
7331             }
7332             break;
7333         case synctex_node_type_kern:
7334             /*  IMPORTANT NOTICE: the location of the kern is recorded AFTER the move.
7335              *  The distance to the kern is very special,
7336              *  in general, there is no text material in the kern,
7337              *  this is why we compute the offset relative to the closest edge of the kern.*/
7338             max = _synctex_data_width(node);
7339             if (max < 0) {
7340                 min = _synctex_data_h(node);
7341                 max = min - max;
7342             } else {
7343                 min = -max;
7344                 max = _synctex_data_h(node);
7345                 min += max;
7346             }
7347             med = (min + max) / 2;
7348             /*  positive kern: '.' means text, '>' means kern offset
7349              *      .............
7350              *                   min>>>>med>>>>max
7351              *                                    ...............
7352              *  negative kern: '.' means text, '<' means kern offset
7353              *      ............................
7354              *                 min<<<<med<<<<max
7355              *                 .................................
7356              *  Actually, we do not take into account negative widths.
7357              *  There is a problem for such situation when there is effectively overlapping text.
7358              *  But this should be extremely rare. I guess that in that case, many different choices
7359              *  could be made, one being in contradiction with the other.
7360              *  It means that the best choice should be made according to the situation that occurs
7361              *  most frequently.
7362              */
7363             if (hit->h < min) {
7364                 nd.distance = min - hit->h + 1; /*  penalty to ensure other nodes are chosen first in case of overlapping ones */
7365             } else if (hit->h > max) {
7366                 nd.distance = max - hit->h - 1; /*  same kind of penalty */
7367             } else if (hit->h > med) {
7368                 /*  do things like if the node had 0 width and was placed at the max edge + 1*/
7369                 nd.distance = max - hit->h + 1; /*  positive, the kern is to the right of the hit point */
7370             } else {
7371                 nd.distance = min - hit->h - 1; /*  negative, the kern is to the left of the hit point */
7372             }
7373             break;
7374         case synctex_node_type_rule: /* to do: special management */
7375         case synctex_node_type_glue:
7376         case synctex_node_type_math:
7377         case synctex_node_type_boundary:
7378         case synctex_node_type_box_bdry:
7379             nd.distance = _synctex_data_h(node) - hit->h;
7380             break;
7381         case synctex_node_type_ref:
7382             nd.node = synctex_node_child(node);
7383             nd = _synctex_point_h_ordered_distance_v2(hit, nd.node);
7384             break;
7385         case synctex_node_type_proxy:
7386         case synctex_node_type_proxy_last: {
7387             /* shift the hit point to be relative to the proxy origin,
7388              *  then compute the distance to the target
7389              */
7390             synctex_point_s otherHit = *hit;
7391             otherHit.h -= _synctex_data_h(node);
7392             otherHit.v -= _synctex_data_v(node);
7393             nd.node = _synctex_tree_target(node);
7394             nd = _synctex_point_h_ordered_distance_v2(&otherHit, nd.node);
7395             nd.node = node;
7396         }
7397         default:
7398             break;
7399         }
7400     }
7401     return nd;
7402 }
7403 /** Rougly speaking, this is:
7404  *  node's v coordinate - hit point's v coordinate.
7405  *  If node is at the top of the hit point, then this distance is positive,
7406  *  if node is at the bottom of the hit point, this distance is negative.
7407  */
7408 static synctex_nd_s _synctex_point_v_ordered_distance_v2(synctex_point_p hit, synctex_node_p node)
7409 {
7410     synctex_nd_s nd = {node, INT_MAX};
7411     int min, max, depth, height;
7412     switch (synctex_node_type(node)) {
7413         /*  The distance between a point and a box is special.
7414          *  It is not the euclidian distance, nor something similar.
7415          *  We have to take into account the particular layout,
7416          *  and the box hierarchy.
7417          *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
7418          *  The origin being at the top left corner of the page,
7419          *  we also give names to the vertices of the box.
7420          *
7421          *   1 | 2 | 3
7422          *  ---A---B--->
7423          *   4 | 5 | 6
7424          *  ---C---D--->
7425          *   7 | 8 | 9
7426          *     v   v
7427          */
7428     case synctex_node_type_vbox:
7429     case synctex_node_type_void_vbox:
7430     case synctex_node_type_void_hbox:
7431         /*  getting the box bounds, taking into account negative width, height and depth. */
7432         min = synctex_node_v(node);
7433         max = min + _synctex_abs(_synctex_data_depth(node));
7434         min -= _synctex_abs(_synctex_data_height(node));
7435         /*  We always have min <= max */
7436         if (hit->v < min) {
7437             nd.distance = min - hit->v; /*  regions 1+2+3, result is > 0 */
7438         } else if (hit->v > max) {
7439             nd.distance = max - hit->v; /*  regions 7+8+9, result is < 0 */
7440         } else {
7441             nd.distance = 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
7442         }
7443         break;
7444     case synctex_node_type_proxy_vbox:
7445         /*  getting the box bounds, taking into account negative width, height and depth. */
7446         min = synctex_node_v(node);
7447         max = min + _synctex_abs(synctex_node_depth(node));
7448         min -= _synctex_abs(synctex_node_height(node));
7449         /*  We always have min <= max */
7450         if (hit->v < min) {
7451             nd.distance = min - hit->v; /*  regions 1+2+3, result is > 0 */
7452         } else if (hit->v > max) {
7453             nd.distance = max - hit->v; /*  regions 7+8+9, result is < 0 */
7454         } else {
7455             nd.distance = 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
7456         }
7457         break;
7458     case synctex_node_type_hbox:
7459     case synctex_node_type_proxy_hbox:
7460         /*  getting the box bounds, taking into account negative height and depth. */
7461         min = synctex_node_hbox_v(node);
7462         depth = synctex_node_hbox_depth(node);
7463         max = min + (depth > 0 ? depth : -depth);
7464         height = synctex_node_hbox_height(node);
7465         min -= (height > 0 ? height : -height);
7466         /*  We always have min <= max */
7467         if (hit->v < min) {
7468             nd.distance = min - hit->v; /*  regions 1+2+3, result is > 0 */
7469         } else if (hit->v > max) {
7470             nd.distance = max - hit->v; /*  regions 7+8+9, result is < 0 */
7471         } else {
7472             nd.distance = 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
7473         }
7474         break;
7475     case synctex_node_type_rule: /* to do: special management */
7476     case synctex_node_type_kern:
7477     case synctex_node_type_glue:
7478     case synctex_node_type_math:
7479         min = _synctex_data_v(node);
7480         max = min + _synctex_abs(_synctex_data_depth(_synctex_tree_parent(node)));
7481         min -= _synctex_abs(_synctex_data_height(_synctex_tree_parent(node)));
7482         /*  We always have min <= max */
7483         if (hit->v < min) {
7484             nd.distance = min - hit->v; /*  regions 1+2+3, result is > 0 */
7485         } else if (hit->v > max) {
7486             nd.distance = max - hit->v; /*  regions 7+8+9, result is < 0 */
7487         } else {
7488             nd.distance = 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
7489         }
7490         break;
7491     case synctex_node_type_ref:
7492         nd.node = synctex_node_child(node);
7493         nd = _synctex_point_v_ordered_distance_v2(hit, nd.node);
7494         break;
7495     case synctex_node_type_proxy:
7496     case synctex_node_type_proxy_last: {
7497         synctex_point_s otherHit = *hit;
7498         otherHit.h -= _synctex_data_h(node);
7499         otherHit.v -= _synctex_data_v(node);
7500         nd.node = _synctex_tree_target(node);
7501         nd = _synctex_point_v_ordered_distance_v2(&otherHit, nd.node);
7502         nd.node = node;
7503     }
7504     default:
7505         break;
7506     }
7507     return nd;
7508 }
7509 /**
7510  *  The best is the one with the smallest area.
7511  *  The area is width*height where width and height may be big.
7512  *  So there is a real risk of overflow if we stick with ints.
7513  */
7514 SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node)
7515 {
7516     long total_height, other_total_height;
7517     unsigned long area, other_area;
7518     long width = synctex_node_hbox_width(node);
7519     long other_width = synctex_node_hbox_width(other_node);
7520     if (width < 0) {
7521         width = -width;
7522     }
7523     if (other_width < 0) {
7524         other_width = -other_width;
7525     }
7526     total_height = _synctex_abs(synctex_node_hbox_depth(node)) + _synctex_abs(synctex_node_hbox_height(node));
7527     other_total_height = _synctex_abs(synctex_node_hbox_depth(other_node)) + _synctex_abs(synctex_node_hbox_height(other_node));
7528     area = total_height * width;
7529     other_area = other_total_height * other_width;
7530     if (area < other_area) {
7531         return node;
7532     }
7533     if (area > other_area) {
7534         return other_node;
7535     }
7536     if (_synctex_abs(_synctex_data_width(node)) > _synctex_abs(_synctex_data_width(other_node))) {
7537         return node;
7538     }
7539     if (_synctex_abs(_synctex_data_width(node)) < _synctex_abs(_synctex_data_width(other_node))) {
7540         return other_node;
7541     }
7542     if (total_height < other_total_height) {
7543         return node;
7544     }
7545     if (total_height > other_total_height) {
7546         return other_node;
7547     }
7548     return node;
7549 }
7550 
7551 SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hit, synctex_node_p node)
7552 {
7553     if (node) {
7554         if (0 == _synctex_point_h_ordered_distance_v2(hit, node).distance && 0 == _synctex_point_v_ordered_distance_v2(hit, node).distance) {
7555             return synctex_YES;
7556         }
7557     }
7558     return synctex_NO;
7559 }
7560 
7561 static int _synctex_distance_to_box_v2(synctex_point_p hit, synctex_box_p box)
7562 {
7563     /*  The distance between a point and a box is special.
7564      *  It is not the euclidian distance, nor something similar.
7565      *  We have to take into account the particular layout,
7566      *  and the box hierarchy.
7567      *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
7568      *  The origin being at the top left corner of the page,
7569      *  we also give names to the vertices of the box.
7570      *
7571      *   1 | 2 | 3
7572      *  ---A---B--->
7573      *   4 | 5 | 6
7574      *  ---C---D--->
7575      *   7 | 8 | 9
7576      *     v   v
7577      *  In each region, there is a different formula.
7578      *  In the end we have a continuous distance which may not be a mathematical distance but who cares. */
7579     if (hit->v < box->min.v) {
7580         /*  Regions 1, 2 or 3 */
7581         if (hit->h < box->min.h) {
7582             /*  This is region 1. The distance to the box is the L1 distance PA. */
7583             return box->min.v - hit->v + box->min.h - hit->h; /*  Integer overflow? probability epsilon */
7584         } else if (hit->h <= box->max.h) {
7585             /*  This is region 2. The distance to the box is the geometrical distance to the top edge.  */
7586             return box->min.v - hit->v;
7587         } else {
7588             /*  This is region 3. The distance to the box is the L1 distance PB. */
7589             return box->min.v - hit->v + hit->h - box->max.h;
7590         }
7591     } else if (hit->v <= box->max.v) {
7592         /*  Regions 4, 5 or 6 */
7593         if (hit->h < box->min.h) {
7594             /*  This is region 4. The distance to the box is the geometrical distance to the left edge.  */
7595             return box->min.h - hit->h;
7596         } else if (hit->h <= box->max.h) {
7597             /*  This is region 5. We are inside the box.  */
7598             return 0;
7599         } else {
7600             /*  This is region 6. The distance to the box is the geometrical distance to the right edge.  */
7601             return hit->h - box->max.h;
7602         }
7603     } else {
7604         /*  Regions 7, 8 or 9 */
7605         if (hit->h < box->min.h) {
7606             /*  This is region 7. The distance to the box is the L1 distance PC. */
7607             return hit->v - box->max.v + box->min.h - hit->h;
7608         } else if (hit->h <= box->max.h) {
7609             /*  This is region 8. The distance to the box is the geometrical distance to the top edge.  */
7610             return hit->v - box->max.v;
7611         } else {
7612             /*  This is region 9. The distance to the box is the L1 distance PD. */
7613             return hit->v - box->max.v + hit->h - box->max.h;
7614         }
7615     }
7616 }
7617 
7618 /**
7619  *  The distance from the hit point to the node.
7620  */
7621 static int _synctex_point_node_distance_v2(synctex_point_p hit, synctex_node_p node)
7622 {
7623     int d = INT_MAX;
7624     if (node) {
7625         synctex_box_s box = {{0, 0}, {0, 0}};
7626         int dd = INT_MAX;
7627         switch (synctex_node_type(node)) {
7628         case synctex_node_type_vbox:
7629             box.min.h = _synctex_data_h(node);
7630             box.max.h = box.min.h + _synctex_abs(_synctex_data_width(node));
7631             box.min.v = synctex_node_v(node);
7632             box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node));
7633             box.min.v -= _synctex_abs(_synctex_data_height(node));
7634             return _synctex_distance_to_box_v2(hit, &box);
7635         case synctex_node_type_proxy_vbox:
7636             box.min.h = synctex_node_h(node);
7637             box.max.h = box.min.h + _synctex_abs(synctex_node_width(node));
7638             box.min.v = synctex_node_v(node);
7639             box.max.v = box.min.v + _synctex_abs(synctex_node_depth(node));
7640             box.min.v -= _synctex_abs(synctex_node_height(node));
7641             return _synctex_distance_to_box_v2(hit, &box);
7642         case synctex_node_type_hbox:
7643         case synctex_node_type_proxy_hbox:
7644             box.min.h = synctex_node_hbox_h(node);
7645             box.max.h = box.min.h + _synctex_abs(synctex_node_hbox_width(node));
7646             box.min.v = synctex_node_hbox_v(node);
7647             box.max.v = box.min.v + _synctex_abs(synctex_node_hbox_depth(node));
7648             box.min.v -= _synctex_abs(synctex_node_hbox_height(node));
7649             return _synctex_distance_to_box_v2(hit, &box);
7650         case synctex_node_type_void_vbox:
7651         case synctex_node_type_void_hbox:
7652             /*  best of distances from the left edge and right edge*/
7653             box.min.h = _synctex_data_h(node);
7654             box.max.h = box.min.h;
7655             box.min.v = _synctex_data_v(node);
7656             box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node));
7657             box.min.v -= _synctex_abs(_synctex_data_height(node));
7658             d = _synctex_distance_to_box_v2(hit, &box);
7659             box.min.h = box.min.h + _synctex_abs(_synctex_data_width(node));
7660             box.max.h = box.min.h;
7661             dd = _synctex_distance_to_box_v2(hit, &box);
7662             return d < dd ? d : dd;
7663         case synctex_node_type_kern:
7664             box.min.h = _synctex_data_h(node);
7665             box.max.h = box.min.h;
7666             box.max.v = _synctex_data_v(node);
7667             box.min.v = box.max.v - _synctex_abs(_synctex_data_height(_synctex_tree_parent(node)));
7668             d = _synctex_distance_to_box_v2(hit, &box);
7669             box.min.h -= _synctex_data_width(node);
7670             box.max.h = box.min.h;
7671             dd = _synctex_distance_to_box_v2(hit, &box);
7672             return d < dd ? d : dd;
7673         case synctex_node_type_glue:
7674         case synctex_node_type_math:
7675         case synctex_node_type_boundary:
7676         case synctex_node_type_box_bdry:
7677             box.min.h = _synctex_data_h(node);
7678             box.max.h = box.min.h;
7679             box.max.v = _synctex_data_v(node);
7680             box.min.v = box.max.v - _synctex_abs(_synctex_data_height(_synctex_tree_parent(node)));
7681             return _synctex_distance_to_box_v2(hit, &box);
7682         case synctex_node_type_proxy:
7683         case synctex_node_type_proxy_last: {
7684             synctex_point_s otherHit = *hit;
7685             otherHit.h -= _synctex_data_h(node);
7686             otherHit.v -= _synctex_data_v(node);
7687             return _synctex_point_node_distance_v2(&otherHit, _synctex_tree_target(node));
7688         }
7689         default:
7690             break;
7691         }
7692     }
7693     return d;
7694 }
7695 static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hit, synctex_node_p node)
7696 {
7697     if (node) {
7698         /**/
7699         synctex_node_p child;
7700         if ((child = synctex_node_child(node))) {
7701             /*  Non void hbox or vbox, form ref or proxy */
7702             /*  We go deep first because some boxes have 0 dimensions
7703              *  despite they do contain some black material.
7704              */
7705             do {
7706                 if ((_synctex_point_in_box_v2(hit, child))) {
7707                     synctex_node_p deep = _synctex_eq_deepest_container_v2(hit, child);
7708                     if (deep) {
7709                         /*  One of the children contains the hit. */
7710                         return deep;
7711                     }
7712                 }
7713             } while ((child = synctex_node_sibling(child)));
7714             /*  is the hit point inside the box? */
7715             if (synctex_node_type(node) == synctex_node_type_vbox || synctex_node_type(node) == synctex_node_type_proxy_vbox) {
7716                 /*  For vboxes we try to use some node inside.
7717                  *  Walk through the list of siblings until we find the closest one.
7718                  *  Only consider siblings with children inside. */
7719                 if ((child = _synctex_tree_child(node))) {
7720                     synctex_nd_s best = SYNCTEX_ND_0;
7721                     do {
7722                         if (_synctex_tree_child(child)) {
7723                             int d = _synctex_point_node_distance_v2(hit, child);
7724                             if (d <= best.distance) {
7725                                 best = (synctex_nd_s) {child, d};
7726                             }
7727                         }
7728                     } while ((child = __synctex_tree_sibling(child)));
7729                     if (best.node) {
7730                         return best.node;
7731                     }
7732                 }
7733             }
7734             if (_synctex_point_in_box_v2(hit, node)) {
7735                 return node;
7736             }
7737         }
7738     }
7739     return NULL;
7740 }
7741 static synctex_nd_s _synctex_eq_deepest_container_v3(synctex_point_p hit, synctex_node_p node)
7742 {
7743     if (node) {
7744         synctex_node_p child = NULL;
7745         if ((child = synctex_node_child(node))) {
7746             /*  Non void hbox, vbox, box proxy or form ref */
7747             /*  We go deep first because some boxes have 0 dimensions
7748              *  despite they do contain some black material.
7749              */
7750             do {
7751                 synctex_nd_s deep = _synctex_eq_deepest_container_v3(hit, child);
7752                 if (deep.node) {
7753                     /*  One of the children contains the hit-> */
7754                     return deep;
7755                 }
7756             } while ((child = synctex_node_sibling(child)));
7757             /*  For vboxes we try to use some node inside.
7758              *  Walk through the list of siblings until we find the closest one.
7759              *  Only consider siblings with children inside. */
7760             if (synctex_node_type(node) == synctex_node_type_vbox || synctex_node_type(node) == synctex_node_type_proxy_vbox) {
7761                 if ((child = synctex_node_child(node))) {
7762                     synctex_nd_s best = SYNCTEX_ND_0;
7763                     do {
7764                         if (synctex_node_child(child)) {
7765                             int d = _synctex_point_node_distance_v2(hit, child);
7766                             if (d < best.distance) {
7767                                 best = (synctex_nd_s) {child, d};
7768                             }
7769                         }
7770                     } while ((child = synctex_node_sibling(child)));
7771                     if (best.node) {
7772                         return best;
7773                     }
7774                 }
7775             }
7776             /*  is the hit point inside the box? */
7777             if (_synctex_point_in_box_v2(hit, node)) {
7778                 return (synctex_nd_s) {node, 0};
7779             }
7780         }
7781     }
7782     return SYNCTEX_ND_0;
7783 }
7784 
7785 /*  Compares the locations of the hit point with the locations of
7786  *  the various nodes contained in the box.
7787  *  As it is an horizontal box, we only compare horizontal coordinates.
7788  */
7789 SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v2(synctex_point_p hitP, synctex_node_p node)
7790 {
7791     synctex_nd_s childd = SYNCTEX_ND_0;
7792     synctex_nd_lr_s nds = {SYNCTEX_ND_0, SYNCTEX_ND_0};
7793     if ((childd.node = synctex_node_child(node))) {
7794         synctex_nd_s nd = SYNCTEX_ND_0;
7795         do {
7796             childd = _synctex_point_h_ordered_distance_v2(hitP, childd.node);
7797             if (childd.distance > 0) {
7798                 /*  node is to the right of the hit point.
7799                  *  We compare node and the previously recorded one, through the recorded distance.
7800                  *  If the nodes have the same tag, prefer the one with the smallest line number,
7801                  *  if the nodes also have the same line number, prefer the one with the smallest column. */
7802                 if (nds.r.distance > childd.distance) {
7803                     nds.r = childd;
7804                 } else if (nds.r.distance == childd.distance && nds.r.node) {
7805                     if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(childd.node) &&
7806                         (_synctex_data_line(nds.r.node) > _synctex_data_line(childd.node) || (_synctex_data_line(nds.r.node) == _synctex_data_line(childd.node) && _synctex_data_column(nds.r.node) > _synctex_data_column(childd.node)))) {
7807                         nds.r = childd;
7808                     }
7809                 }
7810             } else if (childd.distance == 0) {
7811                 /*  hit point is inside node. */
7812                 return _synctex_eq_get_closest_children_in_box_v2(hitP, childd.node);
7813             } else { /*  here childd.distance < 0, the hit point is to the right of node */
7814                 childd.distance = -childd.distance;
7815                 if (nds.l.distance > childd.distance) {
7816                     nds.l = childd;
7817                 } else if (nds.l.distance == childd.distance && nds.l.node) {
7818                     if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(childd.node) &&
7819                         (_synctex_data_line(nds.l.node) > _synctex_data_line(childd.node) || (_synctex_data_line(nds.l.node) == _synctex_data_line(childd.node) && _synctex_data_column(nds.l.node) > _synctex_data_column(childd.node)))) {
7820                         nds.l = childd;
7821                     }
7822                 }
7823             }
7824         } while ((childd.node = synctex_node_sibling(childd.node)));
7825         if (nds.l.node) {
7826             /*  the left node is new, try to narrow the result */
7827             if ((nd = _synctex_eq_deepest_container_v3(hitP, nds.l.node)).node) {
7828                 nds.l = nd;
7829             }
7830             if ((nd = __synctex_closest_deep_child_v2(hitP, nds.l.node)).node) {
7831                 nds.l.node = nd.node;
7832             }
7833         }
7834         if (nds.r.node) {
7835             /*  the right node is new, try to narrow the result */
7836             if ((nd = _synctex_eq_deepest_container_v3(hitP, nds.r.node)).node) {
7837                 nds.r = nd;
7838             }
7839             if ((nd = __synctex_closest_deep_child_v2(hitP, nds.r.node)).node) {
7840                 nds.r.node = nd.node;
7841             }
7842         }
7843     }
7844     return nds;
7845 }
7846 
7847 SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_vbox_v2(synctex_point_p hitP, synctex_node_p nodeP)
7848 {
7849     (void)nodeP; /* unused */
7850     synctex_nd_lr_s nds = {SYNCTEX_ND_0, SYNCTEX_ND_0};
7851     synctex_nd_s nd = SYNCTEX_ND_0;
7852     if ((nd.node = synctex_node_child(nd.node))) {
7853         do {
7854             nd = _synctex_point_v_ordered_distance_v2(hitP, nd.node);
7855             /*  this is what makes the difference with the h version above */
7856             if (nd.distance > 0) {
7857                 /*  node is to the top of the hit point (below because TeX is oriented from top to bottom.
7858                  *  We compare node and the previously recorded one, through the recorded distance.
7859                  *  If the nodes have the same tag, prefer the one with the smallest line number,
7860                  *  if the nodes also have the same line number, prefer the one with the smallest column. */
7861                 if (nds.r.distance > nd.distance) {
7862                     nds.r = nd;
7863                 } else if (nds.r.distance == nd.distance && nds.r.node) {
7864                     if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node) &&
7865                         (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node) || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node) && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) {
7866                         nds.r = nd;
7867                     }
7868                 }
7869             } else if (nd.distance == 0) {
7870                 nds.l = nd;
7871             } else { /*  here nd < 0 */
7872                 nd.distance = -nd.distance;
7873                 if (nds.l.distance > nd.distance) {
7874                     nds.l = nd;
7875                 } else if (nds.l.distance == nd.distance && nds.l.node) {
7876                     if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node) &&
7877                         (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node) || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node) && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) {
7878                         nds.l = nd;
7879                     }
7880                 }
7881             }
7882         } while ((nd.node = synctex_node_sibling(nd.node)));
7883         if (nds.l.node) {
7884             if ((nd.node = _synctex_eq_deepest_container_v2(hitP, nds.l.node))) {
7885                 nds.l.node = nd.node;
7886             }
7887             if ((nd = _synctex_eq_closest_child_v2(hitP, nds.l.node)).node) {
7888                 nds.l.node = nd.node;
7889             }
7890         }
7891         if (nds.r.node) {
7892             if ((nd.node = _synctex_eq_deepest_container_v2(hitP, nds.r.node))) {
7893                 nds.r.node = nd.node;
7894             }
7895             if ((nd = _synctex_eq_closest_child_v2(hitP, nds.r.node)).node) {
7896                 nds.r.node = nd.node;
7897             }
7898         }
7899     }
7900     return nds;
7901 }
7902 
7903 /**
7904  *  Get the child closest to the hit point.
7905  *  - parameter: hit point
7906  *  - parameter: containing node
7907  *  - returns: the child and the distance to the hit point.
7908  *      SYNCTEX_ND_0 if the parameter node has no children.
7909  *  - note: recursive call.
7910  */
7911 static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node)
7912 {
7913     synctex_nd_s best = SYNCTEX_ND_0;
7914     synctex_node_p child = NULL;
7915     if ((child = synctex_node_child(node))) {
7916 #if defined(SYNCTEX_DEBUG)
7917         printf("Closest deep child on box at line %i\n", SYNCTEX_LINEINDEX(node));
7918 #endif
7919         do {
7920 #if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 500
7921             synctex_node_display(child);
7922 #endif
7923             synctex_nd_s nd = SYNCTEX_ND_0;
7924             if (_synctex_node_is_box(child)) {
7925                 nd = __synctex_closest_deep_child_v2(hitP, child);
7926             } else {
7927                 nd = (synctex_nd_s) {child, _synctex_point_node_distance_v2(hitP, child)};
7928             }
7929             if (nd.distance < best.distance || (nd.distance == best.distance && synctex_node_type(nd.node) != synctex_node_type_kern)) {
7930 #if defined(SYNCTEX_DEBUG)
7931                 if (nd.node) {
7932                     printf("New best %i<=%i line %i\n", nd.distance, best.distance, SYNCTEX_LINEINDEX(nd.node));
7933                 }
7934 #endif
7935                 best = nd;
7936             }
7937         } while ((child = synctex_node_sibling(child)));
7938 #if defined(SYNCTEX_DEBUG)
7939         if (best.node) {
7940             printf("Found new best %i line %i\n", best.distance, SYNCTEX_LINEINDEX(best.node));
7941         }
7942 #endif
7943     }
7944     return best;
7945 }
7946 
7947 /**
7948  *  Return the closest child.
7949  *  - parameter: a pointer to the hit point,
7950  *  - parameter: the container
7951  *  - return: SYNCTEX_ND_0 if node has no child,
7952  *      the __synctex_closest_deep_child_v2 otherwise.
7953  */
7954 static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node)
7955 {
7956     synctex_nd_s nd = SYNCTEX_ND_0;
7957     if (_synctex_node_is_box(node)) {
7958         nd = __synctex_closest_deep_child_v2(hitP, node);
7959         if (_synctex_node_is_box(nd.node)) {
7960             synctex_node_p child = NULL;
7961             if ((child = synctex_node_child(nd.node))) {
7962                 synctex_nd_s best = {child, _synctex_point_node_distance_v2(hitP, child)};
7963                 while ((child = synctex_node_sibling(child))) {
7964                     int d = _synctex_point_node_distance_v2(hitP, child);
7965                     if (d < best.distance) {
7966                         best = (synctex_nd_s) {child, d};
7967                     } else if (d == best.distance && synctex_node_type(child) != synctex_node_type_kern) {
7968                         best.node = child;
7969                     }
7970                 }
7971                 return best;
7972             }
7973         }
7974         return nd;
7975     }
7976     return SYNCTEX_ND_0;
7977 }
7978 SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node)
7979 {
7980     synctex_nd_lr_s nds = {SYNCTEX_ND_0, SYNCTEX_ND_0};
7981     if (_synctex_tree_has_child(node)) { /* node != NULL */
7982         if (node->class->type == synctex_node_type_hbox || node->class->type == synctex_node_type_proxy_hbox) {
7983             return __synctex_eq_get_closest_children_in_hbox_v2(hitP, node);
7984         } else {
7985             return __synctex_eq_get_closest_children_in_vbox_v2(hitP, node);
7986         }
7987     }
7988     return nds;
7989 }
7990 
7991 #ifndef SYNCTEX_NO_UPDATER
7992 
7993 #ifdef SYNCTEX_NOTHING
7994 #pragma mark -
7995 #pragma mark Updater
7996 #endif
7997 
7998 typedef int (*synctex_print_f)(synctex_updater_p, const char *, ...); /*  print formatted to either FILE *  or gzFile */
7999 typedef void (*synctex_close_f)(synctex_updater_p);                   /*  close FILE *  or gzFile */
8000 
8001 #define SYNCTEX_BITS_PER_BYTE 8
8002 
8003 typedef union {
8004     gzFile as_gzFile;
8005     FILE *as_FILE_p;
8006     void *as_ptr;
8007 } syncex_file_u;
8008 
8009 struct synctex_updater_t {
8010     syncex_file_u file;
8011     synctex_print_f print;
8012     synctex_close_f close;
8013     int length; /*  the number of chars appended */
8014 };
8015 
8016 static int _synctex_updater_print(synctex_updater_p updater, const char *format, ...) SYNCTEX_PRINTF_FORMAT(2, 3);
8017 static int _synctex_updater_print(synctex_updater_p updater, const char *format, ...)
8018 {
8019     int result = 0;
8020     if (updater) {
8021         va_list va;
8022         va_start(va, format);
8023         result = vfprintf(updater->file.as_FILE_p, format, va);
8024         va_end(va);
8025     }
8026     return result;
8027 }
8028 #if defined(_MSC_VER) || defined(__MINGW32__)
8029 #include <stdio.h>
8030 #include <stdlib.h>
8031 
8032 static int vasprintf(char **ret, const char *format, va_list ap)
8033 {
8034     int len;
8035     len = _vsnprintf(NULL, 0, format, ap);
8036     if (len < 0)
8037         return -1;
8038     *ret = malloc(len + 1);
8039     if (!*ret)
8040         return -1;
8041     _vsnprintf(*ret, len + 1, format, ap);
8042     (*ret)[len] = '\0';
8043     return len;
8044 }
8045 
8046 #endif
8047 
8048 /**
8049  *  gzvprintf is not available until OSX 10.10
8050  */
8051 static int _synctex_updater_print_gz(synctex_updater_p updater, const char *format, ...) SYNCTEX_PRINTF_FORMAT(2, 3);
8052 static int _synctex_updater_print_gz(synctex_updater_p updater, const char *format, ...)
8053 {
8054     int result = 0;
8055     if (updater) {
8056         char *buffer;
8057         va_list va;
8058         va_start(va, format);
8059         if (vasprintf(&buffer, format, va) < 0) {
8060             _synctex_error("Out of memory...");
8061         } else if ((result = (int)strlen(buffer))) {
8062             result = gzwrite(updater->file.as_gzFile, buffer, (unsigned)result);
8063         }
8064         va_end(va);
8065         free(buffer);
8066     }
8067     return result;
8068 }
8069 
8070 static void _synctex_updater_close(synctex_updater_p updater)
8071 {
8072     if (updater) {
8073         fclose(updater->file.as_FILE_p);
8074     }
8075 }
8076 
8077 static void _synctex_updater_close_gz(synctex_updater_p updater)
8078 {
8079     if (updater) {
8080         gzclose(updater->file.as_gzFile);
8081     }
8082 }
8083 
8084 synctex_updater_p synctex_updater_new_with_output_file(const char *output, const char *build_directory)
8085 {
8086     synctex_updater_p updater = NULL;
8087     const char *mode = NULL;
8088     synctex_open_s open;
8089     /*  prepare the updater, the memory is the only one dynamically allocated */
8090     updater = (synctex_updater_p)_synctex_malloc(sizeof(synctex_updater_s));
8091     if (NULL == updater) {
8092         _synctex_error("!  synctex_updater_new_with_file: malloc problem");
8093         return NULL;
8094     }
8095     open = _synctex_open_v2(output, build_directory, 0, synctex_ADD_QUOTES);
8096     if (open.status < SYNCTEX_STATUS_OK) {
8097         open = _synctex_open_v2(output, build_directory, 0, synctex_DONT_ADD_QUOTES);
8098         if (open.status < SYNCTEX_STATUS_OK) {
8099         return_on_error:
8100             _synctex_free(updater);
8101             return updater = NULL;
8102         }
8103     }
8104     /*  OK, the file exists, we close it and reopen it with the correct mode.
8105      *  The receiver is now the owner of the "synctex" variable. */
8106     gzclose(open.file);
8107     updater->file.as_ptr = NULL;
8108     mode = _synctex_get_io_mode_name(open.io_mode | synctex_io_append_mask); /* either "a" or "ab", depending on the file extension */
8109     if (open.io_mode & synctex_io_gz_mask) {
8110         if (NULL == (updater->file.as_FILE_p = fopen(open.synctex, mode))) {
8111         no_write_error:
8112             _synctex_error("!  synctex_updater_new_with_file: Can't append to %s", open.synctex);
8113             free(open.synctex);
8114             goto return_on_error;
8115         }
8116         updater->print = &_synctex_updater_print;
8117         updater->close = &_synctex_updater_close;
8118     } else {
8119         if (NULL == (updater->file.as_gzFile = gzopen(open.synctex, mode))) {
8120             goto no_write_error;
8121         }
8122         updater->print = &_synctex_updater_print_gz;
8123         updater->close = &_synctex_updater_close_gz;
8124     }
8125     printf("SyncTeX: updating %s...", open.synctex);
8126     _synctex_free(open.synctex);
8127     return updater;
8128 }
8129 
8130 void synctex_updater_append_magnification(synctex_updater_p updater, char *magnification)
8131 {
8132     if (NULL == updater) {
8133         return;
8134     }
8135     if (magnification && strlen(magnification)) {
8136         updater->length += updater->print(updater, "Magnification:%s\n", magnification);
8137     }
8138 }
8139 
8140 void synctex_updater_append_x_offset(synctex_updater_p updater, char *x_offset)
8141 {
8142     if (NULL == updater) {
8143         return;
8144     }
8145     if (x_offset && strlen(x_offset)) {
8146         updater->length += updater->print(updater, "X Offset:%s\n", x_offset);
8147     }
8148 }
8149 
8150 void synctex_updater_append_y_offset(synctex_updater_p updater, char *y_offset)
8151 {
8152     if (NULL == updater) {
8153         return;
8154     }
8155     if (y_offset && strlen(y_offset)) {
8156         updater->length += updater->print(updater, "Y Offset:%s\n", y_offset);
8157     }
8158 }
8159 
8160 void synctex_updater_free(synctex_updater_p updater)
8161 {
8162     if (NULL == updater) {
8163         return;
8164     }
8165     if (updater->length > 0) {
8166         updater->print(updater, "!%i\n", updater->length);
8167     }
8168     updater->close(updater);
8169     _synctex_free(updater);
8170     printf("... done.\n");
8171     return;
8172 }
8173 #endif
8174 
8175 #if defined(SYNCTEX_TESTING)
8176 #ifdef SYNCTEX_NOTHING
8177 #pragma mark -
8178 #pragma mark Testers
8179 #endif
8180 static int _synctex_input_copy_name(synctex_node_p input, char *name)
8181 {
8182     char *copy = _synctex_malloc(strlen(name) + 1);
8183     memcpy(copy, name, strlen(name) + 1);
8184     _synctex_data_set_name(input, copy);
8185     return 0;
8186 }
8187 int synctex_test_setup_scanner_sheets_421(synctex_scanner_p scanner)
8188 {
8189     int TC = 0;
8190     synctex_node_p sheet = synctex_node_new(scanner, synctex_node_type_sheet);
8191     _synctex_data_set_page(sheet, 4);
8192     SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet) == 4, "");
8193     synctex_node_free(scanner->sheet);
8194     scanner->sheet = sheet;
8195     sheet = synctex_node_new(scanner, synctex_node_type_sheet);
8196     _synctex_data_set_page(sheet, 2);
8197     SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet) == 2, "");
8198     __synctex_tree_set_sibling(sheet, scanner->sheet);
8199     scanner->sheet = sheet;
8200     sheet = synctex_node_new(scanner, synctex_node_type_sheet);
8201     _synctex_data_set_page(sheet, 1);
8202     SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet) == 1, "");
8203     __synctex_tree_set_sibling(sheet, scanner->sheet);
8204     scanner->sheet = sheet;
8205     return TC;
8206 }
8207 int synctex_test_input(synctex_scanner_p scanner)
8208 {
8209     int TC = 0;
8210     synctex_node_p input = synctex_node_new(scanner, synctex_node_type_input);
8211     _synctex_data_set_tag(input, 421);
8212     SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input) == 421, "");
8213     _synctex_data_set_tag(input, 124);
8214     SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input) == 124, "");
8215     _synctex_data_set_line(input, 421);
8216     SYNCTEX_TEST_BODY(TC, _synctex_data_line(input) == 421, "");
8217     _synctex_data_set_line(input, 214);
8218     SYNCTEX_TEST_BODY(TC, _synctex_data_line(input) == 214, "");
8219     _synctex_data_set_line(input, 214);
8220     SYNCTEX_TEST_BODY(TC, _synctex_data_line(input) == 214, "");
8221     _synctex_input_copy_name(input, "214");
8222     SYNCTEX_TEST_BODY(TC, 0 == memcmp(_synctex_data_name(input), "214", 4), "");
8223     _synctex_input_copy_name(input, "421421");
8224 
8225     SYNCTEX_TEST_BODY(TC, 0 == memcmp(_synctex_data_name(input), "421421", 4), "");
8226     synctex_node_free(input);
8227     return TC;
8228 }
8229 int synctex_test_proxy(synctex_scanner_p scanner)
8230 {
8231     int TC = 0;
8232     synctex_node_p proxy = synctex_node_new(scanner, synctex_node_type_proxy);
8233     synctex_node_p target = synctex_node_new(scanner, synctex_node_type_rule);
8234     _synctex_tree_set_target(proxy, target);
8235     _synctex_data_set_tag(target, 421);
8236     SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target) == 421, "");
8237     SYNCTEX_TEST_BODY(TC, synctex_node_tag(target) == 421, "");
8238     SYNCTEX_TEST_BODY(TC, synctex_node_tag(proxy) == 421, "");
8239     synctex_node_free(proxy);
8240     synctex_node_free(target);
8241     return TC;
8242 }
8243 int synctex_test_handle(synctex_scanner_p scanner)
8244 {
8245     int TC = 0;
8246     synctex_node_p handle = synctex_node_new(scanner, synctex_node_type_handle);
8247     synctex_node_p proxy = synctex_node_new(scanner, synctex_node_type_proxy);
8248     synctex_node_p target = synctex_node_new(scanner, synctex_node_type_rule);
8249     _synctex_tree_set_target(handle, target);
8250     _synctex_data_set_tag(target, 421);
8251     SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target) == 421, "");
8252     SYNCTEX_TEST_BODY(TC, synctex_node_tag(target) == 421, "");
8253     SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle) == 421, "");
8254     _synctex_data_set_line(target, 214);
8255     SYNCTEX_TEST_BODY(TC, _synctex_data_line(target) == 214, "");
8256     SYNCTEX_TEST_BODY(TC, synctex_node_line(target) == 214, "");
8257     SYNCTEX_TEST_BODY(TC, synctex_node_line(handle) == 214, "");
8258     _synctex_data_set_column(target, 142);
8259     SYNCTEX_TEST_BODY(TC, _synctex_data_column(target) == 142, "");
8260     SYNCTEX_TEST_BODY(TC, synctex_node_column(target) == 142, "");
8261     SYNCTEX_TEST_BODY(TC, synctex_node_column(handle) == 142, "");
8262     _synctex_tree_set_target(proxy, target);
8263     _synctex_tree_set_target(handle, proxy);
8264     _synctex_data_set_tag(target, 412);
8265     SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target) == 412, "");
8266     SYNCTEX_TEST_BODY(TC, synctex_node_tag(target) == 412, "");
8267     SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle) == 412, "");
8268     _synctex_data_set_line(target, 124);
8269     SYNCTEX_TEST_BODY(TC, _synctex_data_line(target) == 124, "");
8270     SYNCTEX_TEST_BODY(TC, synctex_node_line(target) == 124, "");
8271     SYNCTEX_TEST_BODY(TC, synctex_node_line(handle) == 124, "");
8272     _synctex_data_set_column(target, 241);
8273     SYNCTEX_TEST_BODY(TC, _synctex_data_column(target) == 241, "");
8274     SYNCTEX_TEST_BODY(TC, synctex_node_column(target) == 241, "");
8275     SYNCTEX_TEST_BODY(TC, synctex_node_column(handle) == 241, "");
8276     synctex_node_free(handle);
8277     synctex_node_free(proxy);
8278     synctex_node_free(target);
8279     return TC;
8280 }
8281 int synctex_test_setup_scanner_input(synctex_scanner_p scanner)
8282 {
8283     int TC = 0;
8284     synctex_node_p input = synctex_node_new(scanner, synctex_node_type_input);
8285     _synctex_data_set_tag(input, 4);
8286     _synctex_input_copy_name(input, "21");
8287     _synctex_data_set_line(input, 421);
8288     synctex_node_free(scanner->input);
8289     scanner->input = input;
8290     SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input) == 4, "");
8291     SYNCTEX_TEST_BODY(TC, strcmp(_synctex_data_name(input), "21") == 0, "");
8292     SYNCTEX_TEST_BODY(TC, _synctex_data_line(input) == 421, "");
8293     return TC;
8294 }
8295 int synctex_test_setup_nodes(synctex_scanner_p scanner, synctex_node_r nodes)
8296 {
8297     int TC = 0;
8298     int n;
8299     for (n = 0; n < synctex_node_number_of_types; ++n) {
8300         nodes[n] = synctex_node_new(scanner, n);
8301         SYNCTEX_TEST_BODY(TC, nodes[n] != NULL, "");
8302     }
8303     return TC;
8304 }
8305 int synctex_test_teardown_nodes(synctex_scanner_p scanner, synctex_node_r nodes)
8306 {
8307     int n;
8308     for (n = 0; n < synctex_node_number_of_types; ++n) {
8309         synctex_node_free(nodes[n]);
8310         nodes[n] = NULL;
8311     }
8312     return 1;
8313 }
8314 int synctex_test_tree(synctex_scanner_p scanner)
8315 {
8316     int TC = 0;
8317     synctex_node_p nodes1[synctex_node_number_of_types];
8318     synctex_node_p nodes2[synctex_node_number_of_types];
8319     synctex_node_p nodes3[synctex_node_number_of_types];
8320     int i, j;
8321     TC += synctex_test_setup_nodes(scanner, nodes1);
8322     TC += synctex_test_setup_nodes(scanner, nodes2);
8323     TC += synctex_test_setup_nodes(scanner, nodes3);
8324     /*  Every node has a sibling */
8325     for (i = 0; i < synctex_node_number_of_types; ++i) {
8326         for (j = 0; j < synctex_node_number_of_types; ++j) {
8327             _synctex_tree_set_sibling(nodes1[i], nodes2[i]);
8328             SYNCTEX_TEST_BODY(TC, nodes2[i] == synctex_node_sibling(nodes1[i]), "");
8329         }
8330     }
8331     synctex_test_teardown_nodes(scanner, nodes3);
8332     synctex_test_teardown_nodes(scanner, nodes2);
8333     synctex_test_teardown_nodes(scanner, nodes1);
8334     return TC;
8335 }
8336 int synctex_test_page(synctex_scanner_p scanner)
8337 {
8338     int TC = synctex_test_setup_scanner_sheets_421(scanner);
8339     synctex_node_p sheet = scanner->sheet;
8340     synctex_node_p node = synctex_node_new(scanner, synctex_node_type_rule);
8341     _synctex_data_set_tag(node, 4);
8342     _synctex_data_set_line(node, 21);
8343     synctex_node_free(_synctex_node_set_child(sheet, node));
8344     SYNCTEX_TEST_BODY(TC, synctex_node_page(node) == synctex_node_page(sheet), "");
8345     return TC;
8346 }
8347 int synctex_test_display_query(synctex_scanner_p scanner)
8348 {
8349     int TC = synctex_test_setup_scanner_sheets_421(scanner);
8350     synctex_node_p sheet = scanner->sheet;
8351     synctex_node_p node = synctex_node_new(scanner, synctex_node_type_rule);
8352     _synctex_data_set_tag(node, 4);
8353     _synctex_data_set_line(node, 21);
8354     synctex_node_free(_synctex_node_set_child(sheet, node));
8355     SYNCTEX_TEST_BODY(TC, node == synctex_node_child(sheet), "");
8356     __synctex_node_make_friend_tlc(node);
8357     SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25) == node, "");
8358     sheet = __synctex_tree_sibling(sheet);
8359     node = synctex_node_new(scanner, synctex_node_type_rule);
8360     _synctex_data_set_tag(node, 4);
8361     _synctex_data_set_line(node, 21);
8362     synctex_node_free(_synctex_node_set_child(sheet, node));
8363     SYNCTEX_TEST_BODY(TC, node == synctex_node_child(sheet), "");
8364     __synctex_node_make_friend_tlc(node);
8365     SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25) == node, "");
8366     sheet = __synctex_tree_sibling(sheet);
8367     node = synctex_node_new(scanner, synctex_node_type_rule);
8368     _synctex_data_set_tag(node, 4);
8369     _synctex_data_set_line(node, 21);
8370     synctex_node_free(_synctex_node_set_child(sheet, node));
8371     SYNCTEX_TEST_BODY(TC, node == synctex_node_child(sheet), "");
8372     __synctex_node_make_friend_tlc(node);
8373     SYNCTEX_TEST_BODY(TC, (_synctex_scanner_friend(scanner, 25) == node), "");
8374     synctex_test_setup_scanner_input(scanner);
8375     scanner->flags.has_parsed = synctex_YES;
8376 #if 1
8377     SYNCTEX_TEST_BODY(TC, (synctex_display_query(scanner, "21", 21, 4, -1) == 3), "");
8378 #endif
8379     return TC;
8380 }
8381 typedef struct {
8382     int s;      /* status */
8383     char n[25]; /* name */
8384 } synctex_test_sn_s;
8385 
8386 synctex_test_sn_s synctex_test_tmp_sn(char *content)
8387 {
8388     synctex_test_sn_s sn = {0, "/tmp/test.XXXXXX.synctex"};
8389     FILE *sfp;
8390     int fd = mkstemps(sn.n, 8);
8391     if (fd < 0) {
8392         fprintf(stderr, "%s: %s\n", sn.n, strerror(errno));
8393         sn.s = -1;
8394         return sn;
8395     }
8396     if ((sfp = fdopen(fd, "w+")) == NULL) {
8397         unlink(sn.n);
8398         close(fd);
8399         fprintf(stderr, "%s: %s\n", sn.n, strerror(errno));
8400         sn.s = -2;
8401         return sn;
8402     }
8403     sn.s = fputs(content, sfp);
8404     printf("temp:%s\n%i\n", sn.n, sn.s);
8405     fclose(sfp);
8406     if (sn.s == 0) {
8407         sn.s = -2;
8408         unlink(sn.n);
8409     }
8410     return sn;
8411 }
8412 int synctex_test_sheet_1()
8413 {
8414     int TC = 0;
8415     char *content =
8416         "SyncTeX Version:1  \n"           /*00-19*/
8417         "Input:1:./1.tex    \n"           /*20-39*/
8418         "Output:pdf         \n"           /*40-59*/
8419         "Magnification:100000000      \n" /*60-89*/
8420         "Unit:1   \n"                     /*90-99*/
8421         "X Offset:0         \n"           /*00-19*/
8422         "Y Offset:0         \n"           /*20-39*/
8423         "Content: \n"                     /*40-49*/
8424         "{1       \n"                     /*50-59*/
8425         "[1,10:20,350:330,330,0       \n" /*60-89*/
8426         "]        \n"                     /*90-99*/
8427         "}        \n"                     /*00-09*/
8428         "Postamble:\n";
8429     synctex_test_sn_s sn = synctex_test_tmp_sn(content);
8430     if (sn.s > 0) {
8431         synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES);
8432         synctex_node_p node = synctex_scanner_handle(scanner);
8433         printf("Created nodes:\n");
8434         while (node) {
8435             printf("%s\n", _synctex_node_abstract(node));
8436             node = synctex_node_next(node);
8437         }
8438         synctex_scanner_free(scanner);
8439         unlink(sn.n);
8440     } else {
8441         ++TC;
8442     }
8443     return TC;
8444 }
8445 int synctex_test_sheet_2()
8446 {
8447     int TC = 0;
8448     char *content =
8449         "SyncTeX Version:1  \n"           /*00-19*/
8450         "Input:1:./1.tex    \n"           /*20-39*/
8451         "Output:pdf         \n"           /*40-59*/
8452         "Magnification:100000000      \n" /*60-89*/
8453         "Unit:1   \n"                     /*90-99*/
8454         "X Offset:0         \n"           /*00-19*/
8455         "Y Offset:0         \n"           /*20-39*/
8456         "Content: \n"                     /*40-49*/
8457         "{1       \n"                     /*50-59*/
8458         "(1,10:20,350:330,330,0       \n" /*60-89*/
8459         ")        \n"                     /*90-99*/
8460         "}        \n"                     /*00-09*/
8461         "Postamble:\n";
8462     synctex_test_sn_s sn = synctex_test_tmp_sn(content);
8463     if (sn.s > 0) {
8464         synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES);
8465         synctex_node_p node = synctex_scanner_handle(scanner);
8466         printf("Created nodes:\n");
8467         while (node) {
8468             printf("%s\n", _synctex_node_abstract(node));
8469             node = _synctex_node_next(node);
8470         }
8471         TC += synctex_scanner_free(scanner);
8472         unlink(sn.n);
8473     } else {
8474         ++TC;
8475     }
8476     return TC;
8477 }
8478 int synctex_test_charindex()
8479 {
8480     int TC = 0;
8481     char *content =
8482         "SyncTeX Version:1  \n"           /*00-19*/
8483         "Input:1:./1.tex    \n"           /*20-39*/
8484         "Output:pdf         \n"           /*40-59*/
8485         "Magnification:100000000      \n" /*60-89*/
8486         "Unit:1   \n"                     /*90-99*/
8487         "X Offset:0         \n"           /*00-19*/
8488         "Y Offset:0         \n"           /*20-39*/
8489         "Content: \n"                     /*40-49*/
8490         "{1       \n"                     /*50-59*/
8491         "[1,10:20,350:330,330,0       \n" /*60-89*/
8492         "(1,58:20,100:250,10,5        \n" /*90-119*/
8493         "f1000:50,100       \n"           /*20-39*/
8494         ")        \n"                     /*40-49*/
8495         "]        \n"                     /*50-59*/
8496         "}        \n"                     /*60-69*/
8497         "Postamble:\n";
8498     synctex_test_sn_s sn = synctex_test_tmp_sn(content);
8499     if (sn.s > 0) {
8500         synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES);
8501         synctex_node_p node = synctex_scanner_handle(scanner);
8502         printf("Created nodes:\n");
8503         while (node) {
8504             printf("%s\n", _synctex_node_abstract(node));
8505             node = synctex_node_next(node);
8506         }
8507         TC += synctex_scanner_free(scanner);
8508         unlink(sn.n);
8509     } else {
8510         ++TC;
8511     }
8512     return TC;
8513 }
8514 int synctex_test_form()
8515 {
8516     int TC = 0;
8517     char *content =
8518         "SyncTeX Version:1  \n"           /*00-19*/
8519         "Input:1:./1.tex    \n"           /*20-39*/
8520         "Output:pdf         \n"           /*40-59*/
8521         "Magnification:100000000      \n" /*60-89*/
8522         "Unit:1   \n"                     /*90-99*/
8523         "X Offset:0         \n"           /*00-19*/
8524         "Y Offset:0         \n"           /*20-39*/
8525         "Content: \n"                     /*40-49*/
8526         "{1       \n"                     /*50-59*/
8527         "[1,10:20,350:330,330,0       \n" /*60-89*/
8528         "(1,58:20,100:250,10,5        \n" /*90-119*/
8529         "f1000:50,100       \n"           /*20-39*/
8530         ")        \n"                     /*40-49*/
8531         "]        \n"                     /*50-59*/
8532         "}        \n"                     /*60-69*/
8533         "<1000    \n"                     /*70-79*/
8534         "(1,63:0,0:100,8,3  \n"           /*80-99*/
8535         ")        \n"                     /*00-09*/
8536         ">        \n"                     /*10-19*/
8537         "Postamble:\n";
8538     synctex_test_sn_s sn = synctex_test_tmp_sn(content);
8539     if (sn.s > 0) {
8540         synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES);
8541         synctex_node_p node = synctex_scanner_handle(scanner);
8542         while (node) {
8543             printf("%s\n", _synctex_node_abstract(node));
8544             node = _synctex_node_next(node);
8545         }
8546         TC += synctex_scanner_free(scanner);
8547         unlink(sn.n);
8548     } else {
8549         ++TC;
8550     }
8551     return TC;
8552 }
8553 #endif