~adamreichold/qpdfview/trunk

« back to all changes in this revision

Viewing changes to synctex/synctex_parser.c

  • Committer: Adam Reichold
  • Date: 2020-07-29 07:15:12 UTC
  • Revision ID: adam.reichold@t-online.de-20200729071512-4ljoi4b4rhj3i2ya
Fix build of Fitz plug-in using MuPDF v1.17.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr
3
 
 
4
 
 This file is part of the __SyncTeX__ package.
5
 
 
6
 
 [//]: # (Latest Revision: Sun Oct 15 15:09:55 UTC 2017)
7
 
 [//]: # (Version: 1.21)
8
 
 
9
 
 See `synctex_parser_readme.md` for more details
10
 
 
11
 
 ## License
12
 
 
13
 
 Permission is hereby granted, free of charge, to any person
14
 
 obtaining a copy of this software and associated documentation
15
 
 files (the "Software"), to deal in the Software without
16
 
 restriction, including without limitation the rights to use,
17
 
 copy, modify, merge, publish, distribute, sublicense, and/or sell
18
 
 copies of the Software, and to permit persons to whom the
19
 
 Software is furnished to do so, subject to the following
20
 
 conditions:
21
 
 
22
 
 The above copyright notice and this permission notice shall be
23
 
 included in all copies or substantial portions of the Software.
24
 
 
25
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26
 
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
27
 
 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28
 
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
29
 
 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
30
 
 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31
 
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
32
 
 OTHER DEALINGS IN THE SOFTWARE
33
 
 
34
 
 Except as contained in this notice, the name of the copyright holder
35
 
 shall not be used in advertising or otherwise to promote the sale,
36
 
 use or other dealings in this Software without prior written
37
 
 authorization from the copyright holder.
38
 
 
39
 
 Acknowledgments:
40
 
 ----------------
41
 
 The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh,
42
 
 and significant help from XeTeX developer Jonathan Kew
43
 
 
44
 
 Nota Bene:
45
 
 ----------
46
 
 If you include or use a significant part of the synctex package into a software,
47
 
 I would appreciate to be listed as contributor and see "SyncTeX" highlighted.
48
 
 
49
 
 */
 
1
/* 
 
2
Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr
 
3
 
 
4
This file is part of the SyncTeX package.
 
5
 
 
6
Latest Revision: Tue Jun 14 08:23:30 UTC 2011
 
7
 
 
8
Version: 1.18
 
9
 
 
10
See synctex_parser_readme.txt for more details
 
11
 
 
12
License:
 
13
--------
 
14
Permission is hereby granted, free of charge, to any person
 
15
obtaining a copy of this software and associated documentation
 
16
files (the "Software"), to deal in the Software without
 
17
restriction, including without limitation the rights to use,
 
18
copy, modify, merge, publish, distribute, sublicense, and/or sell
 
19
copies of the Software, and to permit persons to whom the
 
20
Software is furnished to do so, subject to the following
 
21
conditions:
 
22
 
 
23
The above copyright notice and this permission notice shall be
 
24
included in all copies or substantial portions of the Software.
 
25
 
 
26
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
27
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 
28
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
29
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 
30
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
31
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
32
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 
33
OTHER DEALINGS IN THE SOFTWARE
 
34
 
 
35
Except as contained in this notice, the name of the copyright holder  
 
36
shall not be used in advertising or otherwise to promote the sale,  
 
37
use or other dealings in this Software without prior written  
 
38
authorization from the copyright holder.
 
39
 
 
40
Acknowledgments:
 
41
----------------
 
42
The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh,
 
43
and significant help from XeTeX developer Jonathan Kew
 
44
 
 
45
Nota Bene:
 
46
----------
 
47
If you include or use a significant part of the synctex package into a software,
 
48
I would appreciate to be listed as contributor and see "SyncTeX" highlighted.
 
49
 
 
50
Version 1
 
51
Thu Jun 19 09:39:21 UTC 2008
 
52
 
 
53
*/
50
54
 
51
55
/*  We assume that high level application like pdf viewers will want
52
56
 *  to embed this code as is. We assume that they also have locale.h and setlocale.
55
59
 *  In particular, the HAVE_LOCALE_H and HAVE_SETLOCALE macros should be properly defined.
56
60
 *  With this design, you should not need to edit this file. */
57
61
 
58
 
/**
59
 
 *  \file synctex_parser.c
60
 
 *  \brief SyncTeX file parser and controller.
61
 
 *  - author: Jérôme LAURENS
62
 
 *  \version 1.21
63
 
 *  \date Sun Oct 15 15:09:55 UTC 2017
64
 
 *
65
 
 *  Reads and parse *.synctex[.gz] files,
66
 
 *  performs edit and display queries.
67
 
 *
68
 
 *  See
69
 
 *  - synctex_scanner_new_with_output_file
70
 
 *  - synctex_scanner_parse
71
 
 *  - synctex_scanner_free
72
 
 *  - synctex_display_query
73
 
 *  - synctex_edit_query
74
 
 *  - synctex_scanner_next_result
75
 
 *  - synctex_scanner_reset_result
76
 
 *
77
 
 *  The data is organized in a graph with multiple entries.
78
 
 *  The root object is a scanner, it is created with the contents on a synctex file.
79
 
 *  Each node of the tree is a synctex_node_t object.
80
 
 *  There are 3 subtrees, two of them sharing the same leaves.
81
 
 *  The first tree is the list of input records, where input file names are associated with tags.
82
 
 *  The second tree is the box tree as given by TeX when shipping pages out.
83
 
 *  First level objects are sheets and forms, containing boxes, glues, kerns...
84
 
 *  The third tree allows to browse leaves according to tag and line.
85
 
 */
86
 
/* Declare _GNU_SOURCE for accessing vasprintf. For MSC compiler, vasprintf is
87
 
 * defined in this file
88
 
 */
89
 
#define _GNU_SOURCE
90
 
 
91
62
#   if defined(SYNCTEX_USE_LOCAL_HEADER)
92
63
#       include "synctex_parser_local.h"
93
64
#   else
94
65
#       define HAVE_LOCALE_H 1
95
66
#       define HAVE_SETLOCALE 1
96
 
#       if defined(_MSC_VER)
 
67
#       if defined(_MSC_VER) 
97
68
#          define SYNCTEX_INLINE __inline
98
69
#       else
99
70
#          define SYNCTEX_INLINE inline
101
72
#   endif
102
73
 
103
74
#include <stdlib.h>
104
 
#include <stdarg.h>
105
75
#include <stdio.h>
106
76
#include <string.h>
107
77
#include <errno.h>
111
81
#include <locale.h>
112
82
#endif
113
83
 
114
 
/* Mark unused parameters, so that there will be no compile warnings. */
115
 
#ifdef __DARWIN_UNIX03
116
 
#   define SYNCTEX_UNUSED(x) SYNCTEX_PRAGMA(unused(x))
117
 
#   define SYNCTEX_PRAGMA(x) _Pragma ( #x )
118
 
#else
119
 
#   define SYNCTEX_UNUSED(x) (void)(x);
120
 
#endif
121
 
 
122
 
#include "synctex_parser_advanced.h"
123
 
 
124
 
SYNCTEX_INLINE static int _synctex_abs(int x) {
125
 
    return x>0? x: -x;
126
 
}
 
84
/*  The data is organized in a graph with multiple entries.
 
85
 *  The root object is a scanner, it is created with the contents on a synctex file.
 
86
 *  Each leaf of the tree is a synctex_node_t object.
 
87
 *  There are 3 subtrees, two of them sharing the same leaves.
 
88
 *  The first tree is the list of input records, where input file names are associated with tags.
 
89
 *  The second tree is the box tree as given by TeX when shipping pages out.
 
90
 *  First level objects are sheets, containing boxes, glues, kerns...
 
91
 *  The third tree allows to browse leaves according to tag and line.
 
92
 */
 
93
 
 
94
#include "synctex_parser.h"
 
95
#include "synctex_parser_utils.h"
 
96
 
127
97
/*  These are the possible extensions of the synctex file */
128
98
const char * synctex_suffix = ".synctex";
129
99
const char * synctex_suffix_gz = ".gz";
130
100
 
131
 
typedef synctex_node_p(*synctex_node_new_f)(synctex_scanner_p);
132
 
typedef void(*synctex_node_fld_f)(synctex_node_p);
133
 
typedef char *(*synctex_node_str_f)(synctex_node_p);
134
 
 
135
 
/**
136
 
 *  Pseudo class.
137
 
 *  - author: J. Laurens
138
 
 *
139
 
 *  Each nodes has a class, it is therefore called an object.
140
 
 *  Each class has a unique scanner.
141
 
 *  Each class has a type which is a unique identifier.
142
 
 *  The class points to various methods,
143
 
 *  each of them vary amongst objects.
144
 
 *  Each class has a data model which stores node's attributes.
145
 
 *  Each class has an tree model which stores children and parent.
146
 
 *  Inspectors give access to data and tree elements.
147
 
 */
148
 
 
149
 
/*  8 fields + size: spcflnat */
150
 
typedef struct synctex_tree_model_t {
151
 
    int sibling;
152
 
    int parent;
153
 
    int child;
154
 
    int friend;
155
 
    int last;
156
 
    int next_hbox;
157
 
    int arg_sibling;
158
 
    int target;
159
 
    int size;
160
 
} synctex_tree_model_s;
161
 
typedef const synctex_tree_model_s * synctex_tree_model_p;
162
 
 
163
 
typedef struct synctex_data_model_t {
164
 
    int tag;
165
 
    int line;
166
 
    int column;
167
 
    int h;
168
 
    int v;
169
 
    int width;
170
 
    int height;
171
 
    int depth;
172
 
    int mean_line;
173
 
    int weight;
174
 
    int h_V;
175
 
    int v_V;
176
 
    int width_V;
177
 
    int height_V;
178
 
    int depth_V;
179
 
    int name;
180
 
    int page;
181
 
    int size;
182
 
} synctex_data_model_s;
183
 
 
184
 
typedef const synctex_data_model_s * synctex_data_model_p;
185
 
 
186
 
typedef int (*synctex_int_getter_f)(synctex_node_p);
187
 
typedef struct synctex_tlcpector_t {
188
 
    synctex_int_getter_f tag;
189
 
    synctex_int_getter_f line;
190
 
    synctex_int_getter_f column;
191
 
} synctex_tlcpector_s;
192
 
typedef const synctex_tlcpector_s * synctex_tlcpector_p;
193
 
static int _synctex_int_none(synctex_node_p node) {
194
 
    SYNCTEX_UNUSED(node)
195
 
    return 0;
196
 
}
197
 
static const synctex_tlcpector_s synctex_tlcpector_none = {
198
 
    &_synctex_int_none, /* tag */
199
 
    &_synctex_int_none, /* line */
200
 
    &_synctex_int_none, /* column */
201
 
};
202
 
 
203
 
typedef struct synctex_inspector_t {
204
 
    synctex_int_getter_f h;
205
 
    synctex_int_getter_f v;
206
 
    synctex_int_getter_f width;
207
 
    synctex_int_getter_f height;
208
 
    synctex_int_getter_f depth;
209
 
} synctex_inspector_s;
210
 
typedef const synctex_inspector_s * synctex_inspector_p;
211
 
static const synctex_inspector_s synctex_inspector_none = {
212
 
    &_synctex_int_none, /* h */
213
 
    &_synctex_int_none, /* v */
214
 
    &_synctex_int_none, /* width */
215
 
    &_synctex_int_none, /* height */
216
 
    &_synctex_int_none, /* depth */
217
 
};
218
 
 
219
 
typedef float (*synctex_float_getter_f)(synctex_node_p);
220
 
typedef struct synctex_vispector_t {
221
 
    synctex_float_getter_f h;
222
 
    synctex_float_getter_f v;
223
 
    synctex_float_getter_f width;
224
 
    synctex_float_getter_f height;
225
 
    synctex_float_getter_f depth;
226
 
} synctex_vispector_s;
227
 
static float _synctex_float_none(synctex_node_p node) {
228
 
    SYNCTEX_UNUSED(node)
229
 
    return 0;
230
 
}
231
 
static const synctex_vispector_s synctex_vispector_none = {
232
 
    &_synctex_float_none, /* h */
233
 
    &_synctex_float_none, /* v */
234
 
    &_synctex_float_none, /* width */
235
 
    &_synctex_float_none, /* height */
236
 
    &_synctex_float_none, /* depth */
237
 
};
238
 
typedef const synctex_vispector_s * synctex_vispector_p;
239
 
 
240
 
struct synctex_class_t {
241
 
    synctex_scanner_p scanner;
242
 
    synctex_node_type_t type;
243
 
    synctex_node_new_f new;
244
 
    synctex_node_fld_f free;
245
 
    synctex_node_fld_f log;
246
 
    synctex_node_fld_f display;
247
 
    synctex_node_str_f abstract;
248
 
    synctex_tree_model_p navigator;
249
 
    synctex_data_model_p modelator;
250
 
    synctex_tlcpector_p tlcpector;
251
 
    synctex_inspector_p inspector;
252
 
    synctex_vispector_p vispector;
253
 
};
254
 
 
255
 
/**
256
 
 *  Nota bene: naming convention.
257
 
 *  For static API, when the name contains "proxy", it applies to proxies.
258
 
 *  When the name contains "noxy", it applies to non proxies only.
259
 
 *  When the name contains "node", well it depends...
260
 
 */
261
 
 
262
 
typedef synctex_node_p synctex_proxy_p;
263
 
typedef synctex_node_p synctex_noxy_p;
264
 
 
265
 
#       ifdef SYNCTEX_NOTHING
266
 
#       pragma mark -
267
 
#       pragma mark Abstract OBJECTS and METHODS
268
 
#   endif
269
 
 
270
 
/**
271
 
 *  \def SYNCTEX_MSG_SEND
272
 
 *  \brief Takes care of sending the given message if possible.
273
 
 *  - parameter NODE: of type synctex_node_p
274
 
 *  - parameter SELECTOR: one of the class_ pointer properties
275
 
 */
276
 
#   define SYNCTEX_MSG_SEND(NODE,SELECTOR) do {\
277
 
    synctex_node_p N__ = NODE;\
278
 
    if (N__ && N__->class_->SELECTOR) {\
279
 
        (*(N__->class_->SELECTOR))(N__);\
280
 
    }\
281
 
} while (synctex_NO)
282
 
 
283
 
/**
284
 
 *  Free the given node by sending the free message.
285
 
 *  - parameter NODE: of type synctex_node_p
286
 
 */
287
 
static void synctex_node_free(synctex_node_p node) {
288
 
    SYNCTEX_MSG_SEND(node,free);
289
 
}
290
 
#   if defined(SYNCTEX_TESTING)
291
 
#       if !defined(SYNCTEX_USE_HANDLE)
292
 
#           define SYNCTEX_USE_HANDLE 1
293
 
#       endif
294
 
#       if !defined(SYNCTEX_USE_CHARINDEX)
295
 
#           define SYNCTEX_USE_CHARINDEX 1
296
 
#       endif
297
 
#   endif
298
 
SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target);
299
 
#   if defined(SYNCTEX_USE_HANDLE)
300
 
#       define SYNCTEX_SCANNER_FREE_HANDLE(SCANR) \
301
 
__synctex_scanner_free_handle(SCANR)
302
 
#       define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT) \
303
 
__synctex_scanner_remove_handle_to(WHAT)
304
 
#       define SYNCTEX_REGISTER_HANDLE_TO(NODE) \
305
 
__synctex_scanner_register_handle_to(NODE)
306
 
#   else
307
 
#       define SYNCTEX_SCANNER_FREE_HANDLE(SCANR)
308
 
#       define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT)
309
 
#       define SYNCTEX_REGISTER_HANDLE_TO(NODE)
310
 
#   endif
 
101
/*  each synctex node has a class */
 
102
typedef struct __synctex_class_t _synctex_class_t;
 
103
typedef _synctex_class_t * synctex_class_t;
 
104
 
 
105
 
 
106
/*  synctex_node_t is a pointer to a node
 
107
 *  _synctex_node is the target of the synctex_node_t pointer
 
108
 *  It is a pseudo object oriented program.
 
109
 *  class is a pointer to the class object the node belongs to.
 
110
 *  implementation is meant to contain the private data of the node
 
111
 *  basically, there are 2 kinds of information: navigation information and
 
112
 *  synctex information. Both will depend on the type of the node,
 
113
 *  thus different nodes will have different private data.
 
114
 *  There is no inheritancy overhead.
 
115
 */
 
116
typedef union _synctex_info_t {
 
117
        int    INT;
 
118
        char * PTR;
 
119
} synctex_info_t;
311
120
 
312
121
#   if defined(SYNCTEX_USE_CHARINDEX)
 
122
#       define SYNCTEX_DECLARE_CHARINDEX synctex_charindex_t char_index;
313
123
#       define SYNCTEX_CHARINDEX(NODE) (NODE->char_index)
314
 
#       define SYNCTEX_LINEINDEX(NODE) (NODE->line_index)
315
 
#       define SYNCTEX_PRINT_CHARINDEX_FMT "#%i"
316
 
#       define SYNCTEX_PRINT_CHARINDEX_WHAT ,SYNCTEX_CHARINDEX(node)
317
 
#       define SYNCTEX_PRINT_CHARINDEX \
318
 
            printf(SYNCTEX_PRINT_CHARINDEX_FMT SYNCTEX_PRINT_CHARINDEX_WHAT)
319
 
#       define SYNCTEX_PRINT_LINEINDEX_FMT "L#%i"
320
 
#       define SYNCTEX_PRINT_LINEINDEX_WHAT ,SYNCTEX_LINEINDEX(node)
321
 
#       define SYNCTEX_PRINT_LINEINDEX \
322
 
            printf(SYNCTEX_PRINT_LINEINDEX_FMT SYNCTEX_PRINT_LINEINDEX_WHAT)
323
 
#       define SYNCTEX_PRINT_CHARINDEX_NL \
324
 
            printf(SYNCTEX_PRINT_CHARINDEX_FMT "\n" SYNCTEX_PRINT_CHARINDEX_WHAT)
325
 
#       define SYNCTEX_PRINT_LINEINDEX_NL \
326
 
            printf(SYNCTEX_PRINT_CHARINDEX_FMT "\n"SYNCTEX_PRINT_LINEINDEX_WHAT)
327
 
#       define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION)\
328
 
            NODE->char_index = (synctex_charindex_t)(scanner->reader->charindex_offset+SYNCTEX_CUR-SYNCTEX_START+(CORRECTION)); \
329
 
            NODE->line_index = scanner->reader->line_number;
 
124
#       define SYNCTEX_PRINT_CHARINDEX printf("#%i\n",SYNCTEX_CHARINDEX(node))
 
125
#       define SYNCTEX_DECLARE_CHAR_OFFSET synctex_charindex_t charindex_offset
 
126
#       define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION) NODE->char_index = (synctex_charindex_t)(scanner->charindex_offset+SYNCTEX_CUR-SYNCTEX_START+(CORRECTION));
330
127
#   else
 
128
#       define SYNCTEX_DECLARE_CHARINDEX
331
129
#       define SYNCTEX_CHARINDEX(NODE) 0
332
 
#       define SYNCTEX_LINEINDEX(NODE) 0
333
 
#       define SYNCTEX_PRINT_CHARINDEX_FMT
334
 
#       define SYNCTEX_PRINT_CHARINDEX_WHAT
335
 
#       define SYNCTEX_PRINT_CHARINDEX
336
 
#       define SYNCTEX_PRINT_CHARINDEX
337
 
#       define SYNCTEX_PRINT_LINEINDEX_FMT
338
 
#       define SYNCTEX_PRINT_LINEINDEX_WHAT
339
 
#       define SYNCTEX_PRINT_LINEINDEX
340
 
#       define SYNCTEX_PRINT_CHARINDEX_NL printf("\n")
341
 
#       define SYNCTEX_PRINT_LINEINDEX_NL printf("\n")
 
130
#       define SYNCTEX_PRINT_CHARINDEX printf("\n")
 
131
#       define SYNCTEX_DECLARE_CHAR_OFFSET synctex_charindex_t charindex_offset
342
132
#       define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION)
343
133
#   endif
344
134
 
345
 
/**
346
 
 *  The next macros are used to access the node tree info
347
 
 *  SYNCTEX_DATA(node) points to the first synctex integer or pointer data of node
348
 
 *  SYNCTEX_DATA(node)[index] is the information at index
349
 
 *  for example, the page of a sheet is stored in SYNCTEX_DATA(sheet)[_synctex_data_page_idx]
350
 
 *  - parameter NODE: of type synctex_node_p
351
 
 *  If the name starts with "__", the argument is nonullable
 
135
struct _synctex_node {
 
136
    SYNCTEX_DECLARE_CHARINDEX
 
137
        synctex_class_t class;
 
138
        synctex_info_t * implementation;
 
139
};
 
140
 
 
141
/*  Each node of the tree, except the scanner itself belongs to a class.
 
142
 *  The class object is just a struct declaring the owning scanner
 
143
 *  This is a pointer to the scanner as root of the tree.
 
144
 *  The type is used to identify the kind of node.
 
145
 *  The class declares pointers to a creator and a destructor method.
 
146
 *  The log and display fields are used to log and display the node.
 
147
 *  display will also display the child, sibling and parent sibling.
 
148
 *  parent, child and sibling are used to navigate the tree,
 
149
 *  from TeX box hierarchy point of view.
 
150
 *  The friend field points to a method which allows to navigate from friend to friend.
 
151
 *  A friend is a node with very close tag and line numbers.
 
152
 *  Finally, the info field point to a method giving the private node info offset.
352
153
 */
 
154
 
 
155
typedef synctex_node_t *(*_synctex_node_getter_t)(synctex_node_t);
 
156
typedef synctex_info_t *(*_synctex_info_getter_t)(synctex_node_t);
 
157
 
 
158
struct __synctex_class_t {
 
159
        synctex_scanner_t scanner;
 
160
        int type;
 
161
        synctex_node_t (*new)(synctex_scanner_t scanner);
 
162
        void (*free)(synctex_node_t);
 
163
        void (*log)(synctex_node_t);
 
164
        void (*display)(synctex_node_t);
 
165
        _synctex_node_getter_t parent;
 
166
        _synctex_node_getter_t child;
 
167
        _synctex_node_getter_t sibling;
 
168
        _synctex_node_getter_t friend;
 
169
        _synctex_node_getter_t next_hbox;
 
170
        _synctex_info_getter_t info;
 
171
};
 
172
 
353
173
#       ifdef SYNCTEX_NOTHING
354
174
#       pragma mark -
355
 
#       pragma mark Tree SETGET
 
175
#       pragma mark Abstract OBJECTS and METHODS
356
176
#   endif
357
177
 
358
 
#if SYNCTEX_DEBUG > 1000
359
 
#define SYNCTEX_PARAMETER_ASSERT(WHAT) \
360
 
    do { \
361
 
        if (!(WHAT)) { \
362
 
            printf("! Parameter failure: %s\n",#WHAT); \
363
 
        } \
364
 
    } while (synctex_NO)
365
 
#define DEFINE_SYNCTEX_TREE_HAS(WHAT)\
366
 
static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node) {\
367
 
    if (node) {\
368
 
        if (node->class_->navigator->WHAT>=0) {\
369
 
            return synctex_YES; \
370
 
        } else {\
371
 
            printf("WARNING: NO tree %s for %s\n", #WHAT, synctex_node_isa(node));\
372
 
        }\
373
 
    }\
374
 
    return synctex_NO;\
375
 
}
376
 
#else
377
 
#   define SYNCTEX_PARAMETER_ASSERT(WHAT)
378
 
#   define DEFINE_SYNCTEX_TREE_HAS(WHAT) \
379
 
SYNCTEX_INLINE static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node) {\
380
 
    return (node && (node->class_->navigator->WHAT>=0));\
381
 
}
382
 
#endif
383
 
 
384
 
#   define DEFINE_SYNCTEX_TREE__GET(WHAT) \
385
 
SYNCTEX_INLINE static synctex_node_p __synctex_tree_##WHAT(synctex_non_null_node_p node) {\
386
 
    return node->data[node->class_->navigator->WHAT].as_node;\
387
 
}
388
 
#   define DEFINE_SYNCTEX_TREE_GET(WHAT) \
389
 
DEFINE_SYNCTEX_TREE__GET(WHAT) \
390
 
SYNCTEX_INLINE static synctex_node_p _synctex_tree_##WHAT(synctex_node_p node) {\
391
 
    if (_synctex_tree_has_##WHAT(node)) {\
392
 
        return __synctex_tree_##WHAT(node);\
393
 
    }\
394
 
    return 0;\
395
 
}
396
 
#   define DEFINE_SYNCTEX_TREE__RESET(WHAT) \
397
 
SYNCTEX_INLINE static synctex_node_p __synctex_tree_reset_##WHAT(synctex_non_null_node_p node) {\
398
 
    synctex_node_p old = node->data[node->class_->navigator->WHAT].as_node;\
399
 
    node->data[node->class_->navigator->WHAT].as_node=NULL;\
400
 
    return old;\
401
 
}
402
 
#   define DEFINE_SYNCTEX_TREE_RESET(WHAT) \
403
 
DEFINE_SYNCTEX_TREE__RESET(WHAT) \
404
 
SYNCTEX_INLINE static synctex_node_p _synctex_tree_reset_##WHAT(synctex_node_p node) {\
405
 
        return _synctex_tree_has_##WHAT(node)? \
406
 
            __synctex_tree_reset_##WHAT(node): NULL; \
407
 
}
408
 
#   define DEFINE_SYNCTEX_TREE__SET(WHAT) \
409
 
SYNCTEX_INLINE static synctex_node_p __synctex_tree_set_##WHAT(synctex_non_null_node_p node, synctex_node_p new_value) {\
410
 
    synctex_node_p old = __synctex_tree_##WHAT(node);\
411
 
    node->data[node->class_->navigator->WHAT].as_node=new_value;\
412
 
    return old;\
413
 
}
414
 
#   define DEFINE_SYNCTEX_TREE_SET(WHAT) \
415
 
DEFINE_SYNCTEX_TREE__SET(WHAT) \
416
 
SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_##WHAT(synctex_node_p node, synctex_node_p new_value) {\
417
 
    return _synctex_tree_has_##WHAT(node)?\
418
 
        __synctex_tree_set_##WHAT(node,new_value):NULL;\
419
 
}
420
 
#   define DEFINE_SYNCTEX_TREE__GETSETRESET(WHAT) \
421
 
DEFINE_SYNCTEX_TREE__GET(WHAT) \
422
 
DEFINE_SYNCTEX_TREE__SET(WHAT) \
423
 
DEFINE_SYNCTEX_TREE__RESET(WHAT)
424
 
 
425
 
#   define DEFINE_SYNCTEX_TREE_GETSET(WHAT) \
426
 
DEFINE_SYNCTEX_TREE_HAS(WHAT) \
427
 
DEFINE_SYNCTEX_TREE_GET(WHAT) \
428
 
DEFINE_SYNCTEX_TREE_SET(WHAT)
429
 
 
430
 
#   define DEFINE_SYNCTEX_TREE_GETRESET(WHAT) \
431
 
DEFINE_SYNCTEX_TREE_HAS(WHAT) \
432
 
DEFINE_SYNCTEX_TREE_GET(WHAT) \
433
 
DEFINE_SYNCTEX_TREE_RESET(WHAT)
434
 
 
435
 
#   define DEFINE_SYNCTEX_TREE_GETSETRESET(WHAT) \
436
 
DEFINE_SYNCTEX_TREE_HAS(WHAT) \
437
 
DEFINE_SYNCTEX_TREE_GET(WHAT) \
438
 
DEFINE_SYNCTEX_TREE_SET(WHAT) \
439
 
DEFINE_SYNCTEX_TREE_RESET(WHAT)
440
 
 
441
 
/*
442
 
 *  _synctex_tree_set_... methods return the old value.
443
 
 *  The return value of _synctex_tree_set_child and 
444
 
 *  _synctex_tree_set_sibling must be released somehow.
445
 
 */
446
 
/* The next macro call creates:
447
 
 SYNCTEX_INLINE static synctex_node_p __synctex_tree_sibling(synctex_node_p node)
448
 
 SYNCTEX_INLINE static synctex_node_p __synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_value)
449
 
 SYNCTEX_INLINE static synctex_node_p __synctex_tree_reset_sibling(synctex_node_p node)
450
 
 */
451
 
DEFINE_SYNCTEX_TREE__GETSETRESET(sibling)
452
 
/* The next macro call creates:
453
 
 SYNCTEX_INLINE static synctex_bool_t _synctex_tree_has_parent(synctex_node_p node);
454
 
 SYNCTEX_INLINE static synctex_node_p __synctex_tree_parent(synctex_non_null_node_p node);
455
 
 SYNCTEX_INLINE static synctex_node_p _synctex_tree_parent(synctex_node_p node);
456
 
 SYNCTEX_INLINE static synctex_node_p __synctex_tree_set_parent(synctex_node_p node, synctex_node_p new_value);
457
 
 SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_parent(synctex_node_p node, synctex_node_p new_value);
458
 
 SYNCTEX_INLINE static synctex_node_p __synctex_tree_reset_parent(synctex_node_p node);
459
 
 SYNCTEX_INLINE static synctex_node_p _synctex_tree_reset_parent(synctex_node_p node);
460
 
 */
461
 
DEFINE_SYNCTEX_TREE_GETSETRESET(parent)
462
 
DEFINE_SYNCTEX_TREE_GETSETRESET(child)
463
 
DEFINE_SYNCTEX_TREE_GETSETRESET(friend)
464
 
/* The next macro call creates:
465
 
 SYNCTEX_INLINE static synctex_bool_t _synctex_tree_has_last(synctex_node_p node);
466
 
 SYNCTEX_INLINE static synctex_node_p __synctex_tree_last(synctex_non_null_node_p node);
467
 
 SYNCTEX_INLINE static synctex_node_p _synctex_tree_last(synctex_node_p node);
468
 
 SYNCTEX_INLINE static synctex_node_p __synctex_tree_set_last(synctex_node_p node, synctex_node_p new_value);
469
 
 SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_last(synctex_node_p node, synctex_node_p new_value);
470
 
 */
471
 
DEFINE_SYNCTEX_TREE_GETSET(last)
472
 
DEFINE_SYNCTEX_TREE_GETSET(next_hbox)
473
 
DEFINE_SYNCTEX_TREE_GETSET(arg_sibling)
474
 
DEFINE_SYNCTEX_TREE_GETSETRESET(target)
475
 
 
476
 
#if SYNCTEX_DEBUG>1000
477
 
#   undef SYNCTEX_USE_NODE_COUNT
478
 
#   define SYNCTEX_USE_NODE_COUNT 1
479
 
#endif
480
 
#if SYNCTEX_USE_NODE_COUNT>0
481
 
#   define SYNCTEX_DECLARE_NODE_COUNT int node_count;
482
 
#   define SYNCTEX_INIT_NODE_COUNT \
483
 
        do { node_count = 0; } while(synctex_NO)
484
 
#else
485
 
#   define SYNCTEX_DECLARE_NODE_COUNT
486
 
#   define SYNCTEX_INIT_NODE_COUNT
487
 
#endif
488
 
 
489
 
#if SYNCTEX_USE_NODE_COUNT>10
490
 
#   define SYNCTEX_DID_NEW(N)   _synctex_did_new(N)
491
 
#   define SYNCTEX_WILL_FREE(N) _synctex_will_free(N)
492
 
#else
493
 
#   define SYNCTEX_DID_NEW(N)
494
 
#   define SYNCTEX_WILL_FREE(N)
495
 
#endif
496
 
 
497
 
#define SYNCTEX_HAS_CHILDREN(NODE) (NODE && _synctex_tree_child(NODE))
 
178
/*  These macros are shortcuts
 
179
 *  This macro checks if a message can be sent.
 
180
 */
 
181
#   define SYNCTEX_CAN_PERFORM(NODE,SELECTOR)\
 
182
                (NULL!=((((NODE)->class))->SELECTOR))
 
183
 
 
184
/*  This macro is some kind of objc_msg_send.
 
185
 *  It takes care of sending the proper message if possible.
 
186
 */
 
187
#   define SYNCTEX_MSG_SEND(NODE,SELECTOR) if (NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR)) {\
 
188
                (*((((NODE)->class))->SELECTOR))(NODE);\
 
189
        }
 
190
 
 
191
/*  read only safe getter
 
192
 */
 
193
#   define SYNCTEX_GET(NODE,SELECTOR)((NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR))?SYNCTEX_GETTER(NODE,SELECTOR)[0]:(NULL))
 
194
 
 
195
/*  read/write getter
 
196
 */
 
197
#   define SYNCTEX_GETTER(NODE,SELECTOR)\
 
198
                ((synctex_node_t *)((*((((NODE)->class))->SELECTOR))(NODE)))
 
199
 
 
200
#   define SYNCTEX_FREE(NODE) SYNCTEX_MSG_SEND(NODE,free);
 
201
 
 
202
/*  Parent getter and setter
 
203
 */
 
204
#   define SYNCTEX_PARENT(NODE) SYNCTEX_GET(NODE,parent)
 
205
#   define SYNCTEX_SET_PARENT(NODE,NEW_PARENT) if (NODE && NEW_PARENT && SYNCTEX_CAN_PERFORM(NODE,parent)){\
 
206
                SYNCTEX_GETTER(NODE,parent)[0]=NEW_PARENT;\
 
207
        }
 
208
 
 
209
/*  Child getter and setter
 
210
 */
 
211
#   define SYNCTEX_CHILD(NODE) SYNCTEX_GET(NODE,child)
 
212
#   define SYNCTEX_SET_CHILD(NODE,NEW_CHILD) if (NODE && NEW_CHILD){\
 
213
                SYNCTEX_GETTER(NODE,child)[0]=NEW_CHILD;\
 
214
                SYNCTEX_GETTER(NEW_CHILD,parent)[0]=NODE;\
 
215
        }
 
216
 
 
217
/*  Sibling getter and setter
 
218
 */
 
219
#   define SYNCTEX_SIBLING(NODE) SYNCTEX_GET(NODE,sibling)
 
220
#   define SYNCTEX_SET_SIBLING(NODE,NEW_SIBLING) if (NODE && NEW_SIBLING) {\
 
221
                SYNCTEX_GETTER(NODE,sibling)[0]=NEW_SIBLING;\
 
222
                if (SYNCTEX_CAN_PERFORM(NEW_SIBLING,parent) && SYNCTEX_CAN_PERFORM(NODE,parent)) {\
 
223
                        SYNCTEX_GETTER(NEW_SIBLING,parent)[0]=SYNCTEX_GETTER(NODE,parent)[0];\
 
224
                }\
 
225
        }
 
226
/*  Friend getter and setter. A friend is a kern, math, glue or void box node which tag and line numbers are similar.
 
227
 *  This is a first filter on the nodes that avoids testing all of them.
 
228
 *  Friends are used mainly in forward synchronization aka from source to output.
 
229
 */
 
230
#   define SYNCTEX_FRIEND(NODE) SYNCTEX_GET(NODE,friend)
 
231
#   define SYNCTEX_SET_FRIEND(NODE,NEW_FRIEND) if (NODE && NEW_FRIEND){\
 
232
                SYNCTEX_GETTER(NODE,friend)[0]=NEW_FRIEND;\
 
233
        }
 
234
 
 
235
/*  Next box getter and setter. The box tree can be traversed from one horizontal box to the other.
 
236
 *  Navigation starts with the deeper boxes.
 
237
 */
 
238
#   define SYNCTEX_NEXT_hbox(NODE) SYNCTEX_GET(NODE,next_hbox)
 
239
#   define SYNCTEX_SET_NEXT_hbox(NODE,NEXT_HBOX) if (NODE && NEXT_HBOX){\
 
240
                SYNCTEX_GETTER(NODE,next_hbox)[0]=NEXT_HBOX;\
 
241
        }
 
242
 
 
243
/*  A node is meant to own its child and sibling.
 
244
 *  It is not owned by its parent, unless it is its first child.
 
245
 *  This destructor is for all nodes with children.
 
246
 */
 
247
static void _synctex_free_node(synctex_node_t node) {
 
248
        if (node) {
 
249
                (*((node->class)->sibling))(node);
 
250
                SYNCTEX_FREE(SYNCTEX_SIBLING(node));
 
251
                SYNCTEX_FREE(SYNCTEX_CHILD(node));
 
252
                free(node);
 
253
        }
 
254
        return;
 
255
}
 
256
 
 
257
/*  A node is meant to own its child and sibling.
 
258
 *  It is not owned by its parent, unless it is its first child.
 
259
 *  This destructor is for nodes with no child.
 
260
 *  The first sheet is onwned by the scanner.
 
261
 */
 
262
static void _synctex_free_leaf(synctex_node_t node) {
 
263
        if (node) {
 
264
                SYNCTEX_FREE(SYNCTEX_SIBLING(node));
 
265
                free(node);
 
266
        }
 
267
        return;
 
268
}
498
269
#       ifdef   __SYNCTEX_WORK__
499
 
#               include "/usr/local/include/node/zlib.h"
 
270
#               include "/usr/include/zlib.h"
500
271
#       else
501
272
#               include <zlib.h>
502
273
#       endif
503
274
 
504
 
#       ifdef SYNCTEX_NOTHING
505
 
#       pragma mark -
506
 
#       pragma mark STATUS
507
 
#   endif
508
 
/*  When the end of the synctex file has been reached: */
509
 
#   define SYNCTEX_STATUS_EOF 0
510
 
/*  When the function could not return the value it was asked for: */
511
 
#   define SYNCTEX_STATUS_NOT_OK (SYNCTEX_STATUS_EOF+1)
512
 
/*  When the function returns the value it was asked for:
513
 
 It must be the biggest one */
514
 
#   define SYNCTEX_STATUS_OK (SYNCTEX_STATUS_NOT_OK+1)
515
 
/*  Generic error: */
516
 
#   define SYNCTEX_STATUS_ERROR (SYNCTEX_STATUS_EOF-1)
517
 
/*  Parameter error: */
518
 
#   define SYNCTEX_STATUS_BAD_ARGUMENT (SYNCTEX_STATUS_ERROR-1)
519
 
 
520
 
#       ifdef SYNCTEX_NOTHING
521
 
#       pragma mark -
522
 
#       pragma mark File reader
523
 
#   endif
524
 
 
525
 
/*  We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */
526
 
/*  Actually, the minimum buffer size is driven by integer and float parsing, including the unit.
527
 
 *  ±0.123456789e123??
528
 
 */
529
 
#   define SYNCTEX_BUFFER_MIN_SIZE 32
530
 
#   define SYNCTEX_BUFFER_SIZE 32768
531
 
 
532
 
#if SYNCTEX_BUFFER_SIZE >= UINT_MAX
533
 
#   error BAD BUFFER SIZE(1)
534
 
#endif
535
 
#if SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE
536
 
#   error BAD BUFFER SIZE(2)
537
 
#endif
538
 
 
539
 
typedef struct synctex_reader_t {
540
 
    gzFile file;    /*  The (possibly compressed) file */
541
 
    char * output;
542
 
    char * synctex;
543
 
    char * current; /*  current location in the buffer */
544
 
    char * start;   /*  start of the buffer */
545
 
    char * end;     /*  end of the buffer */
546
 
    size_t min_size;
547
 
    size_t size;
548
 
    int lastv;
549
 
    int line_number;
550
 
    SYNCTEX_DECLARE_CHAR_OFFSET
551
 
} synctex_reader_s;
552
 
 
553
 
typedef synctex_reader_s * synctex_reader_p;
554
 
 
555
 
typedef struct {
556
 
    synctex_status_t status;
557
 
    char * synctex;
558
 
    gzFile file;
559
 
    synctex_io_mode_t io_mode;
560
 
} synctex_open_s;
561
 
 
562
 
/*      This functions opens the file at the "output" given location.
563
 
 *  It manages the problem of quoted filenames that appear with pdftex and filenames containing the space character.
564
 
 *  In TeXLive 2008, the synctex file created with pdftex did contain unexpected quotes.
565
 
 *      This function will remove them if possible.
566
 
 *  All the reference arguments will take a value on return. They must be non NULL.
567
 
 *      - returns: an open structure which status is
568
 
 *      SYNCTEX_STATUS_OK on success,
569
 
 *      SYNCTEX_STATUS_ERROR on failure.
570
 
 *  - note: on success, the caller is the owner
571
 
 *      of the fields of the returned open structure.
572
 
 */
573
 
static synctex_open_s __synctex_open_v2(const char * output, synctex_io_mode_t io_mode, synctex_bool_t add_quotes) {
574
 
    synctex_open_s open = {SYNCTEX_STATUS_ERROR, NULL, NULL, io_mode};
575
 
    char * quoteless_synctex_name = NULL;
576
 
    const char * mode = _synctex_get_io_mode_name(open.io_mode);
577
 
    size_t size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1;
578
 
    if (NULL == (open.synctex = (char *)malloc(size))) {
579
 
        _synctex_error("!  __synctex_open_v2: Memory problem (1)\n");
580
 
        return open;
581
 
    }
582
 
    /*  we have reserved for synctex enough memory to copy output (including its 2 eventual quotes), both suffices,
583
 
     *  including the terminating character. size is free now. */
584
 
    if (open.synctex != strcpy(open.synctex,output)) {
585
 
        _synctex_error("!  __synctex_open_v2: Copy problem\n");
586
 
    return_on_error:
587
 
        free(open.synctex);
588
 
        open.synctex = NULL;
589
 
        free(quoteless_synctex_name);/* We MUST have quoteless_synctex_name<>synctex_name */
590
 
        return open;
591
 
    }
592
 
    /*  remove the last path extension if any */
593
 
    _synctex_strip_last_path_extension(open.synctex);
594
 
    if (!strlen(open.synctex)) {
595
 
        goto return_on_error;
596
 
    }
597
 
    /*  now insert quotes. */
598
 
    if (add_quotes) {
599
 
        char * quoted = NULL;
600
 
        if (_synctex_copy_with_quoting_last_path_component(open.synctex,&quoted,size) || quoted == NULL) {
601
 
            /*  There was an error or quoting does not make sense: */
602
 
            goto return_on_error;
603
 
        }
604
 
        quoteless_synctex_name = open.synctex;
605
 
        open.synctex = quoted;
606
 
    }
607
 
    /*  Now add to open.synctex the first path extension. */
608
 
    if (open.synctex != strcat(open.synctex,synctex_suffix)){
609
 
        _synctex_error("!  __synctex_open_v2: Concatenation problem (can't add suffix '%s')\n",synctex_suffix);
610
 
        goto return_on_error;
611
 
    }
612
 
    /*  Add to quoteless_synctex_name as well, if relevant. */
613
 
    if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix))){
614
 
        free(quoteless_synctex_name);
615
 
        quoteless_synctex_name = NULL;
616
 
    }
617
 
    if (NULL == (open.file = gzopen(open.synctex,mode))) {
618
 
        /*  Could not open this file */
619
 
        if (errno != ENOENT) {
620
 
            /*  The file does exist, this is a lower level error, I can't do anything. */
621
 
            _synctex_error("could not open %s, error %i\n",open.synctex,errno);
622
 
            goto return_on_error;
623
 
        }
624
 
        /*  Apparently, there is no uncompressed synctex file. Try the compressed version */
625
 
        if (open.synctex != strcat(open.synctex,synctex_suffix_gz)){
626
 
            _synctex_error("!  __synctex_open_v2: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz);
627
 
            goto return_on_error;
628
 
        }
629
 
        open.io_mode |= synctex_io_gz_mask;
630
 
        mode = _synctex_get_io_mode_name(open.io_mode); /* the file is a compressed and is a binary file, this caused errors on Windows */
631
 
        /*      Add the suffix to the quoteless_synctex_name as well. */
632
 
        if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix_gz))){
633
 
            free(quoteless_synctex_name);
634
 
            quoteless_synctex_name = NULL;
635
 
        }
636
 
        if (NULL == (open.file = gzopen(open.synctex,mode))) {
637
 
            /*  Could not open this file */
638
 
            if (errno != ENOENT) {
639
 
                /*  The file does exist, this is a lower level error, I can't do anything. */
640
 
                _synctex_error("Could not open %s, error %i\n",open.synctex,errno);
641
 
            }
642
 
            goto return_on_error;
643
 
        }
644
 
    }
645
 
    /*  At this point, the file is properly open.
646
 
     *  If we are in the add_quotes mode, we change the file name by removing the quotes. */
647
 
    if (quoteless_synctex_name) {
648
 
        gzclose(open.file);
649
 
        if (rename(open.synctex,quoteless_synctex_name)) {
650
 
            _synctex_error("Could not rename %s to %s, error %i\n",open.synctex,quoteless_synctex_name,errno);
651
 
            /*  We could not rename, reopen the file with the quoted name. */
652
 
            if (NULL == (open.file = gzopen(open.synctex,mode))) {
653
 
                /*  No luck, could not re open this file, something has happened meanwhile */
654
 
                if (errno != ENOENT) {
655
 
                    /*  The file does not exist any more, it has certainly be removed somehow
656
 
                     *  this is a lower level error, I can't do anything. */
657
 
                    _synctex_error("Could not open again %s, error %i\n",open.synctex,errno);
658
 
                }
659
 
                goto return_on_error;
660
 
            }
661
 
        } else {
662
 
            /*  The file has been successfully renamed */
663
 
            if (NULL == (open.file = gzopen(quoteless_synctex_name,mode))) {
664
 
                /*  Could not open this file */
665
 
                if (errno != ENOENT) {
666
 
                    /*  The file does exist, this is a lower level error, I can't do anything. */
667
 
                    _synctex_error("Could not open renamed %s, error %i\n",quoteless_synctex_name,errno);
668
 
                }
669
 
                goto return_on_error;
670
 
            }
671
 
            /*  The quote free file name should replace the old one:*/
672
 
            free(open.synctex);
673
 
            open.synctex = quoteless_synctex_name;
674
 
            quoteless_synctex_name = NULL;
675
 
        }
676
 
    }
677
 
    /*  The operation is successful, return the arguments by value.    */
678
 
    open.status = SYNCTEX_STATUS_OK;
679
 
    return open;
680
 
}
681
 
 
682
 
/*      Opens the output file, taking into account the eventual build_directory.
683
 
 *      - returns: an open structure which status is
684
 
 *      SYNCTEX_STATUS_OK on success,
685
 
 *      SYNCTEX_STATUS_ERROR on failure.
686
 
 *  - note: on success, the caller is the owner
687
 
 *      of the fields of the returned open structure.
688
 
 */
689
 
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) {
690
 
    synctex_open_s open = __synctex_open_v2(output,io_mode,add_quotes);
691
 
    if (open.status == SYNCTEX_STATUS_OK) {
692
 
        return open;
693
 
    }
694
 
    if (build_directory && strlen(build_directory)) {
695
 
        char * build_output;
696
 
        const char *lpc;
697
 
        size_t size;
698
 
        synctex_bool_t is_absolute;
699
 
        build_output = NULL;
700
 
        lpc = _synctex_last_path_component(output);
701
 
        size = strlen(build_directory)+strlen(lpc)+2;   /*  One for the '/' and one for the '\0'.   */
702
 
        is_absolute = _synctex_path_is_absolute(build_directory);
703
 
        if (!is_absolute) {
704
 
            size += strlen(output);
705
 
        }
706
 
        if ((build_output = (char *)_synctex_malloc(size))) {
707
 
            if (is_absolute) {
708
 
                build_output[0] = '\0';
709
 
            } else {
710
 
                if (build_output != strcpy(build_output,output)) {
711
 
                    _synctex_free(build_output);
712
 
                    return open;
713
 
                }
714
 
                build_output[lpc-output]='\0';
715
 
            }
716
 
            if (build_output == strcat(build_output,build_directory)) {
717
 
                /*      Append a path separator if necessary. */
718
 
                if (!SYNCTEX_IS_PATH_SEPARATOR(build_output[strlen(build_directory)-1])) {
719
 
                    if (build_output != strcat(build_output,"/")) {
720
 
                        _synctex_free(build_output);
721
 
                        return open;
722
 
                    }
723
 
                }
724
 
                /*      Append the last path component of the output. */
725
 
                if (build_output != strcat(build_output,lpc)) {
726
 
                    _synctex_free(build_output);
727
 
                    return open;
728
 
                }
729
 
                open = __synctex_open_v2(build_output,io_mode,add_quotes);
730
 
            }
731
 
            _synctex_free(build_output);
732
 
        } /* if ((build_output... */
733
 
    } /* if (build_directory...) */
734
 
    return open;
735
 
}
736
 
static void synctex_reader_free(synctex_reader_p reader) {
737
 
    if (reader) {
738
 
        _synctex_free(reader->output);
739
 
        _synctex_free(reader->synctex);
740
 
        _synctex_free(reader->start);
741
 
        gzclose(reader->file);
742
 
        _synctex_free(reader);
743
 
    }
744
 
}
745
 
/*
746
 
 *  Return reader on success.
747
 
 *  Deallocate reader and return NULL on failure.
748
 
 */
749
 
static synctex_reader_p synctex_reader_init_with_output_file(synctex_reader_p reader, const char * output, const char * build_directory) {
750
 
    if (reader) {
751
 
        /*  now open the synctex file */
752
 
        synctex_open_s open = _synctex_open_v2(output,build_directory,0,synctex_ADD_QUOTES);
753
 
        if (open.status<SYNCTEX_STATUS_OK) {
754
 
            open = _synctex_open_v2(output,build_directory,0,synctex_DONT_ADD_QUOTES);
755
 
            if (open.status<SYNCTEX_STATUS_OK) {
756
 
                return NULL;
757
 
            }
758
 
        }
759
 
        reader->synctex = open.synctex;
760
 
        reader->file = open.file;
761
 
        /*  make a private copy of output */
762
 
        if (NULL == (reader->output = (char *)_synctex_malloc(strlen(output)+1))){
763
 
            _synctex_error("!  synctex_scanner_new_with_output_file: Memory problem (2), reader's output is not reliable.");
764
 
        } else if (reader->output != strcpy(reader->output,output)) {
765
 
            _synctex_free(reader->output);
766
 
            reader->output = NULL;
767
 
            _synctex_error("!  synctex_scanner_new_with_output_file: Copy problem, reader's output is not reliable.");
768
 
        }
769
 
        reader->start = reader->end = reader->current = NULL;
770
 
        reader->min_size = SYNCTEX_BUFFER_MIN_SIZE;
771
 
        reader->size = SYNCTEX_BUFFER_SIZE;
772
 
        reader->start = reader->current =
773
 
            (char *)_synctex_malloc(reader->size+1); /*  one more character for null termination */
774
 
        if (NULL == reader->start) {
775
 
            _synctex_error("!  malloc error in synctex_reader_init_with_output_file.");
776
 
        bailey:
777
 
#ifdef SYNCTEX_DEBUG
778
 
            return reader;
779
 
#else
780
 
            synctex_reader_free(reader);
781
 
            return NULL;
782
 
#endif
783
 
        }
784
 
        reader->end = reader->start+reader->size;
785
 
        /*  reader->end always points to a null terminating character.
786
 
         *  Maybe there is another null terminating character between reader->current and reader->end-1.
787
 
         *  At least, we are sure that reader->current points to a string covering a valid part of the memory. */
788
 
#   if defined(SYNCTEX_USE_CHARINDEX)
789
 
        reader->charindex_offset = -reader->size;
790
 
#   endif
791
 
    }
792
 
    return reader;
793
 
}
794
 
 
795
 
#   if defined(SYNCTEX_USE_HANDLE)
796
 
#       define SYNCTEX_DECLARE_HANDLE synctex_node_p handle;
797
 
#   else
798
 
#       define SYNCTEX_DECLARE_HANDLE
799
 
#   endif
800
 
 
801
 
#   ifdef SYNCTEX_NOTHING
802
 
#       pragma mark -
803
 
#       pragma mark SCANNER
804
 
#   endif
805
 
/**
806
 
 *  The synctex scanner is the root object.
 
275
/*  The synctex scanner is the root object.
807
276
 *  Is is initialized with the contents of a text file or a gzipped file.
808
 
 *  The buffer_.* are first used to parse the text.
 
277
 *  The buffer_? are first used to parse the text.
809
278
 */
810
 
struct synctex_scanner_t {
811
 
    synctex_reader_p reader;
812
 
    SYNCTEX_DECLARE_NODE_COUNT
813
 
    SYNCTEX_DECLARE_HANDLE
814
 
    char * output_fmt;          /*  dvi or pdf, not yet used */
815
 
    synctex_iterator_p iterator;/*  result iterator */
816
 
    int version;                /*  1, not yet used */
817
 
    struct {
818
 
        unsigned has_parsed:1;          /*  Whether the scanner has parsed its underlying synctex file. */
819
 
        unsigned postamble:1;           /*  Whether the scanner has parsed its underlying synctex file. */
820
 
        unsigned reserved:sizeof(unsigned)-2;   /*  alignment */
821
 
    } flags;
822
 
    int pre_magnification;  /*  magnification from the synctex preamble */
823
 
    int pre_unit;           /*  unit from the synctex preamble */
824
 
    int pre_x_offset;       /*  X offset from the synctex preamble */
825
 
    int pre_y_offset;       /*  Y offset from the synctex preamble */
826
 
    int count;              /*  Number of records, from the synctex postamble */
827
 
    float unit;             /*  real unit, from synctex preamble or post scriptum */
828
 
    float x_offset;         /*  X offset, from synctex preamble or post scriptum */
829
 
    float y_offset;         /*  Y Offset, from synctex preamble or post scriptum */
830
 
    synctex_node_p input;   /*  The first input node, its siblings are the other input nodes */
831
 
    synctex_node_p sheet;   /*  The first sheet node, its siblings are the other sheet nodes */
832
 
    synctex_node_p form;    /*  The first form, its siblings are the other forms */
833
 
    synctex_node_p ref_in_sheet; /*  The first form ref node in sheet, its friends are the other form ref nodes */
834
 
    synctex_node_p ref_in_form;  /*  The first form ref node, its friends are the other form ref nodes in sheet */
835
 
    int number_of_lists;    /*  The number of friend lists */
836
 
    synctex_node_r lists_of_friends;/*  The friend lists */
837
 
    synctex_class_s class_[synctex_node_number_of_types]; /*  The classes of the nodes of the scanner */
838
 
    int display_switcher;
839
 
    char * display_prompt;
 
279
struct __synctex_scanner_t {
 
280
        gzFile file;                  /*  The (possibly compressed) file */
 
281
    SYNCTEX_DECLARE_CHAR_OFFSET;
 
282
        char * buffer_cur;            /*  current location in the buffer */
 
283
        char * buffer_start;          /*  start of the buffer */
 
284
        char * buffer_end;            /*  end of the buffer */
 
285
        char * output_fmt;            /*  dvi or pdf, not yet used */
 
286
        char * output;                /*  the output name used to create the scanner */
 
287
        char * synctex;               /*  the .synctex or .synctex.gz name used to create the scanner */
 
288
        int version;                  /*  1, not yet used */
 
289
        struct {
 
290
                unsigned has_parsed:1;          /*  Whether the scanner has parsed its underlying synctex file. */
 
291
                unsigned reserved:sizeof(unsigned)-1;   /*  alignment */
 
292
        } flags;
 
293
        int pre_magnification;        /*  magnification from the synctex preamble */
 
294
        int pre_unit;                 /*  unit from the synctex preamble */
 
295
        int pre_x_offset;             /*  X offste from the synctex preamble */
 
296
        int pre_y_offset;             /*  Y offset from the synctex preamble */
 
297
        int count;                    /*  Number of records, from the synctex postamble */
 
298
        float unit;                   /*  real unit, from synctex preamble or post scriptum */
 
299
        float x_offset;               /*  X offset, from synctex preamble or post scriptum */
 
300
        float y_offset;               /*  Y Offset, from synctex preamble or post scriptum */
 
301
        synctex_node_t sheet;         /*  The first sheet node, its siblings are the other sheet nodes */
 
302
        synctex_node_t input;         /*  The first input node, its siblings are the other input nodes */
 
303
        int number_of_lists;          /*  The number of friend lists */
 
304
        synctex_node_t * lists_of_friends;/*  The friend lists */
 
305
        _synctex_class_t class[synctex_node_number_of_types]; /*  The classes of the nodes of the scanner */
840
306
};
841
307
 
842
 
/**
843
 
 *  Create a new node of the given type.
844
 
 *  - parameter scanner: of type synctex_node_p
845
 
 *  - parameter type: a type, the client is responsible
846
 
 *  to ask for an acceptable type.
847
 
 */
848
 
synctex_node_p synctex_node_new(synctex_scanner_p scanner, synctex_node_type_t type) {
849
 
    return scanner? scanner->class_[type].new(scanner):NULL;
850
 
}
851
 
#   if defined(SYNCTEX_USE_HANDLE)
852
 
SYNCTEX_INLINE static void __synctex_scanner_free_handle(synctex_scanner_p scanner) {
853
 
    synctex_node_free(scanner->handle);
854
 
}
855
 
SYNCTEX_INLINE static void __synctex_scanner_remove_handle_to(synctex_node_p node) {
856
 
    synctex_node_p arg_sibling = NULL;
857
 
    synctex_node_p handle = node->class_->scanner->handle;
858
 
    while (handle) {
859
 
        synctex_node_p sibling;
860
 
        if (node == _synctex_tree_target(handle)) {
861
 
            sibling = __synctex_tree_reset_sibling(handle);
862
 
            if (arg_sibling) {
863
 
                __synctex_tree_set_sibling(arg_sibling, sibling);
864
 
            } else {
865
 
                node->class_->scanner->handle = sibling;
866
 
            }
867
 
            synctex_node_free(handle);
868
 
            break;
869
 
        } else {
870
 
            sibling = __synctex_tree_sibling(handle);
871
 
        }
872
 
        arg_sibling = handle;
873
 
        handle = sibling;
874
 
    }
875
 
}
876
 
SYNCTEX_INLINE static void __synctex_scanner_register_handle_to(synctex_node_p  node) {
877
 
    synctex_node_p NNN = _synctex_new_handle_with_target(node);
878
 
    __synctex_tree_set_sibling(NNN,node->class_->scanner->handle);
879
 
    node->class_->scanner->handle = NNN;
880
 
}
881
 
#endif
882
 
#if SYNCTEX_USE_NODE_COUNT>10
883
 
SYNCTEX_INLINE static void _synctex_did_new(synctex_node_p node) {
884
 
    printf("NODE CREATED # %i, %s, %p\n",
885
 
           (node->class_->scanner->node_count)++,
886
 
           synctex_node_isa(node),
887
 
           node);
888
 
}
889
 
SYNCTEX_INLINE static void _synctex_will_free(synctex_node_p node) {
890
 
    printf("NODE DELETED # %i, %s, %p\n",
891
 
           --(node->class_->scanner->node_count),
892
 
           synctex_node_isa(node),
893
 
           node);
894
 
}
895
 
#endif
896
 
 
897
 
/**
898
 
 *  Free the given node.
899
 
 *  - parameter node: of type synctex_node_p
900
 
 *  - note: a node is meant to own its child and sibling.
901
 
 *  It is not owned by its parent, unless it is its first child.
902
 
 *  This destructor is for all nodes with children.
903
 
 */
904
 
static void _synctex_free_node(synctex_node_p node) {
905
 
    if (node) {
906
 
        SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node);
907
 
        SYNCTEX_WILL_FREE(node);
908
 
        synctex_node_free(__synctex_tree_sibling(node));
909
 
        synctex_node_free(_synctex_tree_child(node));
910
 
        _synctex_free(node);
911
 
    }
912
 
    return;
913
 
}
914
 
/**
915
 
 *  Free the given handle.
916
 
 *  - parameter node: of type synctex_node_p
917
 
 *  - note: a node is meant to own its child and sibling.
918
 
 *  It is not owned by its parent, unless it is its first child.
919
 
 *  This destructor is for all handles.
920
 
 */
921
 
static void _synctex_free_handle_old(synctex_node_p handle) {
922
 
  if (handle) {
923
 
    _synctex_free_handle_old(__synctex_tree_sibling(handle));
924
 
    _synctex_free_handle_old(_synctex_tree_child(handle));
925
 
    _synctex_free(handle);
926
 
  }
927
 
  return;
928
 
}
929
 
static void _synctex_free_handle(synctex_node_p handle) {
930
 
  if (handle) {
931
 
    synctex_node_p n = handle;
932
 
    synctex_node_p nn;
933
 
    __synctex_tree_set_parent(n, NULL);
934
 
  down:
935
 
    while ((nn = _synctex_tree_child(n))) {
936
 
      __synctex_tree_set_parent(nn, n);
937
 
      n = nn;
938
 
    };
939
 
  right:
940
 
    nn = __synctex_tree_sibling(n);
941
 
    if (nn) {
942
 
      _synctex_free(n);
943
 
      n = nn;
944
 
      goto down;
945
 
    }
946
 
    nn = __synctex_tree_parent(n);
947
 
    _synctex_free(n);
948
 
    if (nn) {
949
 
      n = nn;
950
 
      goto right;
951
 
    }
952
 
  }
953
 
  return;
954
 
}
955
 
 
956
 
/**
957
 
 *  Free the given leaf node.
958
 
 *  - parameter node: of type synctex_node_p, with no child nor sibling.
959
 
 *  - note: a node is meant to own its child and sibling.
960
 
 *  It is not owned by its parent, unless it is its first child.
961
 
 *  This destructor is for all nodes with no children.
962
 
 */
963
 
static void _synctex_free_leaf(synctex_node_p node) {
964
 
    if (node) {
965
 
        SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node);
966
 
        SYNCTEX_WILL_FREE(node);
967
 
        synctex_node_free(__synctex_tree_sibling(node));
968
 
        _synctex_free(node);
969
 
    }
970
 
    return;
971
 
}
972
 
 
973
 
/**
974
 
 SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts
975
 
 */
976
 
#   define SYNCTEX_CUR (scanner->reader->current)
977
 
#   define SYNCTEX_START (scanner->reader->start)
978
 
#   define SYNCTEX_END (scanner->reader->end)
979
 
 
980
 
/*  Here are gathered all the possible status that the next scanning functions will return.
981
 
 *  All these functions return a status, and pass their result through pointers.
982
 
 *  Negative values correspond to errors.
983
 
 *  The management of the buffer is causing some significant overhead.
984
 
 *  Every function that may access the buffer returns a status related to the buffer and file state.
985
 
 *  status >= SYNCTEX_STATUS_OK means the function worked as expected
986
 
 *  status < SYNCTEX_STATUS_OK means the function did not work as expected
987
 
 *  status == SYNCTEX_STATUS_NOT_OK means the function did not work as expected but there is still some material to parse.
988
 
 *  status == SYNCTEX_STATUS_EOF means the function did not work as expected and there is no more material.
989
 
 *  status<SYNCTEX_STATUS_EOF means an error
990
 
 */
991
 
#if defined(SYNCTEX_USE_CHARINDEX)
992
 
synctex_node_p synctex_scanner_handle(synctex_scanner_p scanner) {
993
 
    return scanner? scanner->handle:NULL;
994
 
}
995
 
#endif
996
 
 
997
 
#       ifdef SYNCTEX_NOTHING
998
 
#       pragma mark -
999
 
#       pragma mark Decoding prototypes
1000
 
#   endif
1001
 
 
1002
 
typedef struct {
1003
 
    int integer;
1004
 
    synctex_status_t status;
1005
 
} synctex_is_s;
1006
 
 
1007
 
static synctex_is_s _synctex_decode_int(synctex_scanner_p scanner);
1008
 
static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value);
1009
 
static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner);
1010
 
 
1011
 
typedef struct {
1012
 
    char * string;
1013
 
    synctex_status_t status;
1014
 
} synctex_ss_s;
1015
 
 
1016
 
static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner);
1017
 
 
1018
 
#       ifdef SYNCTEX_NOTHING
1019
 
#       pragma mark -
1020
 
#       pragma mark Data SETGET
1021
 
#   endif
1022
 
 
1023
 
/**
1024
 
 *  The next macros are used to access the node data info
1025
 
 *  through the class modelator integer fields.
1026
 
  *  - parameter NODE: of type synctex_node_p
1027
 
 */
1028
 
#   define SYNCTEX_DATA(NODE) ((*((((NODE)->class_))->info))(NODE))
1029
 
#if defined SYNCTEX_DEBUG > 1000
1030
 
#   define DEFINE_SYNCTEX_DATA_HAS(WHAT) \
1031
 
SYNCTEX_INLINE static synctex_bool_t __synctex_data_has_##WHAT(synctex_node_p node) {\
1032
 
    return (node && (node->class_->modelator->WHAT>=0));\
1033
 
}\
1034
 
SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node) {\
1035
 
    if (node && (node->class_->modelator->WHAT<0)) {\
1036
 
        printf("WARNING: NO %s for %s\n", #WHAT, synctex_node_isa(node));\
1037
 
    }\
1038
 
    return __synctex_data_has_##WHAT(node);\
1039
 
}
1040
 
#else
1041
 
#   define DEFINE_SYNCTEX_DATA_HAS(WHAT) \
1042
 
SYNCTEX_INLINE static synctex_bool_t __synctex_data_has_##WHAT(synctex_node_p node) {\
1043
 
    return (node && (node->class_->modelator->WHAT>=0));\
1044
 
}\
1045
 
SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node) {\
1046
 
    return __synctex_data_has_##WHAT(node);\
1047
 
}
1048
 
#endif
1049
 
 
1050
 
SYNCTEX_INLINE static synctex_data_p __synctex_data(synctex_node_p node) {
1051
 
    return node->data+node->class_->navigator->size;
1052
 
}
1053
 
#   define DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \
1054
 
DEFINE_SYNCTEX_DATA_HAS(WHAT)\
1055
 
static int _synctex_data_##WHAT(synctex_node_p node) {\
1056
 
    if (_synctex_data_has_##WHAT(node)) {\
1057
 
        return __synctex_data(node)[node->class_->modelator->WHAT].as_integer;\
1058
 
    }\
1059
 
    return 0;\
1060
 
}\
1061
 
static int _synctex_data_set_##WHAT(synctex_node_p node, int new_value) {\
1062
 
    int old = 0;\
1063
 
    if (_synctex_data_has_##WHAT(node)) {\
1064
 
        old = __synctex_data(node)[node->class_->modelator->WHAT].as_integer;\
1065
 
        __synctex_data(node)[node->class_->modelator->WHAT].as_integer=new_value;\
1066
 
    }\
1067
 
    return old;\
1068
 
}
1069
 
#define DEFINE_SYNCTEX_DATA_INT_DECODE(WHAT) \
1070
 
static synctex_status_t _synctex_data_decode_##WHAT(synctex_node_p node) {\
1071
 
    if (_synctex_data_has_##WHAT(node)) {\
1072
 
        synctex_is_s is = _synctex_decode_int(node->class_->scanner);\
1073
 
        if (is.status == SYNCTEX_STATUS_OK) {\
1074
 
            _synctex_data_set_##WHAT(node,is.integer);\
1075
 
        } \
1076
 
        return is.status;\
1077
 
    }\
1078
 
    return SYNCTEX_STATUS_BAD_ARGUMENT;\
1079
 
}
1080
 
#   define DEFINE_SYNCTEX_DATA_INT_DECODE_v(WHAT) \
1081
 
static synctex_status_t _synctex_data_decode_##WHAT##_v(synctex_node_p node) {\
1082
 
    if (_synctex_data_has_##WHAT(node)) {\
1083
 
        synctex_is_s is = _synctex_decode_int_v(node->class_->scanner);\
1084
 
        if (is.status == SYNCTEX_STATUS_OK) {\
1085
 
            _synctex_data_set_##WHAT(node,is.integer);\
1086
 
        } \
1087
 
        return is.status;\
1088
 
    }\
1089
 
    return SYNCTEX_STATUS_BAD_ARGUMENT;\
1090
 
}
1091
 
#define DEFINE_SYNCTEX_DATA_STR_GETSET(WHAT) \
1092
 
DEFINE_SYNCTEX_DATA_HAS(WHAT)\
1093
 
static char * _synctex_data_##WHAT(synctex_node_p node) {\
1094
 
    if (_synctex_data_has_##WHAT(node)) {\
1095
 
        return node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string;\
1096
 
    }\
1097
 
    return NULL;\
1098
 
}\
1099
 
static char * _synctex_data_set_##WHAT(synctex_node_p node, char * new_value) {\
1100
 
    char * old = "";\
1101
 
    if (_synctex_data_has_##WHAT(node)) {\
1102
 
        old = node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string;\
1103
 
        node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string =new_value;\
1104
 
    }\
1105
 
    return old;\
1106
 
}
1107
 
#define DEFINE_SYNCTEX_DATA_STR_DECODE(WHAT) \
1108
 
static synctex_status_t _synctex_data_decode_##WHAT(synctex_node_p node) {\
1109
 
    if (_synctex_data_has_##WHAT(node)) {\
1110
 
        synctex_ss_s ss = _synctex_decode_string(node->class_->scanner);\
1111
 
        if (ss.status == SYNCTEX_STATUS_OK) {\
1112
 
            _synctex_data_set_##WHAT(node,ss.string);\
1113
 
        } \
1114
 
        return ss.status;\
1115
 
    }\
1116
 
    return SYNCTEX_STATUS_BAD_ARGUMENT;\
1117
 
}
1118
 
#define DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(WHAT) \
1119
 
DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \
1120
 
DEFINE_SYNCTEX_DATA_INT_DECODE(WHAT)
1121
 
#define DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE_v(WHAT) \
1122
 
DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \
1123
 
DEFINE_SYNCTEX_DATA_INT_DECODE_v(WHAT)
1124
 
#define DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(WHAT) \
1125
 
DEFINE_SYNCTEX_DATA_STR_GETSET(WHAT) \
1126
 
DEFINE_SYNCTEX_DATA_STR_DECODE(WHAT)
 
308
/*  SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts
 
309
 */
 
310
#   define SYNCTEX_CUR (scanner->buffer_cur)
 
311
#   define SYNCTEX_START (scanner->buffer_start)
 
312
#   define SYNCTEX_END (scanner->buffer_end)
1127
313
 
1128
314
#       ifdef SYNCTEX_NOTHING
1129
315
#       pragma mark -
1130
316
#       pragma mark OBJECTS, their creators and destructors.
1131
317
#   endif
1132
318
 
1133
 
#       ifdef SYNCTEX_NOTHING
1134
 
#       pragma mark input.
1135
 
#   endif
1136
 
 
1137
 
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(tag)
1138
 
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(line)
1139
 
DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(name)
1140
 
 
1141
 
/*  Input nodes only know about their sibling, which is another input node.
1142
 
 *  The synctex information is the _synctex_data_tag and _synctex_data_name
1143
 
 *  note: the input owns its name. */
1144
 
 
1145
 
#   define SYNCTEX_INPUT_MARK "Input:"
1146
 
 
1147
 
static const synctex_tree_model_s synctex_tree_model_input = {
1148
 
    synctex_tree_sibling_idx, /* sibling */
1149
 
    -1, /* parent */
1150
 
    -1, /* child */
1151
 
    -1, /* friend */
1152
 
    -1, /* last */
1153
 
    -1, /* next_hbox */
1154
 
    -1, /* arg_sibling */
1155
 
    -1, /* target */
1156
 
    synctex_tree_s_input_max
1157
 
};
1158
 
static const synctex_data_model_s synctex_data_model_input = {
1159
 
    synctex_data_input_tag_idx, /* tag */
1160
 
    synctex_data_input_line_idx,/* line */
1161
 
    -1, /* column */
1162
 
    -1, /* h */
1163
 
    -1, /* v */
1164
 
    -1, /* width */
1165
 
    -1, /* height */
1166
 
    -1, /* depth */
1167
 
    -1, /* mean_line */
1168
 
    -1, /* weight */
1169
 
    -1, /* h_V */
1170
 
    -1, /* v_V */
1171
 
    -1, /* width_V */
1172
 
    -1, /* height_V */
1173
 
    -1, /* depth_V */
1174
 
    synctex_data_input_name_idx, /* name */
1175
 
    -1, /* page */
1176
 
    synctex_data_input_tln_max
1177
 
};
1178
 
 
1179
 
#define SYNCTEX_INSPECTOR_GETTER_F(WHAT)\
1180
 
&_synctex_data_##WHAT, &_synctex_data_set_##WHAT
1181
 
 
1182
 
static synctex_node_p _synctex_new_input(synctex_scanner_p scanner);
1183
 
static void _synctex_free_input(synctex_node_p node);
1184
 
static void _synctex_log_input(synctex_node_p node);
1185
 
static char * _synctex_abstract_input(synctex_node_p node);
1186
 
static void _synctex_display_input(synctex_node_p node);
1187
 
 
1188
 
static const synctex_tlcpector_s synctex_tlcpector_input = {
1189
 
    &_synctex_data_tag, /* tag */
1190
 
    &_synctex_int_none, /* line */
1191
 
    &_synctex_int_none, /* column */
1192
 
};
1193
 
 
1194
 
static synctex_class_s synctex_class_input = {
1195
 
    NULL,                       /*  No scanner yet */
1196
 
    synctex_node_type_input,    /*  Node type */
1197
 
    &_synctex_new_input,        /*  creator */
1198
 
    &_synctex_free_input,       /*  destructor */
1199
 
    &_synctex_log_input,        /*  log */
1200
 
    &_synctex_display_input,    /*  display */
1201
 
    &_synctex_abstract_input,   /*  abstract */
1202
 
    &synctex_tree_model_input,  /*  tree model */
1203
 
    &synctex_data_model_input,  /*  data model */
1204
 
    &synctex_tlcpector_input,   /*  inspector */
1205
 
    &synctex_inspector_none,    /*  inspector */
1206
 
    &synctex_vispector_none,    /*  vispector */
1207
 
};
1208
 
 
1209
 
typedef struct {
1210
 
    SYNCTEX_DECLARE_CHARINDEX
1211
 
    synctex_class_p class_;
1212
 
    synctex_data_u data[synctex_tree_s_input_max+synctex_data_input_tln_max];
1213
 
} synctex_input_s;
1214
 
 
1215
 
static synctex_node_p _synctex_new_input(synctex_scanner_p scanner) {
1216
 
    if (scanner) {
1217
 
        synctex_node_p node = _synctex_malloc(sizeof(synctex_input_s));
1218
 
        if (node) {
1219
 
            node->class_ = scanner->class_+synctex_node_type_input;
1220
 
            SYNCTEX_DID_NEW(node);
1221
 
            SYNCTEX_IMPLEMENT_CHARINDEX(node,0);
1222
 
            SYNCTEX_REGISTER_HANDLE_TO(node);
1223
 
        }
1224
 
        return node;
1225
 
    }
1226
 
    return NULL;
1227
 
}
1228
 
 
1229
 
static void _synctex_free_input(synctex_node_p node){
1230
 
    if (node) {
1231
 
        SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node);
1232
 
        SYNCTEX_WILL_FREE(node);
1233
 
        synctex_node_free(__synctex_tree_sibling(node));
1234
 
        _synctex_free(_synctex_data_name(node));
1235
 
        _synctex_free(node);
1236
 
    }
1237
 
}
 
319
/*  Here, we define the indices for the different informations.
 
320
 *  They are used to declare the size of the implementation.
 
321
 *  For example, if one object uses SYNCTEX_HORIZ_IDX is its size,
 
322
 *  then its info will contain a tag, line, column, horiz but no width nor height nor depth
 
323
 */
1238
324
 
1239
325
/*  The sheet is a first level node.
1240
 
 *  It has no parent (the owner is the scanner itself)
 
326
 *  It has no parent (the parent is the scanner itself)
1241
327
 *  Its sibling points to another sheet.
1242
328
 *  Its child points to its first child, in general a box.
1243
329
 *  A sheet node contains only one synctex information: the page.
1244
330
 *  This is the 1 based page index as given by TeX.
1245
331
 */
1246
 
 
1247
 
#       ifdef SYNCTEX_NOTHING
1248
 
#       pragma mark sheet.
1249
 
#   endif
1250
 
/**
1251
 
 *  Every node has the same structure, but not the same size.
1252
 
 */
1253
 
 
1254
 
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(page)
 
332
/*  The next macros are used to access the node info
 
333
 *  SYNCTEX_INFO(node) points to the first synctex integer or pointer data of node
 
334
 *  SYNCTEX_INFO(node)[index] is the information at index
 
335
 *  for example, the page of a sheet is stored in SYNCTEX_INFO(sheet)[SYNCTEX_PAGE_IDX]
 
336
 */
 
337
#   define SYNCTEX_INFO(NODE) ((*((((NODE)->class))->info))(NODE))
 
338
#   define SYNCTEX_PAGE_IDX 0
 
339
#   define SYNCTEX_PAGE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_PAGE_IDX].INT
 
340
 
 
341
/*  This macro defines implementation offsets
 
342
 *  It is only used for pointer values
 
343
 */
 
344
#   define SYNCTEX_MAKE_GET(SYNCTEX_GETTER,OFFSET)\
 
345
static synctex_node_t * SYNCTEX_GETTER (synctex_node_t node) {\
 
346
        return node?(synctex_node_t *)((&((node)->implementation))+OFFSET):NULL;\
 
347
}
 
348
SYNCTEX_MAKE_GET(_synctex_implementation_0,0)
 
349
SYNCTEX_MAKE_GET(_synctex_implementation_1,1)
 
350
SYNCTEX_MAKE_GET(_synctex_implementation_2,2)
 
351
SYNCTEX_MAKE_GET(_synctex_implementation_3,3)
 
352
SYNCTEX_MAKE_GET(_synctex_implementation_4,4)
 
353
SYNCTEX_MAKE_GET(_synctex_implementation_5,5)
1255
354
 
1256
355
typedef struct {
1257
356
    SYNCTEX_DECLARE_CHARINDEX
1258
 
    synctex_class_p class_;
1259
 
    synctex_data_u data[synctex_tree_scn_sheet_max+synctex_data_p_sheet_max];
1260
 
} synctex_node_sheet_s;
 
357
        synctex_class_t class;
 
358
        synctex_info_t implementation[3+SYNCTEX_PAGE_IDX+1];/*  child, sibling, next box,
 
359
                                 *  SYNCTEX_PAGE_IDX */
 
360
} synctex_node_sheet_t;
1261
361
 
1262
362
/*  sheet node creator */
1263
363
 
1264
 
#define DEFINE_synctex_new_scanned_NODE(NAME)\
1265
 
static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner) {\
1266
 
    if (scanner) {\
1267
 
        ++SYNCTEX_CUR;\
1268
 
        synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));\
1269
 
        if (node) {\
1270
 
            node->class_ = scanner->class_+synctex_node_type_##NAME;\
1271
 
            SYNCTEX_DID_NEW(node); \
1272
 
            SYNCTEX_IMPLEMENT_CHARINDEX(node,-1);\
1273
 
            SYNCTEX_REGISTER_HANDLE_TO(node); \
1274
 
        }\
1275
 
        return node;\
1276
 
    }\
1277
 
    return NULL;\
 
364
#define DEFINE_synctex_new_NODE(NAME)\
 
365
static synctex_node_t _synctex_new_##NAME(synctex_scanner_t scanner) {\
 
366
        if (scanner) {\
 
367
                synctex_node_t node = _synctex_malloc(sizeof(synctex_node_##NAME##_t));\
 
368
                if (node) {\
 
369
                        SYNCTEX_IMPLEMENT_CHARINDEX(node,0);\
 
370
                        ++SYNCTEX_CUR;\
 
371
                        node->class = scanner->class+synctex_node_type_##NAME;\
 
372
                }\
 
373
                return node;\
 
374
        }\
 
375
        return NULL;\
1278
376
}
1279
 
/*  NB: -1 in SYNCTEX_IMPLEMENT_CHARINDEX above because
1280
 
 *  the first char of the line has been scanned
1281
 
 */
1282
 
DEFINE_synctex_new_scanned_NODE(sheet)
1283
 
static void _synctex_log_sheet(synctex_node_p node);
1284
 
static char * _synctex_abstract_sheet(synctex_node_p node);
1285
 
static void _synctex_display_sheet(synctex_node_p node);
1286
 
 
1287
 
static const synctex_tree_model_s synctex_tree_model_sheet = {
1288
 
    synctex_tree_sibling_idx, /* sibling */
1289
 
    -1, /* parent */
1290
 
    synctex_tree_s_child_idx, /* child */
1291
 
    -1, /* friend */
1292
 
    -1, /* last */
1293
 
    synctex_tree_sc_next_hbox_idx, /* next_hbox */
1294
 
    -1, /* arg_sibling */
1295
 
    -1, /* target */
1296
 
    synctex_tree_scn_sheet_max
1297
 
};
1298
 
static const synctex_data_model_s synctex_data_model_sheet = {
1299
 
    -1, /* tag */
1300
 
    -1, /* line */
1301
 
    -1, /* column */
1302
 
    -1, /* h */
1303
 
    -1, /* v */
1304
 
    -1, /* width */
1305
 
    -1, /* height */
1306
 
    -1, /* depth */
1307
 
    -1, /* mean_line */
1308
 
    -1, /* weight */
1309
 
    -1, /* h_V */
1310
 
    -1, /* v_V */
1311
 
    -1, /* width_V */
1312
 
    -1, /* height_V */
1313
 
    -1, /* depth_V */
1314
 
    -1, /* name */
1315
 
    synctex_data_sheet_page_idx, /* page */
1316
 
    synctex_data_p_sheet_max
1317
 
};
1318
 
static synctex_class_s synctex_class_sheet = {
1319
 
    NULL,                       /*  No scanner yet */
1320
 
    synctex_node_type_sheet,    /*  Node type */
1321
 
    &_synctex_new_sheet,        /*  creator */
1322
 
    &_synctex_free_node,        /*  destructor */
1323
 
    &_synctex_log_sheet,        /*  log */
1324
 
    &_synctex_display_sheet,    /*  display */
1325
 
    &_synctex_abstract_sheet,   /*  abstract */
1326
 
    &synctex_tree_model_sheet,  /*  tree model */
1327
 
    &synctex_data_model_sheet,  /*  data model */
1328
 
    &synctex_tlcpector_none,    /*  tlcpector */
1329
 
    &synctex_inspector_none,    /*  inspector */
1330
 
    &synctex_vispector_none,    /*  vispector */
1331
 
};
1332
 
 
1333
 
#       ifdef SYNCTEX_NOTHING
1334
 
#       pragma mark form.
1335
 
#   endif
1336
 
/**
1337
 
 *  Every node has the same structure, but not the same size.
1338
 
 */
1339
 
typedef struct {
1340
 
    SYNCTEX_DECLARE_CHARINDEX
1341
 
    synctex_class_p class_;
1342
 
    synctex_data_u data[synctex_tree_sct_form_max+synctex_data_t_form_max];
1343
 
} synctex_node_form_s;
1344
 
 
1345
 
DEFINE_synctex_new_scanned_NODE(form)
1346
 
 
1347
 
static char * _synctex_abstract_form(synctex_node_p node);
1348
 
static void _synctex_display_form(synctex_node_p node);
1349
 
static void _synctex_log_form(synctex_node_p node);
1350
 
 
1351
 
static const synctex_tree_model_s synctex_tree_model_form = {
1352
 
    synctex_tree_sibling_idx, /* sibling */
1353
 
    -1, /* parent */
1354
 
    synctex_tree_s_child_idx, /* child */
1355
 
    -1, /* friend */
1356
 
    -1, /* last */
1357
 
    -1, /* next_hbox */
1358
 
    -1, /* arg_sibling */
1359
 
    synctex_tree_sc_target_idx, /* target */
1360
 
    synctex_tree_sct_form_max
1361
 
};
1362
 
static const synctex_data_model_s synctex_data_model_form = {
1363
 
    synctex_data_form_tag_idx, /* tag */
1364
 
    -1, /* line */
1365
 
    -1, /* column */
1366
 
    -1, /* h */
1367
 
    -1, /* v */
1368
 
    -1, /* width */
1369
 
    -1, /* height */
1370
 
    -1, /* depth */
1371
 
    -1, /* mean_line */
1372
 
    -1, /* weight */
1373
 
    -1, /* h_V */
1374
 
    -1, /* v_V */
1375
 
    -1, /* width_V */
1376
 
    -1, /* height_V */
1377
 
    -1, /* depth_V */
1378
 
    -1, /* name */
1379
 
    -1, /* page */
1380
 
    synctex_data_t_form_max
1381
 
};
1382
 
static synctex_class_s synctex_class_form = {
1383
 
    NULL,                       /*  No scanner yet */
1384
 
    synctex_node_type_form,     /*  Node type */
1385
 
    &_synctex_new_form,         /*  creator */
1386
 
    &_synctex_free_node,        /*  destructor */
1387
 
    &_synctex_log_form,         /*  log */
1388
 
    &_synctex_display_form,     /*  display */
1389
 
    &_synctex_abstract_form,    /*  abstract */
1390
 
    &synctex_tree_model_form,   /*  tree model */
1391
 
    &synctex_data_model_form,   /*  data model */
1392
 
    &synctex_tlcpector_none,    /*  tlcpector */
1393
 
    &synctex_inspector_none,    /*  inspector */
1394
 
    &synctex_vispector_none,    /*  vispector */
1395
 
};
1396
 
 
1397
 
#       ifdef SYNCTEX_NOTHING
1398
 
#       pragma mark vbox.
1399
 
#   endif
 
377
DEFINE_synctex_new_NODE(sheet)
 
378
 
 
379
static void _synctex_display_sheet(synctex_node_t node);
 
380
static void _synctex_log_sheet(synctex_node_t node);
 
381
 
 
382
static _synctex_class_t synctex_class_sheet = {
 
383
        NULL,                       /*  No scanner yet */
 
384
        synctex_node_type_sheet,    /*  Node type */
 
385
        &_synctex_new_sheet,        /*  creator */
 
386
        &_synctex_free_node,        /*  destructor */
 
387
        &_synctex_log_sheet,        /*  log */
 
388
        &_synctex_display_sheet,    /*  display */
 
389
        NULL,                       /*  No parent */
 
390
        &_synctex_implementation_0, /*  child */
 
391
        &_synctex_implementation_1, /*  sibling */
 
392
        NULL,                       /*  No friend */
 
393
        &_synctex_implementation_2, /*  Next hbox */
 
394
        (_synctex_info_getter_t)&_synctex_implementation_3  /*  info */
 
395
};
1400
396
 
1401
397
/*  A box node contains navigation and synctex information
1402
 
 *  There are different kinds of boxes.
 
398
 *  There are different kind of boxes.
1403
399
 *  Only horizontal boxes are treated differently because of their visible size.
1404
400
 */
 
401
#   define SYNCTEX_TAG_IDX 0
 
402
#   define SYNCTEX_LINE_IDX (SYNCTEX_TAG_IDX+1)
 
403
#   define SYNCTEX_COLUMN_IDX (SYNCTEX_LINE_IDX+1)
 
404
#   define SYNCTEX_HORIZ_IDX (SYNCTEX_COLUMN_IDX+1)
 
405
#   define SYNCTEX_VERT_IDX (SYNCTEX_HORIZ_IDX+1)
 
406
#   define SYNCTEX_WIDTH_IDX (SYNCTEX_VERT_IDX+1)
 
407
#   define SYNCTEX_HEIGHT_IDX (SYNCTEX_WIDTH_IDX+1)
 
408
#   define SYNCTEX_DEPTH_IDX (SYNCTEX_HEIGHT_IDX+1)
 
409
/*  the corresponding info accessors */
 
410
#   define SYNCTEX_TAG(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_TAG_IDX].INT
 
411
#   define SYNCTEX_LINE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_LINE_IDX].INT
 
412
#   define SYNCTEX_COLUMN(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_COLUMN_IDX].INT
 
413
#   define SYNCTEX_HORIZ(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HORIZ_IDX].INT
 
414
#   define SYNCTEX_VERT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_VERT_IDX].INT
 
415
#   define SYNCTEX_WIDTH(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_WIDTH_IDX].INT
 
416
#   define SYNCTEX_HEIGHT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HEIGHT_IDX].INT
 
417
#   define SYNCTEX_DEPTH(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_DEPTH_IDX].INT
 
418
#   define SYNCTEX_ABS_WIDTH(NODE) ((SYNCTEX_WIDTH(NODE)>0?SYNCTEX_WIDTH(NODE):-SYNCTEX_WIDTH(NODE)))
 
419
#   define SYNCTEX_ABS_HEIGHT(NODE) ((SYNCTEX_HEIGHT(NODE)>0?SYNCTEX_HEIGHT(NODE):-SYNCTEX_HEIGHT(NODE)))
 
420
#   define SYNCTEX_ABS_DEPTH(NODE) ((SYNCTEX_DEPTH(NODE)>0?SYNCTEX_DEPTH(NODE):-SYNCTEX_DEPTH(NODE)))
 
421
 
1405
422
typedef struct {
1406
423
    SYNCTEX_DECLARE_CHARINDEX
1407
 
    synctex_class_p class_;
1408
 
    synctex_data_u data[synctex_tree_spcfl_vbox_max+synctex_data_box_max];
1409
 
} synctex_node_vbox_s;
 
424
        synctex_class_t class;
 
425
        synctex_info_t implementation[5+SYNCTEX_DEPTH_IDX+1]; /*  parent,child,sibling,friend,next box,
 
426
                                                        *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
 
427
                                                                *  SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH */
 
428
} synctex_node_vbox_t;
1410
429
 
1411
430
/*  vertical box node creator */
1412
 
DEFINE_synctex_new_scanned_NODE(vbox)
1413
 
 
1414
 
static char * _synctex_abstract_vbox(synctex_node_p node);
1415
 
static void _synctex_display_vbox(synctex_node_p node);
1416
 
static void _synctex_log_vbox(synctex_node_p node);
1417
 
 
1418
 
static const synctex_tree_model_s synctex_tree_model_vbox = {
1419
 
    synctex_tree_sibling_idx,       /* sibling */
1420
 
    synctex_tree_s_parent_idx,      /* parent */
1421
 
    synctex_tree_sp_child_idx,      /* child */
1422
 
    synctex_tree_spc_friend_idx,    /* friend */
1423
 
    synctex_tree_spcf_last_idx,     /* last */
1424
 
    -1, /* next_hbox */
1425
 
    -1, /* arg_sibling */
1426
 
    -1, /* target */
1427
 
    synctex_tree_spcfl_vbox_max
1428
 
};
1429
 
 
1430
 
#define SYNCTEX_DFLT_COLUMN -1
1431
 
 
1432
 
DEFINE_SYNCTEX_DATA_INT_GETSET(column)
1433
 
static synctex_status_t _synctex_data_decode_column(synctex_node_p node) {
1434
 
    if (_synctex_data_has_column(node)) {
1435
 
        synctex_is_s is = _synctex_decode_int_opt(node->class_->scanner,
1436
 
            SYNCTEX_DFLT_COLUMN);
1437
 
        if (is.status == SYNCTEX_STATUS_OK) {
1438
 
            _synctex_data_set_column(node,is.integer);
1439
 
        }
1440
 
        return is.status;
1441
 
    }
1442
 
    return SYNCTEX_STATUS_BAD_ARGUMENT;
1443
 
}
1444
 
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(h)
1445
 
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE_v(v)
1446
 
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(width)
1447
 
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(height)
1448
 
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(depth)
1449
 
 
1450
 
SYNCTEX_INLINE static void _synctex_data_set_tlc(synctex_node_p node, synctex_node_p model) {
1451
 
    _synctex_data_set_tag(node, _synctex_data_tag(model));
1452
 
    _synctex_data_set_line(node, _synctex_data_line(model));
1453
 
    _synctex_data_set_column(node, _synctex_data_column(model));
1454
 
}
1455
 
SYNCTEX_INLINE static void _synctex_data_set_tlchv(synctex_node_p node, synctex_node_p model) {
1456
 
    _synctex_data_set_tlc(node,model);
1457
 
    _synctex_data_set_h(node, _synctex_data_h(model));
1458
 
    _synctex_data_set_v(node, _synctex_data_v(model));
1459
 
}
1460
 
 
1461
 
static const synctex_data_model_s synctex_data_model_box = {
1462
 
    synctex_data_tag_idx, /* tag */
1463
 
    synctex_data_line_idx,  /* line */
1464
 
    synctex_data_column_idx,/* column */
1465
 
    synctex_data_h_idx,     /* h */
1466
 
    synctex_data_v_idx,     /* v */
1467
 
    synctex_data_width_idx, /* width */
1468
 
    synctex_data_height_idx,/* height */
1469
 
    synctex_data_depth_idx, /* depth */
1470
 
    -1, /* mean_line */
1471
 
    -1, /* weight */
1472
 
    -1, /* h_V */
1473
 
    -1, /* v_V */
1474
 
    -1, /* width_V */
1475
 
    -1, /* height_V */
1476
 
    -1, /* depth_V */
1477
 
    -1, /* name */
1478
 
    -1, /* page */
1479
 
    synctex_data_box_max
1480
 
};
1481
 
static const synctex_tlcpector_s synctex_tlcpector_default = {
1482
 
    &_synctex_data_tag, /* tag */
1483
 
    &_synctex_data_line, /* line */
1484
 
    &_synctex_data_column, /* column */
1485
 
};
1486
 
static const synctex_inspector_s synctex_inspector_box = {
1487
 
    &_synctex_data_h,
1488
 
    &_synctex_data_v,
1489
 
    &_synctex_data_width,
1490
 
    &_synctex_data_height,
1491
 
    &_synctex_data_depth,
1492
 
};
1493
 
static float __synctex_node_visible_h(synctex_node_p node);
1494
 
static float __synctex_node_visible_v(synctex_node_p node);
1495
 
static float __synctex_node_visible_width(synctex_node_p node);
1496
 
static float __synctex_node_visible_height(synctex_node_p node);
1497
 
static float __synctex_node_visible_depth(synctex_node_p node);
1498
 
static synctex_vispector_s synctex_vispector_box = {
1499
 
    &__synctex_node_visible_h,
1500
 
    &__synctex_node_visible_v,
1501
 
    &__synctex_node_visible_width,
1502
 
    &__synctex_node_visible_height,
1503
 
    &__synctex_node_visible_depth,
1504
 
};
 
431
DEFINE_synctex_new_NODE(vbox)
 
432
 
 
433
static void _synctex_log_vbox(synctex_node_t node);
 
434
static void _synctex_display_vbox(synctex_node_t node);
 
435
 
1505
436
/*  These are static class objects, each scanner will make a copy of them and setup the scanner field.
1506
437
 */
1507
 
static synctex_class_s synctex_class_vbox = {
1508
 
    NULL,                       /*  No scanner yet */
1509
 
    synctex_node_type_vbox,     /*  Node type */
1510
 
    &_synctex_new_vbox,         /*  creator */
1511
 
    &_synctex_free_node,        /*  destructor */
1512
 
    &_synctex_log_vbox,         /*  log */
1513
 
    &_synctex_display_vbox,     /*  display */
1514
 
    &_synctex_abstract_vbox,    /*  abstract */
1515
 
    &synctex_tree_model_vbox,   /*  tree model */
1516
 
    &synctex_data_model_box,    /*  data model */
1517
 
    &synctex_tlcpector_default, /*  tlcpector */
1518
 
    &synctex_inspector_box,     /*  inspector */
1519
 
    &synctex_vispector_box,     /*  vispector */
 
438
static _synctex_class_t synctex_class_vbox = {
 
439
        NULL,                       /*  No scanner yet */
 
440
        synctex_node_type_vbox,     /*  Node type */
 
441
        &_synctex_new_vbox,         /*  creator */
 
442
        &_synctex_free_node,        /*  destructor */
 
443
        &_synctex_log_vbox,          /*  log */
 
444
        &_synctex_display_vbox,     /*  display */
 
445
        &_synctex_implementation_0, /*  parent */
 
446
        &_synctex_implementation_1, /*  child */
 
447
        &_synctex_implementation_2, /*  sibling */
 
448
        &_synctex_implementation_3, /*  friend */
 
449
        &_synctex_implementation_4, /*  next hbox */
 
450
        (_synctex_info_getter_t)&_synctex_implementation_5
1520
451
};
1521
452
 
1522
 
#       ifdef SYNCTEX_NOTHING
1523
 
#       pragma mark hbox.
1524
 
#   endif
1525
 
 
1526
453
/*  Horizontal boxes must contain visible size, because 0 width does not mean emptiness.
1527
454
 *  They also contain an average of the line numbers of the containing nodes. */
1528
 
 
1529
 
static const synctex_tree_model_s synctex_tree_model_hbox = {
1530
 
    synctex_tree_sibling_idx,       /* sibling */
1531
 
    synctex_tree_s_parent_idx,      /* parent */
1532
 
    synctex_tree_sp_child_idx,      /* child */
1533
 
    synctex_tree_spc_friend_idx,    /* friend */
1534
 
    synctex_tree_spcf_last_idx,     /* last */
1535
 
    synctex_tree_spcfl_next_hbox_idx, /* next_hbox */
1536
 
    -1, /* arg_sibling */
1537
 
    -1, /* target */
1538
 
    synctex_tree_spcfln_hbox_max
1539
 
};
1540
 
 
1541
 
DEFINE_SYNCTEX_DATA_INT_GETSET(mean_line)
1542
 
DEFINE_SYNCTEX_DATA_INT_GETSET(weight)
1543
 
DEFINE_SYNCTEX_DATA_INT_GETSET(h_V)
1544
 
DEFINE_SYNCTEX_DATA_INT_GETSET(v_V)
1545
 
DEFINE_SYNCTEX_DATA_INT_GETSET(width_V)
1546
 
DEFINE_SYNCTEX_DATA_INT_GETSET(height_V)
1547
 
DEFINE_SYNCTEX_DATA_INT_GETSET(depth_V)
1548
 
 
1549
 
/**
1550
 
 *  The hbox model.
1551
 
 *  It contains V variants of geometrical information.
1552
 
 *  It happens that hboxes contain material that is not used to compute
1553
 
 *  the bounding box. Some letters may appear out of the box given by TeX.
1554
 
 *  In such a situation, the visible bouding box is bigger ence the V variant.
1555
 
 *  Only hboxes have such variant. It does not make sense for void boxes
1556
 
 *  and it is not used here for vboxes.
1557
 
 *  - author: JL
1558
 
 */
1559
 
 
1560
 
static const synctex_data_model_s synctex_data_model_hbox = {
1561
 
    synctex_data_tag_idx, /* tag */
1562
 
    synctex_data_line_idx,  /* line */
1563
 
    synctex_data_column_idx,/* column */
1564
 
    synctex_data_h_idx,     /* h */
1565
 
    synctex_data_v_idx,     /* v */
1566
 
    synctex_data_width_idx, /* width */
1567
 
    synctex_data_height_idx,/* height */
1568
 
    synctex_data_depth_idx, /* depth */
1569
 
    synctex_data_mean_line_idx, /* mean_line */
1570
 
    synctex_data_weight_idx, /* weight */
1571
 
    synctex_data_h_V_idx, /* h_V */
1572
 
    synctex_data_v_V_idx, /* v_V */
1573
 
    synctex_data_width_V_idx, /* width_V */
1574
 
    synctex_data_height_V_idx, /* height_V */
1575
 
    synctex_data_depth_V_idx, /* depth_V */
1576
 
    -1, /* name */
1577
 
    -1, /* page */
1578
 
    synctex_data_hbox_max
1579
 
};
 
455
#   define SYNCTEX_MEAN_LINE_IDX (SYNCTEX_DEPTH_IDX+1)
 
456
#   define SYNCTEX_NODE_WEIGHT_IDX (SYNCTEX_MEAN_LINE_IDX+1)
 
457
#   define SYNCTEX_HORIZ_V_IDX (SYNCTEX_NODE_WEIGHT_IDX+1)
 
458
#   define SYNCTEX_VERT_V_IDX (SYNCTEX_HORIZ_V_IDX+1)
 
459
#   define SYNCTEX_WIDTH_V_IDX (SYNCTEX_VERT_V_IDX+1)
 
460
#   define SYNCTEX_HEIGHT_V_IDX (SYNCTEX_WIDTH_V_IDX+1)
 
461
#   define SYNCTEX_DEPTH_V_IDX (SYNCTEX_HEIGHT_V_IDX+1)
 
462
/*  the corresponding info accessors */
 
463
#   define SYNCTEX_MEAN_LINE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_MEAN_LINE_IDX].INT
 
464
#   define SYNCTEX_NODE_WEIGHT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_NODE_WEIGHT_IDX].INT
 
465
#   define SYNCTEX_HORIZ_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HORIZ_V_IDX].INT
 
466
#   define SYNCTEX_VERT_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_VERT_V_IDX].INT
 
467
#   define SYNCTEX_WIDTH_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_WIDTH_V_IDX].INT
 
468
#   define SYNCTEX_HEIGHT_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HEIGHT_V_IDX].INT
 
469
#   define SYNCTEX_DEPTH_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_DEPTH_V_IDX].INT
 
470
#   define SYNCTEX_ABS_WIDTH_V(NODE) ((SYNCTEX_WIDTH_V(NODE)>0?SYNCTEX_WIDTH_V(NODE):-SYNCTEX_WIDTH_V(NODE)))
 
471
#   define SYNCTEX_ABS_HEIGHT_V(NODE) ((SYNCTEX_HEIGHT_V(NODE)>0?SYNCTEX_HEIGHT_V(NODE):-SYNCTEX_HEIGHT_V(NODE)))
 
472
#   define SYNCTEX_ABS_DEPTH_V(NODE) ((SYNCTEX_DEPTH_V(NODE)>0?SYNCTEX_DEPTH_V(NODE):-SYNCTEX_DEPTH_V(NODE)))
1580
473
 
1581
474
typedef struct {
1582
475
    SYNCTEX_DECLARE_CHARINDEX
1583
 
    synctex_class_p class_;
1584
 
    synctex_data_u data[synctex_tree_spcfln_hbox_max+synctex_data_hbox_max];
1585
 
} synctex_node_hbox_s;
 
476
        synctex_class_t class;
 
477
        synctex_info_t implementation[5+SYNCTEX_DEPTH_V_IDX+1]; /*parent,child,sibling,friend,next box,
 
478
                                                *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
 
479
                                                *  SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH,
 
480
                        *  SYNCTEX_MEAN_LINE,SYNCTEX_NODE_WEIGHT,
 
481
                                                *  SYNCTEX_HORIZ_V,SYNCTEX_VERT_V,SYNCTEX_WIDTH_V,SYNCTEX_HEIGHT_V,SYNCTEX_DEPTH_V*/
 
482
} synctex_node_hbox_t;
1586
483
 
1587
484
/*  horizontal box node creator */
1588
 
DEFINE_synctex_new_scanned_NODE(hbox)
1589
 
 
1590
 
static void _synctex_log_hbox(synctex_node_p node);
1591
 
static char * _synctex_abstract_hbox(synctex_node_p node);
1592
 
static void _synctex_display_hbox(synctex_node_p node);
1593
 
 
1594
 
static synctex_class_s synctex_class_hbox = {
1595
 
    NULL,                       /*  No scanner yet */
1596
 
    synctex_node_type_hbox,     /*  Node type */
1597
 
    &_synctex_new_hbox,         /*  creator */
1598
 
    &_synctex_free_node,        /*  destructor */
1599
 
    &_synctex_log_hbox,         /*  log */
1600
 
    &_synctex_display_hbox,     /*  display */
1601
 
    &_synctex_abstract_hbox,    /*  abstract */
1602
 
    &synctex_tree_model_hbox,   /*  tree model */
1603
 
    &synctex_data_model_hbox,   /*  data model */
1604
 
    &synctex_tlcpector_default, /*  tlcpector */
1605
 
    &synctex_inspector_box,     /*  inspector */
1606
 
    &synctex_vispector_box,     /*  vispector */
 
485
DEFINE_synctex_new_NODE(hbox)
 
486
 
 
487
static void _synctex_display_hbox(synctex_node_t node);
 
488
static void _synctex_log_hbox(synctex_node_t node);
 
489
 
 
490
 
 
491
static _synctex_class_t synctex_class_hbox = {
 
492
        NULL,                       /*  No scanner yet */
 
493
        synctex_node_type_hbox,     /*  Node type */
 
494
        &_synctex_new_hbox,         /*  creator */
 
495
        &_synctex_free_node,        /*  destructor */
 
496
        &_synctex_log_hbox,    /*  log */
 
497
        &_synctex_display_hbox,     /*  display */
 
498
        &_synctex_implementation_0, /*  parent */
 
499
        &_synctex_implementation_1, /*  child */
 
500
        &_synctex_implementation_2, /*  sibling */
 
501
        &_synctex_implementation_3, /*  friend */
 
502
        &_synctex_implementation_4, /*  next hbox */
 
503
        (_synctex_info_getter_t)&_synctex_implementation_5
1607
504
};
1608
505
 
1609
 
#       ifdef SYNCTEX_NOTHING
1610
 
#       pragma mark void vbox.
1611
 
#   endif
1612
 
 
1613
506
/*  This void box node implementation is either horizontal or vertical
1614
507
 *  It does not contain a child field.
1615
508
 */
1616
 
static const synctex_tree_model_s synctex_tree_model_spf = {
1617
 
    synctex_tree_sibling_idx,   /* sibling */
1618
 
    synctex_tree_s_parent_idx,  /* parent */
1619
 
    -1, /* child */
1620
 
    synctex_tree_sp_friend_idx, /* friend */
1621
 
    -1, /* last */
1622
 
    -1, /* next_hbox */
1623
 
    -1, /* arg_sibling */
1624
 
    -1, /* target */
1625
 
    synctex_tree_spf_max
1626
 
};
1627
509
typedef struct {
1628
510
    SYNCTEX_DECLARE_CHARINDEX
1629
 
    synctex_class_p class_;
1630
 
    synctex_data_u data[synctex_tree_spf_max+synctex_data_box_max];
1631
 
} synctex_node_void_vbox_s;
 
511
        synctex_class_t class;
 
512
        synctex_info_t implementation[3+SYNCTEX_DEPTH_IDX+1]; /*  parent,sibling,friend,
 
513
                          *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
 
514
                                          *  SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH*/
 
515
} synctex_node_void_vbox_t;
1632
516
 
1633
517
/*  vertical void box node creator */
1634
 
DEFINE_synctex_new_scanned_NODE(void_vbox)
1635
 
 
1636
 
static void _synctex_log_void_box(synctex_node_p node);
1637
 
static char * _synctex_abstract_void_vbox(synctex_node_p node);
1638
 
static void _synctex_display_void_vbox(synctex_node_p node);
1639
 
 
1640
 
static synctex_class_s synctex_class_void_vbox = {
1641
 
    NULL,                       /*  No scanner yet */
1642
 
    synctex_node_type_void_vbox,/*  Node type */
1643
 
    &_synctex_new_void_vbox,    /*  creator */
1644
 
    &_synctex_free_leaf,        /*  destructor */
1645
 
    &_synctex_log_void_box,     /*  log */
1646
 
    &_synctex_display_void_vbox,/*  display */
1647
 
    &_synctex_abstract_void_vbox,/*  abstract */
1648
 
    &synctex_tree_model_spf,    /*  tree model */
1649
 
    &synctex_data_model_box,    /*  data model */
1650
 
    &synctex_tlcpector_default, /*  tlcpector */
1651
 
    &synctex_inspector_box,     /*  inspector */
1652
 
    &synctex_vispector_box,     /*  vispector */
 
518
DEFINE_synctex_new_NODE(void_vbox)
 
519
 
 
520
static void _synctex_log_void_box(synctex_node_t node);
 
521
static void _synctex_display_void_vbox(synctex_node_t node);
 
522
 
 
523
static _synctex_class_t synctex_class_void_vbox = {
 
524
        NULL,                       /*  No scanner yet */
 
525
        synctex_node_type_void_vbox,/*  Node type */
 
526
        &_synctex_new_void_vbox,    /*  creator */
 
527
        &_synctex_free_node,        /*  destructor */
 
528
        &_synctex_log_void_box,     /*  log */
 
529
        &_synctex_display_void_vbox,/*  display */
 
530
        &_synctex_implementation_0, /*  parent */
 
531
        NULL,                       /*  No child */
 
532
        &_synctex_implementation_1, /*  sibling */
 
533
        &_synctex_implementation_2, /*  friend */
 
534
        NULL,                                           /*  No next hbox */
 
535
        (_synctex_info_getter_t)&_synctex_implementation_3
1653
536
};
1654
537
 
1655
 
#       ifdef SYNCTEX_NOTHING
1656
 
#       pragma mark void hbox.
1657
 
#   endif
1658
 
 
1659
 
typedef synctex_node_void_vbox_s synctex_node_void_hbox_s;
 
538
typedef synctex_node_void_vbox_t synctex_node_void_hbox_t;
1660
539
 
1661
540
/*  horizontal void box node creator */
1662
 
DEFINE_synctex_new_scanned_NODE(void_hbox)
1663
 
 
1664
 
static char * _synctex_abstract_void_hbox(synctex_node_p node);
1665
 
static void _synctex_display_void_hbox(synctex_node_p node);
1666
 
 
1667
 
static synctex_class_s synctex_class_void_hbox = {
1668
 
    NULL,                       /*  No scanner yet */
1669
 
    synctex_node_type_void_hbox,/*  Node type */
1670
 
    &_synctex_new_void_hbox,    /*  creator */
1671
 
    &_synctex_free_leaf,        /*  destructor */
1672
 
    &_synctex_log_void_box,     /*  log */
1673
 
    &_synctex_display_void_hbox,/*  display */
1674
 
    &_synctex_abstract_void_hbox,/*  abstract */
1675
 
    &synctex_tree_model_spf,    /*  tree model */
1676
 
    &synctex_data_model_box,    /*  data model */
1677
 
    &synctex_tlcpector_default, /*  tlcpector */
1678
 
    &synctex_inspector_box,     /*  inspector */
1679
 
    &synctex_vispector_box,     /*  vispector */
1680
 
};
1681
 
 
1682
 
#       ifdef SYNCTEX_NOTHING
1683
 
#       pragma mark form ref.
1684
 
#   endif
1685
 
 
1686
 
/*  The form ref node.  */
1687
 
typedef struct {
1688
 
    SYNCTEX_DECLARE_CHARINDEX
1689
 
    synctex_class_p class_;
1690
 
    synctex_data_u data[synctex_tree_spfa_max+synctex_data_ref_thv_max];
1691
 
} synctex_node_ref_s;
1692
 
 
1693
 
/*  form ref node creator */
1694
 
DEFINE_synctex_new_scanned_NODE(ref)
1695
 
 
1696
 
static void _synctex_log_ref(synctex_node_p node);
1697
 
static char * _synctex_abstract_ref(synctex_node_p node);
1698
 
static void _synctex_display_ref(synctex_node_p node);
1699
 
 
1700
 
static const synctex_tree_model_s synctex_tree_model_spfa = {
1701
 
    synctex_tree_sibling_idx,   /* sibling */
1702
 
    synctex_tree_s_parent_idx,  /* parent */
1703
 
    -1, /* child */
1704
 
    synctex_tree_sp_friend_idx, /* friend */
1705
 
    -1, /* last */
1706
 
    -1, /* next_hbox */
1707
 
    synctex_tree_spf_arg_sibling_idx, /* arg_sibling */
1708
 
    -1, /* target */
1709
 
    synctex_tree_spfa_max
1710
 
};
1711
 
static const synctex_data_model_s synctex_data_model_ref = {
1712
 
    synctex_data_tag_idx, /* tag */
1713
 
    -1, /* line */
1714
 
    -1, /* column */
1715
 
    synctex_data_ref_h_idx, /* h */
1716
 
    synctex_data_ref_v_idx, /* v */
1717
 
    -1, /* width */
1718
 
    -1, /* height */
1719
 
    -1, /* depth */
1720
 
    -1, /* mean_line */
1721
 
    -1, /* weight */
1722
 
    -1, /* h_V */
1723
 
    -1, /* v_V */
1724
 
    -1, /* width_V */
1725
 
    -1, /* height_V */
1726
 
    -1, /* depth_V */
1727
 
    -1, /* name */
1728
 
    -1, /* page */
1729
 
    synctex_data_ref_thv_max /* size */
1730
 
};
1731
 
static synctex_class_s synctex_class_ref = {
1732
 
    NULL,                       /*  No scanner yet */
1733
 
    synctex_node_type_ref,      /*  Node type */
1734
 
    &_synctex_new_ref,          /*  creator */
1735
 
    &_synctex_free_leaf,        /*  destructor */
1736
 
    &_synctex_log_ref,          /*  log */
1737
 
    &_synctex_display_ref,      /*  display */
1738
 
    &_synctex_abstract_ref,     /*  abstract */
1739
 
    &synctex_tree_model_spfa,   /*  navigator */
1740
 
    &synctex_data_model_ref,    /*  data model */
1741
 
    &synctex_tlcpector_none,    /*  tlcpector */
1742
 
    &synctex_inspector_none,    /*  inspector */
1743
 
    &synctex_vispector_none,    /*  vispector */
1744
 
};
1745
 
#       ifdef SYNCTEX_NOTHING
1746
 
#       pragma mark small node.
1747
 
#   endif
1748
 
 
1749
 
/*  The small nodes correspond to glue, penalty, math and boundary nodes. */
1750
 
static const synctex_data_model_s synctex_data_model_tlchv = {
1751
 
    synctex_data_tag_idx, /* tag */
1752
 
    synctex_data_line_idx, /* line */
1753
 
    synctex_data_column_idx, /* column */
1754
 
    synctex_data_h_idx, /* h */
1755
 
    synctex_data_v_idx, /* v */
1756
 
    -1, /* width */
1757
 
    -1, /* height */
1758
 
    -1, /* depth */
1759
 
    -1, /* mean_line */
1760
 
    -1, /* weight */
1761
 
    -1, /* h_V */
1762
 
    -1, /* v_V */
1763
 
    -1, /* width_V */
1764
 
    -1, /* height_V */
1765
 
    -1, /* depth_V */
1766
 
    -1, /* name */
1767
 
    -1, /* page */
1768
 
    synctex_data_tlchv_max
1769
 
};
1770
 
 
1771
 
typedef struct {
1772
 
    SYNCTEX_DECLARE_CHARINDEX
1773
 
    synctex_class_p class_;
1774
 
    synctex_data_u data[synctex_tree_spf_max+synctex_data_tlchv_max];
1775
 
} synctex_node_tlchv_s;
1776
 
 
1777
 
static void _synctex_log_tlchv_node(synctex_node_p node);
1778
 
 
1779
 
#       ifdef SYNCTEX_NOTHING
1780
 
#       pragma mark math.
1781
 
#   endif
1782
 
 
1783
 
typedef synctex_node_tlchv_s synctex_node_math_s;
 
541
DEFINE_synctex_new_NODE(void_hbox)
 
542
 
 
543
static void _synctex_display_void_hbox(synctex_node_t node);
 
544
 
 
545
static _synctex_class_t synctex_class_void_hbox = {
 
546
        NULL,                       /*  No scanner yet */
 
547
        synctex_node_type_void_hbox,/*  Node type */
 
548
        &_synctex_new_void_hbox,    /*  creator */
 
549
        &_synctex_free_node,        /*  destructor */
 
550
        &_synctex_log_void_box,     /*  log */
 
551
        &_synctex_display_void_hbox,/*  display */
 
552
        &_synctex_implementation_0, /*  parent */
 
553
        NULL,                       /*  No child */
 
554
        &_synctex_implementation_1, /*  sibling */
 
555
        &_synctex_implementation_2, /*  friend */
 
556
        NULL,                                           /*  No next hbox */
 
557
        (_synctex_info_getter_t)&_synctex_implementation_3
 
558
};
 
559
 
 
560
/*  The medium nodes correspond to kern, glue, penalty and math nodes.
 
561
 *  In LuaTeX, the size of the nodes may have changed.  */
 
562
typedef struct {
 
563
    SYNCTEX_DECLARE_CHARINDEX
 
564
        synctex_class_t class;
 
565
        synctex_info_t implementation[3+SYNCTEX_WIDTH_IDX+1]; /*  parent,sibling,friend,
 
566
                          *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
 
567
                                          *  SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH */
 
568
} synctex_node_medium_t;
 
569
 
 
570
#define SYNCTEX_IS_BOX(NODE)\
 
571
        ((NODE->class->type == synctex_node_type_vbox)\
 
572
        || (NODE->class->type == synctex_node_type_void_vbox)\
 
573
        || (NODE->class->type == synctex_node_type_hbox)\
 
574
        || (NODE->class->type == synctex_node_type_void_hbox))
 
575
        
 
576
#define SYNCTEX_HAS_CHILDREN(NODE) (NODE && SYNCTEX_CHILD(NODE))
 
577
        
 
578
static void _synctex_log_medium_node(synctex_node_t node);
 
579
 
 
580
typedef synctex_node_medium_t synctex_node_math_t;
1784
581
 
1785
582
/*  math node creator */
1786
 
DEFINE_synctex_new_scanned_NODE(math)
1787
 
 
1788
 
static char * _synctex_abstract_math(synctex_node_p node);
1789
 
static void _synctex_display_math(synctex_node_p node);
1790
 
static synctex_inspector_s synctex_inspector_hv = {
1791
 
    &_synctex_data_h,
1792
 
    &_synctex_data_v,
1793
 
    &_synctex_int_none,
1794
 
    &_synctex_int_none,
1795
 
    &_synctex_int_none,
1796
 
};
1797
 
static synctex_vispector_s synctex_vispector_hv = {
1798
 
    &__synctex_node_visible_h,
1799
 
    &__synctex_node_visible_v,
1800
 
    &_synctex_float_none,
1801
 
    &_synctex_float_none,
1802
 
    &_synctex_float_none,
1803
 
};
1804
 
 
1805
 
static synctex_class_s synctex_class_math = {
1806
 
    NULL,                       /*  No scanner yet */
1807
 
    synctex_node_type_math,     /*  Node type */
1808
 
    &_synctex_new_math,         /*  creator */
1809
 
    &_synctex_free_leaf,        /*  destructor */
1810
 
    &_synctex_log_tlchv_node,   /*  log */
1811
 
    &_synctex_display_math,     /*  display */
1812
 
    &_synctex_abstract_math,    /*  abstract */
1813
 
    &synctex_tree_model_spf,    /*  tree model */
1814
 
    &synctex_data_model_tlchv,  /*  data model */
1815
 
    &synctex_tlcpector_default, /*  tlcpector */
1816
 
    &synctex_inspector_hv,      /*  inspector */
1817
 
    &synctex_vispector_hv,      /*  vispector */
1818
 
};
1819
 
 
1820
 
#       ifdef SYNCTEX_NOTHING
1821
 
#       pragma mark kern node.
1822
 
#   endif
1823
 
 
1824
 
static const synctex_data_model_s synctex_data_model_tlchvw = {
1825
 
    synctex_data_tag_idx,   /* tag */
1826
 
    synctex_data_line_idx,  /* line */
1827
 
    synctex_data_column_idx,/* column */
1828
 
    synctex_data_h_idx,     /* h */
1829
 
    synctex_data_v_idx,     /* v */
1830
 
    synctex_data_width_idx, /* width */
1831
 
    -1, /* height */
1832
 
    -1, /* depth */
1833
 
    -1, /* mean_line */
1834
 
    -1, /* weight */
1835
 
    -1, /* h_V */
1836
 
    -1, /* v_V */
1837
 
    -1, /* width_V */
1838
 
    -1, /* height_V */
1839
 
    -1, /* depth_V */
1840
 
    -1, /* name */
1841
 
    -1, /* page */
1842
 
    synctex_data_tlchvw_max
1843
 
};
1844
 
typedef struct {
1845
 
    SYNCTEX_DECLARE_CHARINDEX
1846
 
    synctex_class_p class_;
1847
 
    synctex_data_u data[synctex_tree_spf_max+synctex_data_tlchvw_max];
1848
 
} synctex_node_kern_s;
 
583
DEFINE_synctex_new_NODE(math)
 
584
 
 
585
static void _synctex_display_math(synctex_node_t node);
 
586
 
 
587
static _synctex_class_t synctex_class_math = {
 
588
        NULL,                       /*  No scanner yet */
 
589
        synctex_node_type_math,     /*  Node type */
 
590
        &_synctex_new_math,         /*  creator */
 
591
        &_synctex_free_leaf,        /*  destructor */
 
592
        &_synctex_log_medium_node,  /*  log */
 
593
        &_synctex_display_math,     /*  display */
 
594
        &_synctex_implementation_0, /*  parent */
 
595
        NULL,                       /*  No child */
 
596
        &_synctex_implementation_1, /*  sibling */
 
597
        &_synctex_implementation_2, /*  friend */
 
598
        NULL,                       /*  No next hbox */
 
599
        (_synctex_info_getter_t)&_synctex_implementation_3
 
600
};
 
601
 
 
602
typedef synctex_node_medium_t synctex_node_kern_t;
1849
603
 
1850
604
/*  kern node creator */
1851
 
DEFINE_synctex_new_scanned_NODE(kern)
1852
 
 
1853
 
static void _synctex_log_kern_node(synctex_node_p node);
1854
 
static char * _synctex_abstract_kern(synctex_node_p node);
1855
 
static void _synctex_display_kern(synctex_node_p node);
1856
 
 
1857
 
static synctex_inspector_s synctex_inspector_kern = {
1858
 
    &_synctex_data_h,
1859
 
    &_synctex_data_v,
1860
 
    &_synctex_data_width,
1861
 
    &_synctex_int_none,
1862
 
    &_synctex_int_none,
1863
 
};
1864
 
static float __synctex_kern_visible_h(synctex_node_p node);
1865
 
static float __synctex_kern_visible_width(synctex_node_p node);
1866
 
static synctex_vispector_s synctex_vispector_kern = {
1867
 
    &__synctex_kern_visible_h,
1868
 
    &__synctex_node_visible_v,
1869
 
    &__synctex_kern_visible_width,
1870
 
    &_synctex_float_none,
1871
 
    &_synctex_float_none,
1872
 
};
1873
 
 
1874
 
static synctex_class_s synctex_class_kern = {
1875
 
    NULL,                       /*  No scanner yet */
1876
 
    synctex_node_type_kern,     /*  Node type */
1877
 
    &_synctex_new_kern,         /*  creator */
1878
 
    &_synctex_free_leaf,        /*  destructor */
1879
 
    &_synctex_log_kern_node,    /*  log */
1880
 
    &_synctex_display_kern,     /*  display */
1881
 
    &_synctex_abstract_kern,    /*  abstract */
1882
 
    &synctex_tree_model_spf,    /*  tree model */
1883
 
    &synctex_data_model_tlchvw, /*  data model */
1884
 
    &synctex_tlcpector_default, /*  tlcpector */
1885
 
    &synctex_inspector_kern,    /*  inspector */
1886
 
    &synctex_vispector_kern,    /*  vispector */
1887
 
};
1888
 
 
1889
 
#       ifdef SYNCTEX_NOTHING
1890
 
#       pragma mark glue.
1891
 
#   endif
 
605
DEFINE_synctex_new_NODE(kern)
 
606
 
 
607
static void _synctex_display_kern(synctex_node_t node);
 
608
 
 
609
static _synctex_class_t synctex_class_kern = {
 
610
        NULL,                       /*  No scanner yet */
 
611
        synctex_node_type_kern,     /*  Node type */
 
612
        &_synctex_new_kern,         /*  creator */
 
613
        &_synctex_free_leaf,        /*  destructor */
 
614
        &_synctex_log_medium_node,  /*  log */
 
615
        &_synctex_display_kern,     /*  display */
 
616
        &_synctex_implementation_0, /*  parent */
 
617
        NULL,                       /*  No child */
 
618
        &_synctex_implementation_1, /*  sibling */
 
619
        &_synctex_implementation_2, /*  friend */
 
620
        NULL,                       /*  No next hbox */
 
621
        (_synctex_info_getter_t)&_synctex_implementation_3
 
622
};
 
623
 
 
624
/*  The small nodes correspond to glue and boundary nodes.  */
 
625
typedef struct {
 
626
    SYNCTEX_DECLARE_CHARINDEX
 
627
        synctex_class_t class;
 
628
        synctex_info_t implementation[3+SYNCTEX_VERT_IDX+1]; /*  parent,sibling,friend,
 
629
                          *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
 
630
                                          *  SYNCTEX_HORIZ,SYNCTEX_VERT */
 
631
} synctex_node_small_t;
 
632
 
 
633
static void _synctex_log_small_node(synctex_node_t node);
1892
634
 
1893
635
/*  glue node creator */
1894
 
typedef synctex_node_tlchv_s synctex_node_glue_s;
1895
 
DEFINE_synctex_new_scanned_NODE(glue)
1896
 
 
1897
 
static char * _synctex_abstract_glue(synctex_node_p node);
1898
 
static void _synctex_display_glue(synctex_node_p node);
1899
 
 
1900
 
static synctex_class_s synctex_class_glue = {
1901
 
    NULL,                       /*  No scanner yet */
1902
 
    synctex_node_type_glue,     /*  Node type */
1903
 
    &_synctex_new_glue,         /*  creator */
1904
 
    &_synctex_free_leaf,        /*  destructor */
1905
 
    &_synctex_log_tlchv_node,   /*  log */
1906
 
    &_synctex_display_glue,     /*  display */
1907
 
    &_synctex_abstract_glue,    /*  abstract */
1908
 
    &synctex_tree_model_spf,    /*  tree model */
1909
 
    &synctex_data_model_tlchv,  /*  data model */
1910
 
    &synctex_tlcpector_default, /*  tlcpector */
1911
 
    &synctex_inspector_hv,      /*  inspector */
1912
 
    &synctex_vispector_hv,      /*  vispector */
1913
 
};
1914
 
 
1915
 
/*  The small nodes correspond to glue and boundary nodes.  */
1916
 
 
1917
 
#       ifdef SYNCTEX_NOTHING
1918
 
#       pragma mark rule.
1919
 
#   endif
1920
 
 
1921
 
typedef struct {
1922
 
    SYNCTEX_DECLARE_CHARINDEX
1923
 
    synctex_class_p class_;
1924
 
    synctex_data_u data[synctex_tree_spf_max+synctex_data_box_max];
1925
 
} synctex_node_rule_s;
1926
 
 
1927
 
DEFINE_synctex_new_scanned_NODE(rule)
1928
 
 
1929
 
static void _synctex_log_rule(synctex_node_p node);
1930
 
static char * _synctex_abstract_rule(synctex_node_p node);
1931
 
static void _synctex_display_rule(synctex_node_p node);
1932
 
 
1933
 
static float __synctex_rule_visible_h(synctex_node_p node);
1934
 
static float __synctex_rule_visible_v(synctex_node_p node);
1935
 
static float __synctex_rule_visible_width(synctex_node_p node);
1936
 
static float __synctex_rule_visible_height(synctex_node_p node);
1937
 
static float __synctex_rule_visible_depth(synctex_node_p node);
1938
 
static synctex_vispector_s synctex_vispector_rule = {
1939
 
    &__synctex_rule_visible_h,
1940
 
    &__synctex_rule_visible_v,
1941
 
    &__synctex_rule_visible_width,
1942
 
    &__synctex_rule_visible_height,
1943
 
    &__synctex_rule_visible_depth,
1944
 
};
1945
 
 
1946
 
static synctex_class_s synctex_class_rule = {
1947
 
    NULL,                       /*  No scanner yet */
1948
 
    synctex_node_type_rule,     /*  Node type */
1949
 
    &_synctex_new_rule,         /*  creator */
1950
 
    &_synctex_free_leaf,        /*  destructor */
1951
 
    &_synctex_log_rule,         /*  log */
1952
 
    &_synctex_display_rule,     /*  display */
1953
 
    &_synctex_abstract_rule,    /*  abstract */
1954
 
    &synctex_tree_model_spf,    /*  tree model */
1955
 
    &synctex_data_model_box,    /*  data model */
1956
 
    &synctex_tlcpector_default, /*  tlcpector */
1957
 
    &synctex_inspector_box,     /*  inspector */
1958
 
    &synctex_vispector_rule,    /*  vispector */
1959
 
};
1960
 
 
1961
 
#       ifdef SYNCTEX_NOTHING
1962
 
#       pragma mark boundary.
1963
 
#   endif
 
636
typedef synctex_node_small_t synctex_node_glue_t;
 
637
DEFINE_synctex_new_NODE(glue)
 
638
static void _synctex_display_glue(synctex_node_t node);
 
639
 
 
640
static _synctex_class_t synctex_class_glue = {
 
641
        NULL,                       /*  No scanner yet */
 
642
        synctex_node_type_glue,     /*  Node type */
 
643
        &_synctex_new_glue,         /*  creator */
 
644
        &_synctex_free_leaf,        /*  destructor */
 
645
        &_synctex_log_medium_node,  /*  log */
 
646
        &_synctex_display_glue,     /*  display */
 
647
        &_synctex_implementation_0, /*  parent */
 
648
        NULL,                       /*  No child */
 
649
        &_synctex_implementation_1, /*  sibling */
 
650
        &_synctex_implementation_2, /*  friend */
 
651
        NULL,                       /*  No next hbox */
 
652
        (_synctex_info_getter_t)&_synctex_implementation_3
 
653
};
1964
654
 
1965
655
/*  boundary node creator */
1966
 
typedef synctex_node_tlchv_s synctex_node_boundary_s;
1967
 
DEFINE_synctex_new_scanned_NODE(boundary)
1968
 
 
1969
 
static char * _synctex_abstract_boundary(synctex_node_p node);
1970
 
static void _synctex_display_boundary(synctex_node_p node);
1971
 
 
1972
 
static synctex_class_s synctex_class_boundary = {
1973
 
    NULL,                       /*  No scanner yet */
1974
 
    synctex_node_type_boundary, /*  Node type */
1975
 
    &_synctex_new_boundary,     /*  creator */
1976
 
    &_synctex_free_leaf,        /*  destructor */
1977
 
    &_synctex_log_tlchv_node,   /*  log */
1978
 
    &_synctex_display_boundary, /*  display */
1979
 
    &_synctex_abstract_boundary,/*  abstract */
1980
 
    &synctex_tree_model_spf,    /*  tree model */
1981
 
    &synctex_data_model_tlchv,  /*  data model */
1982
 
    &synctex_tlcpector_default, /*  tlcpector */
1983
 
    &synctex_inspector_hv,      /*  inspector */
1984
 
    &synctex_vispector_hv,      /*  vispector */
1985
 
};
1986
 
 
1987
 
#       ifdef SYNCTEX_NOTHING
1988
 
#       pragma mark box boundary.
1989
 
#   endif
1990
 
 
1991
 
typedef struct {
1992
 
    SYNCTEX_DECLARE_CHARINDEX
1993
 
    synctex_class_p class_;
1994
 
    synctex_data_u data[synctex_tree_spfa_max+synctex_data_tlchv_max];
1995
 
} synctex_node_box_bdry_s;
1996
 
 
1997
 
#define DEFINE_synctex_new_unscanned_NODE(NAME)\
1998
 
SYNCTEX_INLINE static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner) {\
1999
 
    if (scanner) {\
2000
 
        synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));\
2001
 
        if (node) {\
2002
 
            node->class_ = scanner->class_+synctex_node_type_##NAME;\
2003
 
            SYNCTEX_DID_NEW(node); \
2004
 
        }\
2005
 
        return node;\
2006
 
    }\
2007
 
    return NULL;\
2008
 
}
2009
 
DEFINE_synctex_new_unscanned_NODE(box_bdry)
2010
 
 
2011
 
static char * _synctex_abstract_box_bdry(synctex_node_p node);
2012
 
static void _synctex_display_box_bdry(synctex_node_p node);
2013
 
 
2014
 
static synctex_class_s synctex_class_box_bdry = {
2015
 
    NULL,                       /*  No scanner yet */
2016
 
    synctex_node_type_box_bdry, /*  Node type */
2017
 
    &_synctex_new_box_bdry,     /*  creator */
2018
 
    &_synctex_free_leaf,        /*  destructor */
2019
 
    &_synctex_log_tlchv_node,   /*  log */
2020
 
    &_synctex_display_box_bdry, /*  display */
2021
 
    &_synctex_abstract_box_bdry,/*  display */
2022
 
    &synctex_tree_model_spfa,   /*  tree model */
2023
 
    &synctex_data_model_tlchv,  /*  data model */
2024
 
    &synctex_tlcpector_default, /*  tlcpector */
2025
 
    &synctex_inspector_hv,      /*  inspector */
2026
 
    &synctex_vispector_hv,      /*  vispector */
2027
 
};
2028
 
 
2029
 
#       ifdef SYNCTEX_NOTHING
2030
 
#       pragma mark hbox proxy.
2031
 
#   endif
2032
 
 
2033
 
/**
2034
 
 *  Standard nodes refer to TeX nodes: math, kern, boxes...
2035
 
 *  Proxy nodes are used to support forms.
2036
 
 *  A form is parsed as a tree of standard nodes starting
2037
 
 *  at the top left position.
2038
 
 *  When a reference is used, the form is duplicated
2039
 
 *  to the location specified by the reference.
2040
 
 *  As the same form can be duplicated at different locations,
2041
 
 *  the geometrical information is relative to its own top left point.
2042
 
 *  As we need absolute locations, we use proxy nodes.
2043
 
 *  A proxy node records an offset and the target node.
2044
 
 *  The target partly acts as a delegate.
2045
 
 *  The h and v position of the proxy node is the h and v
2046
 
 *  position of the target shifted by the proxy's offset.
2047
 
 *  The width, height and depth are not sensitive to offsets.
2048
 
 *  When are proxies created ?
2049
 
 *  1)  when the synctex file has been parsed, all the form refs
2050
 
 *  are replaced by proxies to the content of a form.
2051
 
 *  This content is a node with siblings (actually none).
2052
 
 *  Those root proxies have the parent of the ref they replace,
2053
 
 *  so their parents exist and are no proxy.
2054
 
 *  Moreover, if they have no sibling, it means that their target have no
2055
 
 *  sibling as well.
2056
 
 *  Such nodes are called root proxies.
2057
 
 *  2)  On the fly, when a proxy is asked for its child
2058
 
 *  (or sibling) and has none, a proxy to its target's child
2059
 
 *  (or sibling) is created if any. There are only 2 possible situations:
2060
 
 *  either the newly created proxy is the child of a proxy,
2061
 
 *  or it is the sibling of a proxy created on the fly.
2062
 
 *  In both cases, the parent is a proxy with children.
2063
 
 *  Such nodes are called child proxies.
2064
 
 *  How to compute the offset of a proxy ?
2065
 
 *  The offset of root proxy objects is exactly
2066
 
 *  the offset of the ref they replace.
2067
 
 *  The offset of other proxies is their owner's,
2068
 
 *  except when pointing to a root proxy.
2069
 
 *  What happens for cascading forms ?
2070
 
 *  Here is an example diagram
2071
 
 *
2072
 
 *  At parse time, the arrow means "owns":
2073
 
 *  sheet0 -> ref_to1
2074
 
 *
2075
 
 *            target1 -> ref_to2
2076
 
 *
2077
 
 *                       target2 -> child22
2078
 
 *
2079
 
 *  After replacing the refs:
2080
 
 *  sheet0 -> proxy00 -> proxy01 -> proxy02
2081
 
 *               |          |          |
2082
 
 *            target1 -> proxy11 -> proxy12
2083
 
 *                          |          |
2084
 
 *                       target2 -> proxy22
2085
 
 *
2086
 
 *  proxy00, proxy11 and proxy22 are root proxies.
2087
 
 *  Their offset is the one of the ref they replace
2088
 
 *  proxy01, proxy02 and proxy12 are child proxies.
2089
 
 *  Their proxy is the one of their parent.
2090
 
 *  Optimization.
2091
 
 *  After all the refs are replaced, there are only root nodes
2092
 
 *  targeting standard node. We make sure that each child proxy
2093
 
 *  also targets a standard node.
2094
 
 *  It is possible for a proxy to have a standard sibling 
2095
 
 *  whereas its target has no sibling at all. Root proxies
2096
 
 *  are such nodes, and are the only ones.
2097
 
 *  The consequence is that proxies created on the fly
2098
 
 *  must take into account this situation.
2099
 
 */
2100
 
 
2101
 
/*  A proxy to a hbox.
2102
 
 *  A proxy do have a target, which can be a proxy
2103
 
 */
2104
 
 
2105
 
static const synctex_tree_model_s synctex_tree_model_proxy_hbox = {
2106
 
    synctex_tree_sibling_idx,       /* sibling */
2107
 
    synctex_tree_s_parent_idx,      /* parent */
2108
 
    synctex_tree_sp_child_idx,      /* child */
2109
 
    synctex_tree_spc_friend_idx,    /* friend */
2110
 
    synctex_tree_spcf_last_idx,     /* last */
2111
 
    synctex_tree_spcfl_next_hbox_idx,   /* next_hbox */
2112
 
    -1, /* arg_sibling */
2113
 
    synctex_tree_spcfln_target_idx, /* target */
2114
 
    synctex_tree_spcflnt_proxy_hbox_max
2115
 
};
2116
 
static const synctex_data_model_s synctex_data_model_proxy = {
2117
 
    -1, /* tag */
2118
 
    -1, /* line */
2119
 
    -1, /* column */
2120
 
    synctex_data_proxy_h_idx, /* h */
2121
 
    synctex_data_proxy_v_idx, /* v */
2122
 
    -1, /* width */
2123
 
    -1, /* height */
2124
 
    -1, /* depth */
2125
 
    -1, /* mean_line */
2126
 
    -1, /* weight */
2127
 
    -1, /* h_V */
2128
 
    -1, /* v_V */
2129
 
    -1, /* width_V */
2130
 
    -1, /* height_V */
2131
 
    -1, /* depth_V */
2132
 
    -1, /* name */
2133
 
    -1, /* page */
2134
 
    synctex_data_proxy_hv_max
2135
 
};
2136
 
typedef struct {
2137
 
    SYNCTEX_DECLARE_CHARINDEX
2138
 
    synctex_class_p class_;
2139
 
    synctex_data_u data[synctex_tree_spcflnt_proxy_hbox_max+synctex_data_proxy_hv_max];
2140
 
} synctex_node_proxy_hbox_s;
2141
 
 
2142
 
/*  box proxy node creator */
2143
 
DEFINE_synctex_new_unscanned_NODE(proxy_hbox)
2144
 
 
2145
 
static void _synctex_log_proxy(synctex_node_p node);
2146
 
static char * _synctex_abstract_proxy_hbox(synctex_node_p node);
2147
 
static void _synctex_display_proxy_hbox(synctex_node_p node);
2148
 
 
2149
 
static int _synctex_proxy_tag(synctex_node_p);
2150
 
static int _synctex_proxy_line(synctex_node_p);
2151
 
static int _synctex_proxy_column(synctex_node_p);
2152
 
 
2153
 
static synctex_tlcpector_s synctex_tlcpector_proxy = {
2154
 
    &_synctex_proxy_tag,
2155
 
    &_synctex_proxy_line,
2156
 
    &_synctex_proxy_column,
2157
 
};
2158
 
static int _synctex_proxy_h(synctex_node_p);
2159
 
static int _synctex_proxy_v(synctex_node_p);
2160
 
static int _synctex_proxy_width(synctex_node_p);
2161
 
static int _synctex_proxy_height(synctex_node_p);
2162
 
static int _synctex_proxy_depth(synctex_node_p);
2163
 
static synctex_inspector_s synctex_inspector_proxy_box = {
2164
 
    &_synctex_proxy_h,
2165
 
    &_synctex_proxy_v,
2166
 
    &_synctex_proxy_width,
2167
 
    &_synctex_proxy_height,
2168
 
    &_synctex_proxy_depth,
2169
 
};
2170
 
 
2171
 
static float __synctex_proxy_visible_h(synctex_node_p);
2172
 
static float __synctex_proxy_visible_v(synctex_node_p);
2173
 
static float __synctex_proxy_visible_width(synctex_node_p);
2174
 
static float __synctex_proxy_visible_height(synctex_node_p);
2175
 
static float __synctex_proxy_visible_depth(synctex_node_p);
2176
 
 
2177
 
static synctex_vispector_s synctex_vispector_proxy_box = {
2178
 
    &__synctex_proxy_visible_h,
2179
 
    &__synctex_proxy_visible_v,
2180
 
    &__synctex_proxy_visible_width,
2181
 
    &__synctex_proxy_visible_height,
2182
 
    &__synctex_proxy_visible_depth,
2183
 
};
2184
 
 
2185
 
static synctex_class_s synctex_class_proxy_hbox = {
2186
 
    NULL,                           /*  No scanner yet */
2187
 
    synctex_node_type_proxy_hbox,   /*  Node type */
2188
 
    &_synctex_new_proxy_hbox,       /*  creator */
2189
 
    &_synctex_free_node,            /*  destructor */
2190
 
    &_synctex_log_proxy,            /*  log */
2191
 
    &_synctex_display_proxy_hbox,   /*  display */
2192
 
    &_synctex_abstract_proxy_hbox,  /*  abstract */
2193
 
    &synctex_tree_model_proxy_hbox, /*  tree model */
2194
 
    &synctex_data_model_proxy,      /*  data model */
2195
 
    &synctex_tlcpector_proxy,       /*  tlcpector */
2196
 
    &synctex_inspector_proxy_box,   /*  inspector */
2197
 
    &synctex_vispector_proxy_box,   /*  vispector */
2198
 
};
2199
 
 
2200
 
#       ifdef SYNCTEX_NOTHING
2201
 
#       pragma mark vbox proxy.
2202
 
#   endif
2203
 
 
2204
 
/*  A proxy to a vbox. */
2205
 
 
2206
 
static const synctex_tree_model_s synctex_tree_model_proxy_vbox = {
2207
 
    synctex_tree_sibling_idx,       /* sibling */
2208
 
    synctex_tree_s_parent_idx,      /* parent */
2209
 
    synctex_tree_sp_child_idx,      /* child */
2210
 
    synctex_tree_spc_friend_idx,    /* friend */
2211
 
    synctex_tree_spcf_last_idx, /* last */
2212
 
    -1, /* next_hbox */
2213
 
    -1, /* arg_sibling */
2214
 
    synctex_tree_spcfl_target_idx,    /* target */
2215
 
    synctex_tree_spcflt_proxy_vbox_max
2216
 
};
2217
 
 
2218
 
typedef struct {
2219
 
    SYNCTEX_DECLARE_CHARINDEX
2220
 
    synctex_class_p class_;
2221
 
    synctex_data_u data[synctex_tree_spcflt_proxy_vbox_max+synctex_data_proxy_hv_max];
2222
 
} synctex_node_proxy_vbox_s;
2223
 
 
2224
 
/*  box proxy node creator */
2225
 
DEFINE_synctex_new_unscanned_NODE(proxy_vbox)
2226
 
 
2227
 
static void _synctex_log_proxy(synctex_node_p node);
2228
 
static char * _synctex_abstract_proxy_vbox(synctex_node_p node);
2229
 
static void _synctex_display_proxy_vbox(synctex_node_p node);
2230
 
 
2231
 
static synctex_class_s synctex_class_proxy_vbox = {
2232
 
    NULL,                           /*  No scanner yet */
2233
 
    synctex_node_type_proxy_vbox,   /*  Node type */
2234
 
    &_synctex_new_proxy_vbox,       /*  creator */
2235
 
    &_synctex_free_node,            /*  destructor */
2236
 
    &_synctex_log_proxy,            /*  log */
2237
 
    &_synctex_display_proxy_vbox,   /*  display */
2238
 
    &_synctex_abstract_proxy_vbox,  /*  abstract */
2239
 
    &synctex_tree_model_proxy_vbox, /*  tree model */
2240
 
    &synctex_data_model_proxy,      /*  data model */
2241
 
    &synctex_tlcpector_proxy,       /*  tlcpector */
2242
 
    &synctex_inspector_proxy_box,   /*  inspector */
2243
 
    &synctex_vispector_proxy_box,   /*  vispector */
2244
 
};
2245
 
 
2246
 
#       ifdef SYNCTEX_NOTHING
2247
 
#       pragma mark proxy.
2248
 
#   endif
2249
 
 
2250
 
/**
2251
 
 *  A proxy to a node but a box.
2252
 
 */
2253
 
 
2254
 
static const synctex_tree_model_s synctex_tree_model_proxy = {
2255
 
    synctex_tree_sibling_idx,   /* sibling */
2256
 
    synctex_tree_s_parent_idx,  /* parent */
2257
 
    -1, /* child */
2258
 
    synctex_tree_sp_friend_idx, /* friend */
2259
 
    -1, /* last */
2260
 
    -1, /* next_hbox */
2261
 
    -1, /* arg_sibling */
2262
 
    synctex_tree_spf_target_idx,/* target */
2263
 
    synctex_tree_spft_proxy_max
2264
 
};
2265
 
 
2266
 
typedef struct {
2267
 
    SYNCTEX_DECLARE_CHARINDEX
2268
 
    synctex_class_p class_;
2269
 
    synctex_data_u data[synctex_tree_spft_proxy_max+synctex_data_proxy_hv_max];
2270
 
} synctex_node_proxy_s;
2271
 
 
2272
 
/*  proxy node creator */
2273
 
DEFINE_synctex_new_unscanned_NODE(proxy)
2274
 
 
2275
 
static void _synctex_log_proxy(synctex_node_p node);
2276
 
static char * _synctex_abstract_proxy(synctex_node_p node);
2277
 
static void _synctex_display_proxy(synctex_node_p node);
2278
 
 
2279
 
static synctex_vispector_s synctex_vispector_proxy = {
2280
 
    &__synctex_proxy_visible_h,
2281
 
    &__synctex_proxy_visible_v,
2282
 
    &__synctex_proxy_visible_width,
2283
 
    &_synctex_float_none,
2284
 
    &_synctex_float_none,
2285
 
};
2286
 
 
2287
 
static synctex_class_s synctex_class_proxy = {
2288
 
    NULL,                       /*  No scanner yet */
2289
 
    synctex_node_type_proxy,    /*  Node type */
2290
 
    &_synctex_new_proxy,        /*  creator */
2291
 
    &_synctex_free_leaf,        /*  destructor */
2292
 
    &_synctex_log_proxy,        /*  log */
2293
 
    &_synctex_display_proxy,    /*  display */
2294
 
    &_synctex_abstract_proxy,   /*  abstract */
2295
 
    &synctex_tree_model_proxy,  /*  tree model */
2296
 
    &synctex_data_model_proxy,  /*  data model */
2297
 
    &synctex_tlcpector_proxy,   /*  tlcpector */
2298
 
    &synctex_inspector_proxy_box,   /*  inspector */
2299
 
    &synctex_vispector_proxy,   /*  vispector */
2300
 
};
2301
 
 
2302
 
#       ifdef SYNCTEX_NOTHING
2303
 
#       pragma mark last proxy.
2304
 
#   endif
2305
 
 
2306
 
/**
2307
 
 *  A proxy to the last proxy/box boundary.
2308
 
 */
2309
 
 
2310
 
static const synctex_tree_model_s synctex_tree_model_proxy_last = {
2311
 
    synctex_tree_sibling_idx,   /* sibling */
2312
 
    synctex_tree_s_parent_idx,  /* parent */
2313
 
    -1, /* child */
2314
 
    synctex_tree_sp_friend_idx, /* friend */
2315
 
    -1, /* last */
2316
 
    -1, /* next_hbox */
2317
 
    synctex_tree_spf_arg_sibling_idx, /* arg_sibling */
2318
 
    synctex_tree_spfa_target_idx,     /* target */
2319
 
    synctex_tree_spfat_proxy_last_max
2320
 
};
2321
 
 
2322
 
typedef struct {
2323
 
    SYNCTEX_DECLARE_CHARINDEX
2324
 
    synctex_class_p class_;
2325
 
    synctex_data_u data[synctex_tree_spfat_proxy_last_max+synctex_data_proxy_hv_max];
2326
 
} synctex_node_proxy_last_s;
2327
 
 
2328
 
/*  proxy node creator */
2329
 
DEFINE_synctex_new_unscanned_NODE(proxy_last)
2330
 
 
2331
 
static void _synctex_log_proxy(synctex_node_p node);
2332
 
static char * _synctex_abstract_proxy(synctex_node_p node);
2333
 
static void _synctex_display_proxy(synctex_node_p node);
2334
 
 
2335
 
static synctex_class_s synctex_class_proxy_last = {
2336
 
    NULL,                           /*  No scanner yet */
2337
 
    synctex_node_type_proxy_last,   /*  Node type */
2338
 
    &_synctex_new_proxy,            /*  creator */
2339
 
    &_synctex_free_leaf,            /*  destructor */
2340
 
    &_synctex_log_proxy,            /*  log */
2341
 
    &_synctex_display_proxy,        /*  display */
2342
 
    &_synctex_abstract_proxy,       /*  abstract */
2343
 
    &synctex_tree_model_proxy_last, /*  tree model */
2344
 
    &synctex_data_model_proxy,      /*  data model */
2345
 
    &synctex_tlcpector_proxy,       /*  tlcpector */
2346
 
    &synctex_inspector_proxy_box,       /*  inspector */
2347
 
    &synctex_vispector_proxy,       /*  vispector */
2348
 
};
2349
 
 
2350
 
#       ifdef SYNCTEX_NOTHING
2351
 
#       pragma mark handle.
2352
 
#   endif
2353
 
 
2354
 
/**
2355
 
 *  A handle node.
2356
 
 *  A handle is never the target of a proxy
2357
 
 *  or another handle.
2358
 
 *  The child of a handle is always a handle if any.
2359
 
 *  The sibling of a handle is always a handle if any.
2360
 
 *  The parent of a handle is always a handle if any.
2361
 
 */
2362
 
 
2363
 
static const synctex_tree_model_s synctex_tree_model_handle = {
2364
 
    synctex_tree_sibling_idx,   /* sibling */
2365
 
    synctex_tree_s_parent_idx,  /* parent */
2366
 
    synctex_tree_sp_child_idx,  /* child */
2367
 
    -1, /* friend */
2368
 
    -1, /* last */
2369
 
    -1, /* next_hbox */
2370
 
    -1, /* arg_sibling */
2371
 
    synctex_tree_spc_target_idx,/* target */
2372
 
    synctex_tree_spct_handle_max
2373
 
};
2374
 
 
2375
 
static const synctex_data_model_s synctex_data_model_handle = {
2376
 
    -1, /* tag */
2377
 
    -1, /* line */
2378
 
    -1, /* column */
2379
 
    -1, /* h */
2380
 
    -1, /* v */
2381
 
    -1, /* width */
2382
 
    -1, /* height */
2383
 
    -1, /* depth */
2384
 
    -1, /* mean_line */
2385
 
    synctex_data_handle_w_idx, /* weight */
2386
 
    -1, /* h_V */
2387
 
    -1, /* v_V */
2388
 
    -1, /* width_V */
2389
 
    -1, /* height_V */
2390
 
    -1, /* depth_V */
2391
 
    -1, /* name */
2392
 
    -1, /* page */
2393
 
    synctex_data_handle_w_max
2394
 
};
2395
 
 
2396
 
typedef struct {
2397
 
    SYNCTEX_DECLARE_CHARINDEX
2398
 
    synctex_class_p class_;
2399
 
    synctex_data_u data[synctex_tree_spct_handle_max+synctex_data_handle_w_max];
2400
 
} synctex_node_handle_s;
2401
 
 
2402
 
/*  handle node creator */
2403
 
DEFINE_synctex_new_unscanned_NODE(handle)
2404
 
 
2405
 
static void _synctex_log_handle(synctex_node_p node);
2406
 
static char * _synctex_abstract_handle(synctex_node_p node);
2407
 
static void _synctex_display_handle(synctex_node_p node);
2408
 
 
2409
 
static synctex_class_s synctex_class_handle = {
2410
 
    NULL,                       /*  No scanner yet */
2411
 
    synctex_node_type_handle,   /*  Node type */
2412
 
    &_synctex_new_handle,       /*  creator */
2413
 
    &_synctex_free_handle,      /*  destructor */
2414
 
    &_synctex_log_handle,       /*  log */
2415
 
    &_synctex_display_handle,   /*  display */
2416
 
    &_synctex_abstract_handle,  /*  abstract */
2417
 
    &synctex_tree_model_handle, /*  tree model */
2418
 
    &synctex_data_model_handle, /*  data model */
2419
 
    &synctex_tlcpector_proxy,   /*  tlcpector */
2420
 
    &synctex_inspector_proxy_box,   /*  inspector */
2421
 
    &synctex_vispector_proxy_box,   /*  vispector */
2422
 
};
2423
 
 
2424
 
SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target) {
2425
 
    if (target) {
2426
 
        synctex_node_p result = _synctex_new_handle(target->class_->scanner);
2427
 
        if (result) {
2428
 
            _synctex_tree_set_target(result,target);
2429
 
            return result;
2430
 
        }
2431
 
    }
2432
 
    return NULL;
2433
 
}
2434
 
SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_child(synctex_node_p child) {
2435
 
    if (child) {
2436
 
        synctex_node_p result = _synctex_new_handle(child->class_->scanner);
2437
 
        if (result) {
2438
 
            _synctex_tree_set_child(result,child);
2439
 
            return result;
2440
 
        }
2441
 
    }
2442
 
    return NULL;
2443
 
}
 
656
typedef synctex_node_small_t synctex_node_boundary_t;
 
657
DEFINE_synctex_new_NODE(boundary)
 
658
 
 
659
static void _synctex_display_boundary(synctex_node_t node);
 
660
 
 
661
static _synctex_class_t synctex_class_boundary = {
 
662
        NULL,                       /*  No scanner yet */
 
663
        synctex_node_type_boundary,     /*  Node type */
 
664
        &_synctex_new_boundary, /*  creator */
 
665
        &_synctex_free_leaf,        /*  destructor */
 
666
        &_synctex_log_small_node,   /*  log */
 
667
        &_synctex_display_boundary,     /*  display */
 
668
        &_synctex_implementation_0, /*  parent */
 
669
        NULL,                       /*  No child */
 
670
        &_synctex_implementation_1, /*  sibling */
 
671
        &_synctex_implementation_2, /*  friend */
 
672
        NULL,                       /*  No next hbox */
 
673
        (_synctex_info_getter_t)&_synctex_implementation_3
 
674
};
 
675
 
 
676
#   define SYNCTEX_NAME_IDX (SYNCTEX_TAG_IDX+1)
 
677
#   define SYNCTEX_NAME(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_NAME_IDX].PTR
 
678
 
 
679
/*  Input nodes only know about their sibling, which is another input node.
 
680
 *  The synctex information is the SYNCTEX_TAG and SYNCTEX_NAME*/
 
681
typedef struct {
 
682
    SYNCTEX_DECLARE_CHARINDEX
 
683
        synctex_class_t class;
 
684
        synctex_info_t implementation[1+SYNCTEX_NAME_IDX+1]; /*  sibling,
 
685
                                  *  SYNCTEX_TAG,SYNCTEX_NAME */
 
686
} synctex_input_t;
 
687
 
 
688
#   define SYNCTEX_INPUT_MARK "Input:"
 
689
static synctex_node_t _synctex_new_input(synctex_scanner_t scanner) {
 
690
        if (scanner) {
 
691
                synctex_node_t node = _synctex_malloc(sizeof(synctex_input_t));
 
692
                if (node) {
 
693
            SYNCTEX_IMPLEMENT_CHARINDEX(node,strlen(SYNCTEX_INPUT_MARK));
 
694
                        node->class = scanner->class+synctex_node_type_input;
 
695
                }
 
696
                return node;
 
697
        }
 
698
        return NULL;
 
699
}
 
700
 
 
701
static void _synctex_free_input(synctex_node_t node){
 
702
        if (node) {
 
703
                SYNCTEX_FREE(SYNCTEX_SIBLING(node));
 
704
                free(SYNCTEX_NAME(node));
 
705
                free(node);
 
706
        }
 
707
}
 
708
 
 
709
static void _synctex_display_input(synctex_node_t node);
 
710
static void _synctex_log_input(synctex_node_t node);
 
711
 
 
712
static _synctex_class_t synctex_class_input = {
 
713
        NULL,                       /*  No scanner yet */
 
714
        synctex_node_type_input,    /*  Node type */
 
715
        &_synctex_new_input,        /*  creator */
 
716
        &_synctex_free_input,       /*  destructor */
 
717
        &_synctex_log_input,        /*  log */
 
718
        &_synctex_display_input,    /*  display */
 
719
        NULL,                       /*  No parent */
 
720
        NULL,                       /*  No child */
 
721
        &_synctex_implementation_0, /*  sibling */
 
722
        NULL,                       /*  No friend */
 
723
        NULL,                       /*  No next hbox */
 
724
        (_synctex_info_getter_t)&_synctex_implementation_1
 
725
};
2444
726
 
2445
727
#       ifdef SYNCTEX_NOTHING
2446
728
#       pragma mark -
2447
729
#       pragma mark Navigation
2448
730
#   endif
2449
 
synctex_node_p synctex_node_parent(synctex_node_p node)
2450
 
{
2451
 
    return _synctex_tree_parent(node);
2452
 
}
2453
 
synctex_node_p synctex_node_parent_sheet(synctex_node_p node)
2454
 
{
2455
 
    while(node && synctex_node_type(node) != synctex_node_type_sheet) {
2456
 
        node = _synctex_tree_parent(node);
2457
 
    }
2458
 
    /*  exit the while loop either when node is NULL or node is a sheet */
2459
 
    return node;
2460
 
}
2461
 
synctex_node_p synctex_node_parent_form(synctex_node_p node)
2462
 
{
2463
 
    while(node && synctex_node_type(node) != synctex_node_type_form) {
2464
 
        node = _synctex_tree_parent(node);
2465
 
    }
2466
 
    /*  exit the while loop either when node is NULL or node is a form */
2467
 
    return node;
2468
 
}
2469
 
 
2470
 
/**
2471
 
 *  The returned proxy will be the child or a sibling of source.
2472
 
 *  The returned proxy has no parent, child nor sibling.
2473
 
 *  Used only by __synctex_replace_ref.
2474
 
 *  argument to_node: a box, not a proxy nor anything else.
2475
 
 */
2476
 
SYNCTEX_INLINE static synctex_node_p __synctex_new_proxy_from_ref_to(synctex_node_p ref, synctex_node_p to_node) {
2477
 
    synctex_node_p proxy = NULL;
2478
 
    if (!ref || !to_node) {
2479
 
        return NULL;
2480
 
    }
2481
 
    switch(synctex_node_type(to_node)) {
2482
 
        case synctex_node_type_vbox:
2483
 
            proxy = _synctex_new_proxy_vbox(ref->class_->scanner);
2484
 
            break;
2485
 
        case synctex_node_type_hbox:
2486
 
            proxy = _synctex_new_proxy_hbox(ref->class_->scanner);
2487
 
            break;
2488
 
        default:
2489
 
            _synctex_error("!  __synctex_new_proxy_from_ref_to. Unexpected form child (%s). Please report.", synctex_node_isa(to_node));
2490
 
            return NULL;
2491
 
    }
2492
 
    if (!proxy) {
2493
 
        _synctex_error("!  __synctex_new_proxy_from_ref_to. Internal error. Please report.");
2494
 
        return NULL;
2495
 
    }
2496
 
    _synctex_data_set_h(proxy, _synctex_data_h(ref));
2497
 
    _synctex_data_set_v(proxy, _synctex_data_v(ref)-_synctex_data_height(to_node));
2498
 
    _synctex_tree_set_target(proxy,to_node);
2499
 
#   if defined(SYNCTEX_USE_CHARINDEX)
2500
 
    proxy->line_index=to_node?to_node->line_index:0;
2501
 
    proxy->char_index=to_node?to_node->char_index:0;
2502
 
#   endif
2503
 
    return proxy;
2504
 
}
2505
 
/**
2506
 
 *  The returned proxy will be the child or a sibling of owning_proxy.
2507
 
 *  The returned proxy has no parent, nor child.
2508
 
 *  Used only by synctex_node_child and synctex_node_sibling
2509
 
 *  to create proxies on the fly.
2510
 
 *  If the to_node has an already computed sibling,
2511
 
 *  then the returned proxy has itself a sibling
2512
 
 *  pointing to that already computed sibling.
2513
 
 */
2514
 
SYNCTEX_INLINE static synctex_node_p __synctex_new_child_proxy_to(synctex_node_p owner, synctex_node_p to_node) {
2515
 
    synctex_node_p proxy = NULL;
2516
 
    synctex_node_p target = to_node;
2517
 
    if (!owner) {
2518
 
        return NULL;
2519
 
    }
2520
 
    switch(synctex_node_type(target)) {
2521
 
        case synctex_node_type_vbox:
2522
 
            if ((proxy = _synctex_new_proxy_vbox(owner->class_->scanner))) {
2523
 
            exit_standard:
2524
 
                _synctex_data_set_h(proxy, _synctex_data_h(owner));
2525
 
                _synctex_data_set_v(proxy, _synctex_data_v(owner));
2526
 
            exit0:
2527
 
                _synctex_tree_set_target(proxy,target);
2528
 
#   if defined(SYNCTEX_USE_CHARINDEX)
2529
 
                proxy->line_index=to_node?to_node->line_index:0;
2530
 
                proxy->char_index=to_node?to_node->char_index:0;
2531
 
#   endif
2532
 
                return proxy;
2533
 
            };
2534
 
            break;
2535
 
        case synctex_node_type_proxy_vbox:
2536
 
            if ((proxy = _synctex_new_proxy_vbox(owner->class_->scanner))) {
2537
 
            exit_proxy:
2538
 
                target = _synctex_tree_target(to_node);
2539
 
                _synctex_data_set_h(proxy, _synctex_data_h(owner)+_synctex_data_h(to_node));
2540
 
                _synctex_data_set_v(proxy, _synctex_data_v(owner)+_synctex_data_v(to_node));
2541
 
                goto exit0;
2542
 
            };
2543
 
            break;
2544
 
        case synctex_node_type_hbox:
2545
 
            if ((proxy = _synctex_new_proxy_hbox(owner->class_->scanner))) {
2546
 
                goto exit_standard;
2547
 
            };
2548
 
            break;
2549
 
        case synctex_node_type_proxy_hbox:
2550
 
            if ((proxy = _synctex_new_proxy_hbox(owner->class_->scanner))) {
2551
 
                goto exit_proxy;
2552
 
            };
2553
 
            break;
2554
 
        case synctex_node_type_proxy:
2555
 
        case synctex_node_type_proxy_last:
2556
 
            if ((proxy = _synctex_new_proxy(owner->class_->scanner))) {
2557
 
                goto exit_proxy;
2558
 
            };
2559
 
            break;
2560
 
        default:
2561
 
            if ((proxy = _synctex_new_proxy(owner->class_->scanner))) {
2562
 
                goto exit_standard;
2563
 
            };
2564
 
            break;
2565
 
    }
2566
 
    _synctex_error("!  __synctex_new_child_proxy_to. "
2567
 
                   "Internal error. "
2568
 
                   "Please report.");
2569
 
    return NULL;
2570
 
}
2571
 
SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_sibling);
2572
 
typedef struct synctex_nns_t {
2573
 
    synctex_node_p first;
2574
 
    synctex_node_p last;
2575
 
    synctex_status_t status;
2576
 
} synctex_nns_s;
2577
 
/**
2578
 
 *  Given a target node, create a list of proxies.
2579
 
 *  The first proxy points to the target node,
2580
 
 *  its sibling points to the target's sibling and so on.
2581
 
 *  Returns the first created proxy, the last one and
2582
 
 *  an error status.
2583
 
 */
2584
 
SYNCTEX_INLINE static synctex_nns_s _synctex_new_child_proxies_to(synctex_node_p owner, synctex_node_p to_node) {
2585
 
    synctex_nns_s nns = {NULL,NULL,SYNCTEX_STATUS_OK};
2586
 
    if ((nns.first = nns.last = __synctex_new_child_proxy_to(owner,to_node))) {
2587
 
        synctex_node_p to_next_sibling = __synctex_tree_sibling(to_node);
2588
 
        synctex_node_p to_sibling;
2589
 
        while ((to_sibling = to_next_sibling)) {
2590
 
            synctex_node_p sibling;
2591
 
            if ((to_next_sibling = __synctex_tree_sibling(to_sibling))) {
2592
 
                /*  This is not the last sibling */
2593
 
                if((sibling = __synctex_new_child_proxy_to(owner,to_sibling))) {
2594
 
                    _synctex_tree_set_sibling(nns.last,sibling);
2595
 
                    nns.last = sibling;
2596
 
                    continue;
2597
 
                } else {
2598
 
                    _synctex_error("!  _synctex_new_child_proxy_to. "
2599
 
                                   "Internal error (1). "
2600
 
                                   "Please report.");
2601
 
                    nns.status = SYNCTEX_STATUS_ERROR;
2602
 
                }
2603
 
            } else if((sibling = _synctex_new_proxy_last(owner->class_->scanner))) {
2604
 
                _synctex_tree_set_sibling(nns.last,sibling);
2605
 
                nns.last = sibling;
2606
 
                _synctex_data_set_h(nns.last, _synctex_data_h(nns.first));
2607
 
                _synctex_data_set_v(nns.last, _synctex_data_v(nns.first));
2608
 
                _synctex_tree_set_target(nns.last,to_sibling);
2609
 
#   if defined(SYNCTEX_USE_CHARINDEX)
2610
 
                nns.last->line_index=to_sibling->line_index;
2611
 
                nns.last->char_index=to_sibling->char_index;
2612
 
#   endif
2613
 
            } else {
2614
 
                _synctex_error("!  _synctex_new_child_proxy_to. "
2615
 
                               "Internal error (2). "
2616
 
                               "Please report.");
2617
 
                nns.status = SYNCTEX_STATUS_ERROR;
2618
 
            }
2619
 
            break;
2620
 
        }
2621
 
    }
2622
 
    return nns;
2623
 
}
2624
 
static char * _synctex_node_abstract(synctex_node_p node);
2625
 
SYNCTEX_INLINE static synctex_node_p synctex_tree_set_friend(synctex_node_p node,synctex_node_p new_friend) {
2626
 
#if SYNCTEX_DEBUG
2627
 
    synctex_node_p F = new_friend;
2628
 
    while (F) {
2629
 
        if (node == F) {
2630
 
            printf("THIS IS AN ERROR\n");
2631
 
            F = new_friend;
2632
 
            while (F) {
2633
 
                printf("%s\n",_synctex_node_abstract(F));
2634
 
                if (node == F) {
2635
 
                    return NULL;
2636
 
                }
2637
 
                F = _synctex_tree_friend(F);
2638
 
            }
2639
 
            return NULL;
2640
 
        }
2641
 
        F = _synctex_tree_friend(F);
2642
 
    }
2643
 
#endif
2644
 
    return new_friend?_synctex_tree_set_friend(node,new_friend):_synctex_tree_reset_friend(node);
2645
 
}
2646
 
/**
2647
 
 *
2648
 
 */
2649
 
SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend(synctex_node_p node, int i) {
2650
 
    synctex_node_p old = NULL;
2651
 
    if (i>=0) {
2652
 
        i = i%(node->class_->scanner->number_of_lists);
2653
 
        old = synctex_tree_set_friend(node,(node->class_->scanner->lists_of_friends)[i]);
2654
 
        (node->class_->scanner->lists_of_friends)[i] = node;
2655
 
#if SYNCTEX_DEBUG>500
2656
 
        printf("tl(%i)=>",i);
2657
 
        synctex_node_log(node);
2658
 
        if (synctex_node_parent_form(node)) {
2659
 
            printf("!  ERROR. No registration expected!\n");
2660
 
        }
2661
 
#endif
2662
 
    }
2663
 
    return old;
2664
 
}
2665
 
/**
2666
 
 *  All proxies have tlc attributes, on behalf of their target.
2667
 
 *  The purpose is to register all af them.
2668
 
 *  - argument node: is the proxy, must not be NULL
2669
 
 */
2670
 
SYNCTEX_INLINE static synctex_node_p __synctex_proxy_make_friend_and_next_hbox(synctex_node_p node) {
2671
 
    synctex_node_p old = NULL;
2672
 
    synctex_node_p target = _synctex_tree_target(node);
2673
 
    if (target) {
2674
 
        int i = _synctex_data_tag(target)+_synctex_data_line(target);
2675
 
        old = __synctex_node_make_friend(node,i);
2676
 
    } else {
2677
 
        old = __synctex_tree_reset_friend(node);
2678
 
    }
2679
 
    if (synctex_node_type(node) == synctex_node_type_proxy_hbox) {
2680
 
        synctex_node_p sheet = synctex_node_parent_sheet(node);
2681
 
        if (sheet) {
2682
 
            _synctex_tree_set_next_hbox(node,_synctex_tree_next_hbox(sheet));
2683
 
            _synctex_tree_set_next_hbox(sheet,node);
2684
 
        }
2685
 
    }
2686
 
    return old;
2687
 
}
2688
 
/**
2689
 
 *  Register a node which have tag, line and column.
2690
 
 *  - argument node: the node
2691
 
 */
2692
 
SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend_tlc(synctex_node_p node) {
2693
 
    int i = synctex_node_tag(node)+synctex_node_line(node);
2694
 
    return __synctex_node_make_friend(node,i);
2695
 
}
2696
 
/**
2697
 
 *  Register a node which have tag, line and column.
2698
 
 *  Does nothing if the argument is NULL.
2699
 
 *  Calls __synctex_node_make_friend_tlc.
2700
 
 *  - argument node: the node
2701
 
 */
2702
 
SYNCTEX_INLINE static void _synctex_node_make_friend_tlc(synctex_node_p node) {
2703
 
    if (node) {
2704
 
        __synctex_node_make_friend_tlc(node);
2705
 
    }
2706
 
}
2707
 
static synctex_node_p _synctex_node_set_child(synctex_node_p node, synctex_node_p new_child);
2708
 
/**
2709
 
 *  The (first) child of the node, if any, NULL otherwise.
2710
 
 *  At parse time, non void box nodes have children.
2711
 
 *  All other nodes have no children.
2712
 
 *  In order to support pdf forms, proxies are created
2713
 
 *  to place form nodes at real locations.
2714
 
 *  Ref nodes are replaced by root proxies targeting
2715
 
 *  form contents. If root proxies have no children,
2716
 
 *  they are created on the fly as proxies to the
2717
 
 *  children of the targeted box.
2718
 
 *  As such, proxies created here are targeting a
2719
 
 *  node that belongs to a form.
2720
 
 *  This is the only place where child proxies are created.
2721
 
 */
2722
 
synctex_node_p synctex_node_child(synctex_node_p node) {
2723
 
    synctex_node_p child = NULL;
2724
 
    synctex_node_p target = NULL;
2725
 
    if ((child = _synctex_tree_child(node))) {
2726
 
        return child;
2727
 
    } else if ((target = _synctex_tree_target(node))) {
2728
 
        if ((child = synctex_node_child(target))) {
2729
 
            /*  This is a proxy with no child
2730
 
             *  which target does have a child. */
2731
 
            synctex_nns_s nns = _synctex_new_child_proxies_to(node, child);
2732
 
            if (nns.first) {
2733
 
                _synctex_node_set_child(node,nns.first);
2734
 
                return nns.first;
2735
 
            } else {
2736
 
                _synctex_error("!  synctex_node_child. Internal inconsistency. Please report.");
2737
 
            }
2738
 
        }
2739
 
    }
2740
 
    return NULL;
2741
 
}
2742
 
/*
2743
 
 *  Set the parent/child bound.
2744
 
 *  Things get complicated when new_child has siblings.
2745
 
 *  The caller is responsible for releasing the returned value.
2746
 
 */
2747
 
static synctex_node_p _synctex_node_set_child(synctex_node_p parent, synctex_node_p new_child) {
2748
 
    if (parent) {
2749
 
        synctex_node_p old = _synctex_tree_set_child(parent,new_child);
2750
 
        synctex_node_p last_child = NULL;
2751
 
        synctex_node_p child;
2752
 
        if ((child = old)) {
2753
 
            do {
2754
 
                _synctex_tree_reset_parent(child);
2755
 
            } while ((child = __synctex_tree_sibling(child)));
2756
 
        }
2757
 
        if ((child = new_child)) {
2758
 
            do {
2759
 
                _synctex_tree_set_parent(child,parent);
2760
 
                last_child = child;
2761
 
            } while ((child = __synctex_tree_sibling(child)));
2762
 
        }
2763
 
        _synctex_tree_set_last(parent,last_child);
2764
 
        return old;
2765
 
    }
2766
 
    return NULL;
2767
 
}
2768
 
 
2769
 
/*  The last child of the given node, or NULL.
2770
 
 */
2771
 
synctex_node_p synctex_node_last_child(synctex_node_p node) {
2772
 
    return _synctex_tree_last(node);
2773
 
}
2774
 
/**
2775
 
 *  All nodes siblings are properly set up at parse time
2776
 
 *  except for non root proxies.
2777
 
 */
2778
 
synctex_node_p synctex_node_sibling(synctex_node_p node) {
2779
 
    return node? __synctex_tree_sibling(node): NULL;
2780
 
}
2781
 
/**
2782
 
 *  All the _synctex_tree_... methods refer to the tree model.
2783
 
 *  __synctex_tree_... methods are low level.
2784
 
 */
2785
 
/**
2786
 
 *  Replace the sibling.
2787
 
 *  Connect to the arg_sibling of the new_sibling if relevant.
2788
 
 *  - returns the old sibling.
2789
 
 *  The caller is responsible for releasing the old sibling.
2790
 
 *  The bound to the parent is managed below.
2791
 
 */
2792
 
SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_sibling) {
2793
 
    if (node == new_sibling) {
2794
 
        printf("BOF\n");
2795
 
    }
2796
 
    synctex_node_p old = node? __synctex_tree_set_sibling(node,new_sibling): NULL;
2797
 
    _synctex_tree_set_arg_sibling(new_sibling,node);
2798
 
    return old;
2799
 
}
2800
 
/**
2801
 
 *  Replace the sibling.
2802
 
 *  Set the parent of the new sibling (and further siblings)
2803
 
 *  to the parent of the receiver.
2804
 
 *  Also set the last sibling of parent.
2805
 
 *  - argument new_sibling: must not be NULL.
2806
 
 *  - returns the old sibling.
2807
 
 *  The caller is responsible for releasing the old sibling.
2808
 
 */
2809
 
static synctex_node_p _synctex_node_set_sibling(synctex_node_p node, synctex_node_p new_sibling) {
2810
 
    if (node && new_sibling) {
2811
 
        synctex_node_p old = _synctex_tree_set_sibling(node,new_sibling);
2812
 
        if (_synctex_tree_has_parent(node)) {
2813
 
            synctex_node_p parent = __synctex_tree_parent(node);
2814
 
            if (parent) {
2815
 
                synctex_node_p N = new_sibling;
2816
 
                while (synctex_YES) {
2817
 
                    if (_synctex_tree_has_parent(N)) {
2818
 
                        __synctex_tree_set_parent(N,parent);
2819
 
                        _synctex_tree_set_last(parent,N);
2820
 
                        N = __synctex_tree_sibling(N);
2821
 
                        continue;
2822
 
                    } else if (N) {
2823
 
                        _synctex_error("!  synctex_node_sibling. "
2824
 
                                       "Internal inconsistency. "
2825
 
                                       "Please report.");
2826
 
                    }
2827
 
                    break;
2828
 
                }
2829
 
            }
2830
 
        }
2831
 
        return old;
2832
 
    }
2833
 
    return NULL;
2834
 
}
2835
 
/**
2836
 
 *  The last sibling of the given node, or NULL with node.
2837
 
 */
2838
 
synctex_node_p synctex_node_last_sibling(synctex_node_p node) {
2839
 
    synctex_node_p sibling;
2840
 
    do {
2841
 
        sibling = node;
2842
 
    } while((node = synctex_node_sibling(node)));
2843
 
    return sibling;
2844
 
}
2845
 
/**
2846
 
 *  The next nodes corresponds to a deep first tree traversal.
2847
 
 *  Does not create child proxies as side effect contrary to
2848
 
 *  the synctex_node_next method above.
2849
 
 *  May loop infinitely many times if the tree
2850
 
 *  is not properly built (contains loops).
2851
 
 */
2852
 
SYNCTEX_INLINE static synctex_node_p _synctex_node_sibling_or_parents(synctex_node_p node) {
2853
 
    while (node) {
2854
 
        synctex_node_p N;
2855
 
        if ((N = __synctex_tree_sibling(node))) {
2856
 
            return N;
2857
 
        } else if ((node = _synctex_tree_parent(node))) {
2858
 
            if (synctex_node_type(node) == synctex_node_type_sheet) {/*  EXC_BAD_ACCESS? */
2859
 
                return NULL;
2860
 
            } else if (synctex_node_type(node) == synctex_node_type_form) {
2861
 
                return NULL;
2862
 
            }
2863
 
        } else {
2864
 
            return NULL;
2865
 
        }
2866
 
    }
2867
 
    return NULL;
2868
 
}
2869
 
/**
2870
 
 *  The next nodes corresponds to a deep first tree traversal.
2871
 
 *  Creates child proxies as side effect.
2872
 
 *  May loop infinitely many times if the tree
2873
 
 *  is not properly built (contains loops).
2874
 
 */
2875
 
synctex_node_p synctex_node_next(synctex_node_p node) {
2876
 
    synctex_node_p N = synctex_node_child(node);
2877
 
    if (N) {
2878
 
        return N;
2879
 
    }
2880
 
    return _synctex_node_sibling_or_parents(node);
2881
 
}
2882
 
/**
2883
 
 *  The node which argument is the sibling.
2884
 
 *  - return: NULL if the argument has no parent or
2885
 
 *      is the first child of its parent.
2886
 
 *  - Input nodes have no arg siblings
2887
 
 */
2888
 
synctex_node_p synctex_node_arg_sibling(synctex_node_p node) {
2889
 
#if 1
2890
 
    return _synctex_tree_arg_sibling(node);
2891
 
#else
2892
 
    synctex_node_p N = _synctex_tree_parent(node);
2893
 
    if ((N = _synctex_tree_child(N))) {
2894
 
        do {
2895
 
            synctex_node_p NN = __synctex_tree_sibling(N);
2896
 
            if (NN == node) {
2897
 
                return N;
2898
 
            }
2899
 
            N = NN;
2900
 
        } while (N);
2901
 
    }
2902
 
    return N;
2903
 
#endif
 
731
synctex_node_t synctex_node_parent(synctex_node_t node)
 
732
{
 
733
        return SYNCTEX_PARENT(node);
 
734
}
 
735
synctex_node_t synctex_node_sheet(synctex_node_t node)
 
736
{
 
737
        while(node && node->class->type != synctex_node_type_sheet) {
 
738
                node = SYNCTEX_PARENT(node);
 
739
        }
 
740
        /*  exit the while loop either when node is NULL or node is a sheet */
 
741
        return node;
 
742
}
 
743
synctex_node_t synctex_node_child(synctex_node_t node)
 
744
{
 
745
        return SYNCTEX_CHILD(node);
 
746
}
 
747
synctex_node_t synctex_node_sibling(synctex_node_t node)
 
748
{
 
749
        return SYNCTEX_SIBLING(node);
 
750
}
 
751
synctex_node_t synctex_node_next(synctex_node_t node) {
 
752
        if (SYNCTEX_CHILD(node)) {
 
753
                return SYNCTEX_CHILD(node);
 
754
        }
 
755
sibling:
 
756
        if (SYNCTEX_SIBLING(node)) {
 
757
                return SYNCTEX_SIBLING(node);
 
758
        }
 
759
        if ((node = SYNCTEX_PARENT(node))) {
 
760
                if (node->class->type == synctex_node_type_sheet) {/*  EXC_BAD_ACCESS? */
 
761
                        return NULL;
 
762
                }
 
763
                goto sibling;
 
764
        }
 
765
        return NULL;
2904
766
}
2905
767
#       ifdef SYNCTEX_NOTHING
2906
768
#       pragma mark -
2908
770
#   endif
2909
771
 
2910
772
/*  Public node accessor: the type  */
2911
 
synctex_node_type_t synctex_node_type(synctex_node_p node) {
2912
 
    return node? node->class_->type: synctex_node_type_none;
2913
 
}
2914
 
 
2915
 
/*  Public node accessor: the type  */
2916
 
synctex_node_type_t synctex_node_target_type(synctex_node_p node) {
2917
 
    synctex_node_p target = _synctex_tree_target(node);
2918
 
    if (target) {
2919
 
        return (((target)->class_))->type;
2920
 
    } else if (node) {
2921
 
        return (((node)->class_))->type;
2922
 
    }
2923
 
    return synctex_node_type_none;
 
773
synctex_node_type_t synctex_node_type(synctex_node_t node) {
 
774
        if (node) {
 
775
                return (((node)->class))->type;
 
776
        }
 
777
        return synctex_node_type_error;
2924
778
}
2925
779
 
2926
780
/*  Public node accessor: the human readable type  */
2927
 
const char * synctex_node_isa(synctex_node_p node) {
2928
 
    static const char * isa[synctex_node_number_of_types] =
2929
 
    {"Not a node",
2930
 
        "input",
2931
 
        "sheet",
2932
 
        "form",
2933
 
        "ref",
2934
 
        "vbox",
2935
 
        "void vbox",
2936
 
        "hbox",
2937
 
        "void hbox",
2938
 
        "kern",
2939
 
        "glue",
2940
 
        "rule",
2941
 
        "math",
2942
 
        "boundary",
2943
 
        "box_bdry",
2944
 
        "proxy",
2945
 
        "last proxy",
2946
 
        "vbox proxy",
2947
 
        "hbox proxy",
2948
 
        "handle"};
2949
 
    return isa[synctex_node_type(node)];
 
781
const char * synctex_node_isa(synctex_node_t node) {
 
782
static const char * isa[synctex_node_number_of_types] =
 
783
                {"Not a node","input","sheet","vbox","void vbox","hbox","void hbox","kern","glue","math","boundary"};
 
784
        return isa[synctex_node_type(node)];
2950
785
}
2951
786
 
2952
787
#       ifdef SYNCTEX_NOTHING
2953
788
#       pragma mark -
2954
 
#       pragma mark LOG
 
789
#       pragma mark SYNCTEX_LOG
2955
790
#   endif
2956
791
 
 
792
#   define SYNCTEX_LOG(NODE) SYNCTEX_MSG_SEND(NODE,log)
 
793
 
2957
794
/*  Public node logger  */
2958
 
void synctex_node_log(synctex_node_p node) {
2959
 
    SYNCTEX_MSG_SEND(node,log);
2960
 
}
2961
 
 
2962
 
static void _synctex_log_input(synctex_node_p node) {
2963
 
    if (node) {
2964
 
        printf("%s:%i,%s(%i)\n",synctex_node_isa(node),
2965
 
               _synctex_data_tag(node),
2966
 
               _synctex_data_name(node),
2967
 
               _synctex_data_line(node));
2968
 
        printf("SELF:%p\n",(void *)node);
2969
 
        printf("    SIBLING:%p\n",
2970
 
               (void *)__synctex_tree_sibling(node));
2971
 
    }
2972
 
}
2973
 
 
2974
 
static void _synctex_log_sheet(synctex_node_p node) {
2975
 
    if (node) {
2976
 
        printf("%s:%i",synctex_node_isa(node),_synctex_data_page(node));
2977
 
        SYNCTEX_PRINT_CHARINDEX_NL;
2978
 
        printf("SELF:%p\n",(void *)node);
2979
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
2980
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
2981
 
        printf("    CHILD:%p\n",(void *)_synctex_tree_child(node));
2982
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
2983
 
        printf("    NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node));
2984
 
    }
2985
 
}
2986
 
 
2987
 
static void _synctex_log_form(synctex_node_p node) {
2988
 
    if (node) {
2989
 
        printf("%s:%i",synctex_node_isa(node),_synctex_data_tag(node));
2990
 
        SYNCTEX_PRINT_CHARINDEX_NL;
2991
 
        printf("SELF:%p\n",(void *)node);
2992
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
2993
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
2994
 
        printf("    CHILD:%p\n",(void *)_synctex_tree_child(node));
2995
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
2996
 
    }
2997
 
}
2998
 
 
2999
 
static void _synctex_log_ref(synctex_node_p node) {
3000
 
    if (node) {
3001
 
        printf("%s:%i:%i,%i",
3002
 
               synctex_node_isa(node),
3003
 
               _synctex_data_tag(node),
3004
 
               _synctex_data_h(node),
3005
 
               _synctex_data_v(node));
3006
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3007
 
        printf("SELF:%p\n",(void *)node);
3008
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3009
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
3010
 
    }
3011
 
}
3012
 
 
3013
 
static void _synctex_log_tlchv_node(synctex_node_p node) {
3014
 
    if (node) {
3015
 
        printf("%s:%i,%i,%i:%i,%i",
3016
 
               synctex_node_isa(node),
3017
 
               _synctex_data_tag(node),
3018
 
               _synctex_data_line(node),
3019
 
               _synctex_data_column(node),
3020
 
               _synctex_data_h(node),
3021
 
               _synctex_data_v(node));
3022
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3023
 
        printf("SELF:%p\n",(void *)node);
3024
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3025
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
3026
 
        printf("    CHILD:%p\n",(void *)_synctex_tree_child(node));
3027
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
3028
 
    }
3029
 
}
3030
 
 
3031
 
static void _synctex_log_kern_node(synctex_node_p node) {
3032
 
    if (node) {
3033
 
        printf("%s:%i,%i,%i:%i,%i:%i",
3034
 
               synctex_node_isa(node),
3035
 
               _synctex_data_tag(node),
3036
 
               _synctex_data_line(node),
3037
 
               _synctex_data_column(node),
3038
 
               _synctex_data_h(node),
3039
 
               _synctex_data_v(node),
3040
 
               _synctex_data_width(node));
3041
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3042
 
        printf("SELF:%p\n",(void *)node);
3043
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3044
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
3045
 
        printf("    CHILD:%p\n",(void *)_synctex_tree_child(node));
3046
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
3047
 
    }
3048
 
}
3049
 
 
3050
 
static void _synctex_log_rule(synctex_node_p node) {
3051
 
    if (node) {
3052
 
        printf("%s:%i,%i,%i:%i,%i",
3053
 
               synctex_node_isa(node),
3054
 
               _synctex_data_tag(node),
3055
 
               _synctex_data_line(node),
3056
 
               _synctex_data_column(node),
3057
 
               _synctex_data_h(node),
3058
 
               _synctex_data_v(node));
3059
 
        printf(":%i",_synctex_data_width(node));
3060
 
        printf(",%i",_synctex_data_height(node));
3061
 
        printf(",%i",_synctex_data_depth(node));
3062
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3063
 
        printf("SELF:%p\n",(void *)node);
3064
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3065
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
3066
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
3067
 
    }
3068
 
}
3069
 
 
3070
 
static void _synctex_log_void_box(synctex_node_p node) {
3071
 
    if (node) {
3072
 
        printf("%s",synctex_node_isa(node));
3073
 
        printf(":%i",_synctex_data_tag(node));
3074
 
        printf(",%i",_synctex_data_line(node));
3075
 
        printf(",%i",_synctex_data_column(node));
3076
 
        printf(":%i",_synctex_data_h(node));
3077
 
        printf(",%i",_synctex_data_v(node));
3078
 
        printf(":%i",_synctex_data_width(node));
3079
 
        printf(",%i",_synctex_data_height(node));
3080
 
        printf(",%i",_synctex_data_depth(node));
3081
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3082
 
        printf("SELF:%p\n",(void *)node);
3083
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3084
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
3085
 
        printf("    CHILD:%p\n",(void *)_synctex_tree_child(node));
3086
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
3087
 
    }
3088
 
}
3089
 
 
3090
 
static void _synctex_log_vbox(synctex_node_p node) {
3091
 
    if (node) {
3092
 
        printf("%s",synctex_node_isa(node));
3093
 
        printf(":%i",_synctex_data_tag(node));
3094
 
        printf(",%i",_synctex_data_line(node));
3095
 
        printf(",%i",_synctex_data_column(node));
3096
 
        printf(":%i",_synctex_data_h(node));
3097
 
        printf(",%i",_synctex_data_v(node));
3098
 
        printf(":%i",_synctex_data_width(node));
3099
 
        printf(",%i",_synctex_data_height(node));
3100
 
        printf(",%i",_synctex_data_depth(node));
3101
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3102
 
        printf("SELF:%p\n",(void *)node);
3103
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3104
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
3105
 
        printf("    CHILD:%p\n",(void *)_synctex_tree_child(node));
3106
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
3107
 
        printf("    NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node));
3108
 
    }
3109
 
}
3110
 
 
3111
 
static void _synctex_log_hbox(synctex_node_p node) {
3112
 
    if (node) {
3113
 
        printf("%s",synctex_node_isa(node));
3114
 
        printf(":%i",_synctex_data_tag(node));
3115
 
        printf(",%i~%i*%i",_synctex_data_line(node),_synctex_data_mean_line(node),_synctex_data_weight(node));
3116
 
        printf(",%i",_synctex_data_column(node));
3117
 
        printf(":%i",_synctex_data_h(node));
3118
 
        printf(",%i",_synctex_data_v(node));
3119
 
        printf(":%i",_synctex_data_width(node));
3120
 
        printf(",%i",_synctex_data_height(node));
3121
 
        printf(",%i",_synctex_data_depth(node));
3122
 
        printf("/%i",_synctex_data_h_V(node));
3123
 
        printf(",%i",_synctex_data_v_V(node));
3124
 
        printf(":%i",_synctex_data_width_V(node));
3125
 
        printf(",%i",_synctex_data_height_V(node));
3126
 
        printf(",%i",_synctex_data_depth_V(node));
3127
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3128
 
        printf("SELF:%p\n",(void *)node);
3129
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3130
 
        printf("    PARENT:%p\n",(void *)_synctex_tree_parent(node));
3131
 
        printf("    CHILD:%p\n",(void *)_synctex_tree_child(node));
3132
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
3133
 
        printf("    NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node));
3134
 
    }
3135
 
}
3136
 
static void _synctex_log_proxy(synctex_node_p node) {
3137
 
    if (node) {
3138
 
        synctex_node_p N = _synctex_tree_target(node);
3139
 
        printf("%s",synctex_node_isa(node));
3140
 
        printf(":%i",_synctex_data_h(node));
3141
 
        printf(",%i",_synctex_data_v(node));
3142
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3143
 
        printf("SELF:%p\n",(void *)node);
3144
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3145
 
        printf("    LEFT:%p\n",(void *)_synctex_tree_friend(node));
3146
 
        printf("    ->%s\n",_synctex_node_abstract(N));
3147
 
    }
3148
 
}
3149
 
static void _synctex_log_handle(synctex_node_p node) {
3150
 
    if (node) {
3151
 
        synctex_node_p N = _synctex_tree_target(node);
3152
 
        printf("%s",synctex_node_isa(node));
3153
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3154
 
        printf("SELF:%p\n",(void *)node);
3155
 
        printf("    SIBLING:%p\n",(void *)__synctex_tree_sibling(node));
3156
 
        printf("    ->%s\n",_synctex_node_abstract(N));
3157
 
    }
3158
 
}
3159
 
 
3160
 
#       ifdef SYNCTEX_NOTHING
3161
 
#       pragma mark -
3162
 
#       pragma mark SYNCTEX_DISPLAY
3163
 
#   endif
3164
 
 
3165
 
int synctex_scanner_display_switcher(synctex_scanner_p scanR) {
3166
 
    return scanR->display_switcher;
3167
 
}
3168
 
void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher) {
3169
 
    scanR->display_switcher = switcher;
3170
 
}
3171
 
static const char * const _synctex_display_prompt = "................................";
3172
 
 
3173
 
static char * _synctex_scanner_display_prompt_down(synctex_scanner_p scanR) {
3174
 
    if (scanR->display_prompt>_synctex_display_prompt) {
3175
 
        --scanR->display_prompt;
3176
 
    }
3177
 
    return scanR->display_prompt;
3178
 
}
3179
 
static char * _synctex_scanner_display_prompt_up(synctex_scanner_p scanR) {
3180
 
    if (scanR->display_prompt+1<_synctex_display_prompt+strlen(_synctex_display_prompt)) {
3181
 
        ++scanR->display_prompt;
3182
 
    }
3183
 
    return scanR->display_prompt;
3184
 
}
3185
 
 
3186
 
void synctex_node_display(synctex_node_p node) {
3187
 
    if (node) {
3188
 
        synctex_scanner_p scanR = node->class_->scanner;
3189
 
        if (scanR) {
3190
 
            if (scanR->display_switcher<0) {
3191
 
                SYNCTEX_MSG_SEND(node, display);
3192
 
            } else if (scanR->display_switcher>0 && --scanR->display_switcher>0) {
3193
 
                SYNCTEX_MSG_SEND(node, display);
3194
 
            } else if (scanR->display_switcher-->=0) {
3195
 
                printf("%s Next display skipped. Reset display switcher.\n",node->class_->scanner->display_prompt);
3196
 
            }
3197
 
        } else {
3198
 
            SYNCTEX_MSG_SEND(node, display);
3199
 
        }
3200
 
    }
3201
 
}
3202
 
static char * _synctex_node_abstract(synctex_node_p node) {
3203
 
    SYNCTEX_PARAMETER_ASSERT(node || node->class_);
3204
 
    return (node && node->class_->abstract)? node->class_->abstract(node):"none";
3205
 
}
3206
 
 
3207
 
SYNCTEX_INLINE static void _synctex_display_child(synctex_node_p node) {
3208
 
    synctex_node_p N = _synctex_tree_child(node);
3209
 
    if (N) {
3210
 
        _synctex_scanner_display_prompt_down(N->class_->scanner);
3211
 
        synctex_node_display(N);
3212
 
        _synctex_scanner_display_prompt_up(N->class_->scanner);
3213
 
    }
3214
 
}
3215
 
 
3216
 
SYNCTEX_INLINE static void _synctex_display_sibling(synctex_node_p node) {
3217
 
    synctex_node_display(__synctex_tree_sibling(node));
3218
 
}
3219
 
#define SYNCTEX_ABSTRACT_MAX 128
3220
 
static char * _synctex_abstract_input(synctex_node_p node) {
3221
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3222
 
    if (node) {
3223
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"Input:%i:%s(%i)" SYNCTEX_PRINT_CHARINDEX_FMT,
3224
 
               _synctex_data_tag(node),
3225
 
               _synctex_data_name(node),
3226
 
               _synctex_data_line(node)
3227
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3228
 
    }
3229
 
    return abstract;
3230
 
}
3231
 
 
3232
 
static void _synctex_display_input(synctex_node_p node) {
3233
 
    if (node) {
3234
 
        printf("Input:%i:%s(%i)"
3235
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3236
 
               "\n",
3237
 
               _synctex_data_tag(node),
3238
 
               _synctex_data_name(node),
3239
 
               _synctex_data_line(node)
3240
 
                SYNCTEX_PRINT_CHARINDEX_WHAT);
3241
 
        synctex_node_display(__synctex_tree_sibling(node));
3242
 
    }
3243
 
}
3244
 
 
3245
 
static char * _synctex_abstract_sheet(synctex_node_p node) {
3246
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3247
 
    if (node) {
3248
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"{%i...}" SYNCTEX_PRINT_CHARINDEX_FMT,
3249
 
               _synctex_data_page(node)
3250
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3251
 
    }
3252
 
    return abstract;
3253
 
}
3254
 
 
3255
 
static void _synctex_display_sheet(synctex_node_p node) {
3256
 
    if (node) {
3257
 
        printf("%s{%i"
3258
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3259
 
               "\n",
3260
 
               node->class_->scanner->display_prompt,
3261
 
               _synctex_data_page(node)
3262
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3263
 
        _synctex_display_child(node);
3264
 
        printf("%s}\n",node->class_->scanner->display_prompt);
3265
 
        _synctex_display_sibling(node);
3266
 
    }
3267
 
}
3268
 
 
3269
 
static char * _synctex_abstract_form(synctex_node_p node) {
3270
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3271
 
    if (node) {
3272
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"<%i...>" SYNCTEX_PRINT_CHARINDEX_FMT,
3273
 
               _synctex_data_tag(node)
3274
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3275
 
        SYNCTEX_PRINT_CHARINDEX;
3276
 
    }
3277
 
    return abstract;
3278
 
}
3279
 
 
3280
 
static void _synctex_display_form(synctex_node_p node) {
3281
 
    if (node) {
3282
 
        printf("%s<%i"
3283
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3284
 
               "\n",
3285
 
               node->class_->scanner->display_prompt,
3286
 
               _synctex_data_tag(node)
3287
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3288
 
        _synctex_display_child(node);
3289
 
        printf("%s>\n",node->class_->scanner->display_prompt);
3290
 
        _synctex_display_sibling(node);
3291
 
    }
3292
 
}
3293
 
 
3294
 
static char * _synctex_abstract_vbox(synctex_node_p node) {
3295
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3296
 
    if (node) {
3297
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"[%i,%i:%i,%i:%i,%i,%i...]"
3298
 
               SYNCTEX_PRINT_CHARINDEX_FMT,
3299
 
               _synctex_data_tag(node),
3300
 
               _synctex_data_line(node),
3301
 
               _synctex_data_h(node),
3302
 
               _synctex_data_v(node),
3303
 
               _synctex_data_width(node),
3304
 
               _synctex_data_height(node),
3305
 
               _synctex_data_depth(node)
3306
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3307
 
    }
3308
 
    return abstract;
3309
 
}
3310
 
 
3311
 
static void _synctex_display_vbox(synctex_node_p node) {
3312
 
    if (node) {
3313
 
        printf("%s[%i,%i:%i,%i:%i,%i,%i"
3314
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3315
 
               "\n",
3316
 
               node->class_->scanner->display_prompt,
3317
 
               _synctex_data_tag(node),
3318
 
               _synctex_data_line(node),
3319
 
               _synctex_data_h(node),
3320
 
               _synctex_data_v(node),
3321
 
               _synctex_data_width(node),
3322
 
               _synctex_data_height(node),
3323
 
               _synctex_data_depth(node)
3324
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3325
 
        _synctex_display_child(node);
3326
 
        printf("%s]\n%slast:%s\n",
3327
 
               node->class_->scanner->display_prompt,
3328
 
               node->class_->scanner->display_prompt,
3329
 
               _synctex_node_abstract(_synctex_tree_last(node)));
3330
 
        _synctex_display_sibling(node);
3331
 
    }
3332
 
}
3333
 
 
3334
 
static char * _synctex_abstract_hbox(synctex_node_p node) {
3335
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3336
 
    if (node) {
3337
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"(%i,%i~%i*%i:%i,%i:%i,%i,%i...)"
3338
 
               SYNCTEX_PRINT_CHARINDEX_FMT,
3339
 
               _synctex_data_tag(node),
3340
 
               _synctex_data_line(node),
3341
 
               _synctex_data_mean_line(node),
3342
 
               _synctex_data_weight(node),
3343
 
               _synctex_data_h(node),
3344
 
               _synctex_data_v(node),
3345
 
               _synctex_data_width(node),
3346
 
               _synctex_data_height(node),
3347
 
               _synctex_data_depth(node)
3348
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3349
 
    }
3350
 
    return abstract;
3351
 
}
3352
 
 
3353
 
static void _synctex_display_hbox(synctex_node_p node) {
3354
 
    if (node) {
3355
 
        printf("%s(%i,%i~%i*%i:%i,%i:%i,%i,%i"
3356
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3357
 
               "\n",
3358
 
               node->class_->scanner->display_prompt,
3359
 
               _synctex_data_tag(node),
3360
 
               _synctex_data_line(node),
3361
 
               _synctex_data_mean_line(node),
3362
 
               _synctex_data_weight(node),
3363
 
               _synctex_data_h(node),
3364
 
               _synctex_data_v(node),
3365
 
               _synctex_data_width(node),
3366
 
               _synctex_data_height(node),
3367
 
               _synctex_data_depth(node)
3368
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3369
 
        _synctex_display_child(node);
3370
 
        printf("%s)\n%slast:%s\n",
3371
 
               node->class_->scanner->display_prompt,
3372
 
               node->class_->scanner->display_prompt,
3373
 
               _synctex_node_abstract(_synctex_tree_last(node)));
3374
 
        _synctex_display_sibling(node);
3375
 
    }
3376
 
}
3377
 
 
3378
 
static char * _synctex_abstract_void_vbox(synctex_node_p node) {
3379
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3380
 
    if (node) {
3381
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"v%i,%i;%i,%i:%i,%i,%i"
3382
 
                       SYNCTEX_PRINT_CHARINDEX_FMT
3383
 
                       "\n",
3384
 
               _synctex_data_tag(node),
3385
 
               _synctex_data_line(node),
3386
 
               _synctex_data_h(node),
3387
 
               _synctex_data_v(node),
3388
 
               _synctex_data_width(node),
3389
 
               _synctex_data_height(node),
3390
 
               _synctex_data_depth(node)
3391
 
                       SYNCTEX_PRINT_CHARINDEX_WHAT);
3392
 
    }
3393
 
    return abstract;
3394
 
}
3395
 
 
3396
 
static void _synctex_display_void_vbox(synctex_node_p node) {
3397
 
    if (node) {
3398
 
        printf("%sv%i,%i;%i,%i:%i,%i,%i"
3399
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3400
 
               "\n",
3401
 
               node->class_->scanner->display_prompt,
3402
 
               _synctex_data_tag(node),
3403
 
               _synctex_data_line(node),
3404
 
               _synctex_data_h(node),
3405
 
               _synctex_data_v(node),
3406
 
               _synctex_data_width(node),
3407
 
               _synctex_data_height(node),
3408
 
               _synctex_data_depth(node)
3409
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3410
 
        _synctex_display_sibling(node);
3411
 
    }
3412
 
}
3413
 
 
3414
 
static char * _synctex_abstract_void_hbox(synctex_node_p node) {
3415
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3416
 
    if (node) {
3417
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"h%i,%i:%i,%i:%i,%i,%i"
3418
 
                       SYNCTEX_PRINT_CHARINDEX_FMT,
3419
 
               _synctex_data_tag(node),
3420
 
               _synctex_data_line(node),
3421
 
               _synctex_data_h(node),
3422
 
               _synctex_data_v(node),
3423
 
               _synctex_data_width(node),
3424
 
               _synctex_data_height(node),
3425
 
               _synctex_data_depth(node)
3426
 
                       SYNCTEX_PRINT_CHARINDEX_WHAT);
3427
 
    }
3428
 
    return abstract;
3429
 
}
3430
 
 
3431
 
static void _synctex_display_void_hbox(synctex_node_p node) {
3432
 
    if (node) {
3433
 
        printf("%sh%i,%i:%i,%i:%i,%i,%i"
3434
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3435
 
               "\n",
3436
 
               node->class_->scanner->display_prompt,
3437
 
               _synctex_data_tag(node),
3438
 
               _synctex_data_line(node),
3439
 
               _synctex_data_h(node),
3440
 
               _synctex_data_v(node),
3441
 
               _synctex_data_width(node),
3442
 
               _synctex_data_height(node),
3443
 
               _synctex_data_depth(node)
3444
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3445
 
        _synctex_display_sibling(node);
3446
 
    }
3447
 
}
3448
 
 
3449
 
static char * _synctex_abstract_glue(synctex_node_p node) {
3450
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3451
 
    if (node) {
3452
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"glue:%i,%i:%i,%i"
3453
 
                       SYNCTEX_PRINT_CHARINDEX_FMT,
3454
 
               _synctex_data_tag(node),
3455
 
               _synctex_data_line(node),
3456
 
               _synctex_data_h(node),
3457
 
               _synctex_data_v(node)
3458
 
                       SYNCTEX_PRINT_CHARINDEX_WHAT);
3459
 
    }
3460
 
    return abstract;
3461
 
}
3462
 
 
3463
 
static void _synctex_display_glue(synctex_node_p node) {
3464
 
    if (node) {
3465
 
        printf("%sglue:%i,%i:%i,%i"
3466
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3467
 
               "\n",
3468
 
               node->class_->scanner->display_prompt,
3469
 
               _synctex_data_tag(node),
3470
 
               _synctex_data_line(node),
3471
 
               _synctex_data_h(node),
3472
 
               _synctex_data_v(node)
3473
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3474
 
        _synctex_display_sibling(node);
3475
 
    }
3476
 
}
3477
 
 
3478
 
static char * _synctex_abstract_rule(synctex_node_p node) {
3479
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3480
 
    if (node) {
3481
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"rule:%i,%i:%i,%i:%i,%i,%i"
3482
 
               SYNCTEX_PRINT_CHARINDEX_FMT,
3483
 
               _synctex_data_tag(node),
3484
 
               _synctex_data_line(node),
3485
 
               _synctex_data_h(node),
3486
 
               _synctex_data_v(node),
3487
 
               _synctex_data_width(node),
3488
 
               _synctex_data_height(node),
3489
 
               _synctex_data_depth(node)
3490
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3491
 
    }
3492
 
    return abstract;
3493
 
}
3494
 
 
3495
 
static void _synctex_display_rule(synctex_node_p node) {
3496
 
    if (node) {
3497
 
        printf("%srule:%i,%i:%i,%i:%i,%i,%i"
3498
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3499
 
               "\n",
3500
 
               node->class_->scanner->display_prompt,
3501
 
               _synctex_data_tag(node),
3502
 
               _synctex_data_line(node),
3503
 
               _synctex_data_h(node),
3504
 
               _synctex_data_v(node),
3505
 
               _synctex_data_width(node),
3506
 
               _synctex_data_height(node),
3507
 
               _synctex_data_depth(node)
3508
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3509
 
        _synctex_display_sibling(node);
3510
 
    }
3511
 
}
3512
 
 
3513
 
static char * _synctex_abstract_math(synctex_node_p node) {
3514
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3515
 
    if (node) {
3516
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"math:%i,%i:%i,%i"
3517
 
                       SYNCTEX_PRINT_CHARINDEX_FMT,
3518
 
               _synctex_data_tag(node),
3519
 
               _synctex_data_line(node),
3520
 
               _synctex_data_h(node),
3521
 
               _synctex_data_v(node)
3522
 
                       SYNCTEX_PRINT_CHARINDEX_WHAT);
3523
 
    }
3524
 
    return abstract;
3525
 
}
3526
 
 
3527
 
static void _synctex_display_math(synctex_node_p node) {
3528
 
    if (node) {
3529
 
        printf("%smath:%i,%i:%i,%i"
3530
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3531
 
               "\n",
3532
 
               node->class_->scanner->display_prompt,
3533
 
               _synctex_data_tag(node),
3534
 
               _synctex_data_line(node),
3535
 
               _synctex_data_h(node),
3536
 
               _synctex_data_v(node)
3537
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3538
 
        _synctex_display_sibling(node);
3539
 
    }
3540
 
}
3541
 
 
3542
 
static char * _synctex_abstract_kern(synctex_node_p node) {
3543
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3544
 
    if (node) {
3545
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"kern:%i,%i:%i,%i:%i"
3546
 
                       SYNCTEX_PRINT_CHARINDEX_FMT,
3547
 
               _synctex_data_tag(node),
3548
 
               _synctex_data_line(node),
3549
 
               _synctex_data_h(node),
3550
 
               _synctex_data_v(node),
3551
 
               _synctex_data_width(node)
3552
 
                       SYNCTEX_PRINT_CHARINDEX_WHAT);
3553
 
    }
3554
 
    return abstract;
3555
 
}
3556
 
 
3557
 
static void _synctex_display_kern(synctex_node_p node) {
3558
 
    if (node) {
3559
 
        printf("%skern:%i,%i:%i,%i:%i"
3560
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3561
 
               "\n",
3562
 
               node->class_->scanner->display_prompt,
3563
 
               _synctex_data_tag(node),
3564
 
               _synctex_data_line(node),
3565
 
               _synctex_data_h(node),
3566
 
               _synctex_data_v(node),
3567
 
               _synctex_data_width(node)
3568
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3569
 
        _synctex_display_sibling(node);
3570
 
    }
3571
 
}
3572
 
 
3573
 
static char * _synctex_abstract_boundary(synctex_node_p node) {
3574
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3575
 
    if (node) {
3576
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"boundary:%i,%i:%i,%i"
3577
 
                       SYNCTEX_PRINT_CHARINDEX_FMT,
3578
 
               _synctex_data_tag(node),
3579
 
               _synctex_data_line(node),
3580
 
               _synctex_data_h(node),
3581
 
               _synctex_data_v(node)
3582
 
                       SYNCTEX_PRINT_CHARINDEX_WHAT);
3583
 
    }
3584
 
    return abstract;
3585
 
}
3586
 
 
3587
 
static void _synctex_display_boundary(synctex_node_p node) {
3588
 
    if (node) {
3589
 
        printf("%sboundary:%i,%i:%i,%i"
3590
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3591
 
               "\n",
3592
 
               node->class_->scanner->display_prompt,
3593
 
               _synctex_data_tag(node),
3594
 
               _synctex_data_line(node),
3595
 
               _synctex_data_h(node),
3596
 
               _synctex_data_v(node)
3597
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3598
 
        _synctex_display_sibling(node);
3599
 
    }
3600
 
}
3601
 
 
3602
 
static char * _synctex_abstract_box_bdry(synctex_node_p node) {
3603
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3604
 
    if (node) {
3605
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"box bdry:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT,
3606
 
               _synctex_data_tag(node),
3607
 
               _synctex_data_line(node),
3608
 
               _synctex_data_h(node),
3609
 
               _synctex_data_v(node)
3610
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3611
 
    }
3612
 
    return abstract;
3613
 
}
3614
 
 
3615
 
static void _synctex_display_box_bdry(synctex_node_p node) {
3616
 
    if (node) {
3617
 
        printf("%sbox bdry:%i,%i:%i,%i",
3618
 
               node->class_->scanner->display_prompt,
3619
 
               _synctex_data_tag(node),
3620
 
               _synctex_data_line(node),
3621
 
               _synctex_data_h(node),
3622
 
               _synctex_data_v(node));
3623
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3624
 
        _synctex_display_sibling(node);
3625
 
    }
3626
 
}
3627
 
 
3628
 
static char * _synctex_abstract_ref(synctex_node_p node) {
3629
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3630
 
    if (node) {
3631
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"form ref:%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT,
3632
 
               _synctex_data_tag(node),
3633
 
               _synctex_data_h(node),
3634
 
               _synctex_data_v(node)
3635
 
                       SYNCTEX_PRINT_CHARINDEX_WHAT);
3636
 
    }
3637
 
    return abstract;
3638
 
}
3639
 
 
3640
 
static void _synctex_display_ref(synctex_node_p node) {
3641
 
    if (node) {
3642
 
        printf("%sform ref:%i:%i,%i",
3643
 
               node->class_->scanner->display_prompt,
3644
 
               _synctex_data_tag(node),
3645
 
               _synctex_data_h(node),
3646
 
               _synctex_data_v(node));
3647
 
        SYNCTEX_PRINT_CHARINDEX_NL;
3648
 
        _synctex_display_sibling(node);
3649
 
    }
3650
 
}
3651
 
static char * _synctex_abstract_proxy(synctex_node_p node) {
3652
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3653
 
    if (node) {
3654
 
        synctex_node_p N = _synctex_tree_target(node);
3655
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%i,%i:%i,%i/%p%s",
3656
 
               synctex_node_isa(node),
3657
 
               synctex_node_tag(node),
3658
 
               synctex_node_line(node),
3659
 
               _synctex_data_h(node),
3660
 
               _synctex_data_v(node),
3661
 
               node,
3662
 
               _synctex_node_abstract(N));
3663
 
    }
3664
 
    return abstract;
3665
 
}
3666
 
static void _synctex_display_proxy(synctex_node_p node) {
3667
 
    if (node) {
3668
 
        synctex_node_p N = _synctex_tree_target(node);
3669
 
        printf("%s%s:%i,%i:%i,%i",
3670
 
               node->class_->scanner->display_prompt,
3671
 
               synctex_node_isa(node),
3672
 
               synctex_node_tag(node),
3673
 
               synctex_node_line(node),
3674
 
               _synctex_data_h(node),
3675
 
               _synctex_data_v(node));
3676
 
        if (N) {
3677
 
            printf("=%i,%i:%i,%i,%i->%s",
3678
 
                   synctex_node_h(node),
3679
 
                   synctex_node_v(node),
3680
 
                   synctex_node_width(node),
3681
 
                   synctex_node_height(node),
3682
 
                   synctex_node_depth(node),
3683
 
                   _synctex_node_abstract(N));
3684
 
        }
3685
 
        printf("\n");
3686
 
        _synctex_display_child(node);
3687
 
        _synctex_display_sibling(node);
3688
 
    }
3689
 
}
3690
 
static char * _synctex_abstract_proxy_vbox(synctex_node_p node) {
3691
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3692
 
    if (node) {
3693
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,
3694
 
                 "[*%i,%i:%i,%i:%i,%i,%i...*]"
3695
 
               SYNCTEX_PRINT_CHARINDEX_FMT,
3696
 
               synctex_node_tag(node),
3697
 
               synctex_node_line(node),
3698
 
               synctex_node_h(node),
3699
 
               synctex_node_v(node),
3700
 
               synctex_node_width(node),
3701
 
               synctex_node_height(node),
3702
 
               synctex_node_depth(node)
3703
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3704
 
    }
3705
 
    return abstract;
3706
 
}
3707
 
 
3708
 
static void _synctex_display_proxy_vbox(synctex_node_p node) {
3709
 
    if (node) {
3710
 
        printf("%s[*%i,%i:%i,%i:%i,%i,%i"
3711
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3712
 
               "\n",
3713
 
               node->class_->scanner->display_prompt,
3714
 
               synctex_node_tag(node),
3715
 
               synctex_node_line(node),
3716
 
               synctex_node_h(node),
3717
 
               synctex_node_v(node),
3718
 
               synctex_node_width(node),
3719
 
               synctex_node_height(node),
3720
 
               synctex_node_depth(node)
3721
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3722
 
        _synctex_display_child(node);
3723
 
        printf("%s*]\n%slast:%s\n",
3724
 
               node->class_->scanner->display_prompt,
3725
 
               node->class_->scanner->display_prompt,
3726
 
               _synctex_node_abstract(_synctex_tree_last(node)));
3727
 
        _synctex_display_sibling(node);
3728
 
    }
3729
 
}
3730
 
 
3731
 
static char * _synctex_abstract_proxy_hbox(synctex_node_p node) {
3732
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3733
 
    if (node) {
3734
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"(*%i,%i~%i*%i:%i,%i:%i,%i,%i...*)/%p"
3735
 
               SYNCTEX_PRINT_CHARINDEX_FMT,
3736
 
               synctex_node_tag(node),
3737
 
               synctex_node_line(node),
3738
 
               synctex_node_mean_line(node),
3739
 
               synctex_node_weight(node),
3740
 
               synctex_node_h(node),
3741
 
               synctex_node_v(node),
3742
 
               synctex_node_width(node),
3743
 
               synctex_node_height(node),
3744
 
               synctex_node_depth(node),
3745
 
               node
3746
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3747
 
    }
3748
 
    return abstract;
3749
 
}
3750
 
 
3751
 
static void _synctex_display_proxy_hbox(synctex_node_p node) {
3752
 
    if (node) {
3753
 
        printf("%s(*%i,%i~%i*%i:%i,%i:%i,%i,%i"
3754
 
               SYNCTEX_PRINT_CHARINDEX_FMT
3755
 
               "\n",
3756
 
               node->class_->scanner->display_prompt,
3757
 
               synctex_node_tag(node),
3758
 
               synctex_node_line(node),
3759
 
               synctex_node_mean_line(node),
3760
 
               synctex_node_weight(node),
3761
 
               synctex_node_h(node),
3762
 
               synctex_node_v(node),
3763
 
               synctex_node_width(node),
3764
 
               synctex_node_height(node),
3765
 
               synctex_node_depth(node)
3766
 
               SYNCTEX_PRINT_CHARINDEX_WHAT);
3767
 
        _synctex_display_child(node);
3768
 
        printf("%s*)\n%slast:%s\n",
3769
 
               node->class_->scanner->display_prompt,
3770
 
               node->class_->scanner->display_prompt,
3771
 
               _synctex_node_abstract(_synctex_tree_last(node)));
3772
 
        _synctex_display_sibling(node);
3773
 
    }
3774
 
}
3775
 
 
3776
 
static char * _synctex_abstract_handle(synctex_node_p node) {
3777
 
    static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3778
 
    if (node) {
3779
 
        synctex_node_p N = _synctex_tree_target(node);
3780
 
        if (N && !N->class_) {
3781
 
            exit(1);
3782
 
        }
3783
 
        snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%s",
3784
 
               synctex_node_isa(node),
3785
 
               (N?_synctex_node_abstract(N):""));
3786
 
    }
3787
 
    return abstract;
3788
 
}
3789
 
static void _synctex_display_handle(synctex_node_p node) {
3790
 
    if (node) {
3791
 
        synctex_node_p N = _synctex_tree_target(node);
3792
 
        printf("%s%s(%i):->%s\n",
3793
 
               node->class_->scanner->display_prompt,
3794
 
               synctex_node_isa(node),
3795
 
               _synctex_data_weight(N),
3796
 
               _synctex_node_abstract(N));
3797
 
        _synctex_display_child(node);
3798
 
        _synctex_display_sibling(node);
3799
 
    }
3800
 
}
3801
 
#       ifdef SYNCTEX_NOTHING
3802
 
#       pragma mark -
3803
 
#       pragma mark STATUS
3804
 
#   endif
 
795
void synctex_node_log(synctex_node_t node) {
 
796
        SYNCTEX_LOG(node);
 
797
}
 
798
 
 
799
static void _synctex_log_input(synctex_node_t node) {
 
800
        if (node) {
 
801
        printf("%s:%i,%s",synctex_node_isa(node),SYNCTEX_TAG(node),SYNCTEX_NAME(node));
 
802
        printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
 
803
    }
 
804
}
 
805
 
 
806
static void _synctex_log_sheet(synctex_node_t node) {
 
807
        if (node) {
 
808
                printf("%s:%i",synctex_node_isa(node),SYNCTEX_PAGE(node));
 
809
        SYNCTEX_PRINT_CHARINDEX;
 
810
                printf("SELF:%p",(void *)node);
 
811
                printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
 
812
                printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
 
813
                printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
 
814
                printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node));
 
815
        printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node));
 
816
        }
 
817
}
 
818
 
 
819
static void _synctex_log_small_node(synctex_node_t node) {
 
820
        if (node) {
 
821
        printf("%s:%i,%i:%i,%i",
 
822
            synctex_node_isa(node),
 
823
            SYNCTEX_TAG(node),
 
824
            SYNCTEX_LINE(node),
 
825
            SYNCTEX_HORIZ(node),
 
826
            SYNCTEX_VERT(node));
 
827
            SYNCTEX_PRINT_CHARINDEX;
 
828
        printf("SELF:%p",(void *)node);
 
829
        printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
 
830
        printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
 
831
        printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
 
832
        printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node));
 
833
    }
 
834
}
 
835
 
 
836
static void _synctex_log_medium_node(synctex_node_t node) {
 
837
        if (node) {
 
838
        printf("%s:%i,%i:%i,%i:%i",
 
839
            synctex_node_isa(node),
 
840
            SYNCTEX_TAG(node),
 
841
            SYNCTEX_LINE(node),
 
842
            SYNCTEX_HORIZ(node),
 
843
            SYNCTEX_VERT(node),
 
844
            SYNCTEX_WIDTH(node));
 
845
            SYNCTEX_PRINT_CHARINDEX;
 
846
        printf("SELF:%p",(void *)node);
 
847
        printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
 
848
        printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
 
849
        printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
 
850
        printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node));
 
851
    }
 
852
}
 
853
 
 
854
static void _synctex_log_void_box(synctex_node_t node) {
 
855
        if (node) {
 
856
        printf("%s",synctex_node_isa(node));
 
857
        printf(":%i",SYNCTEX_TAG(node));
 
858
        printf(",%i",SYNCTEX_LINE(node));
 
859
        printf(",%i",0);
 
860
        printf(":%i",SYNCTEX_HORIZ(node));
 
861
        printf(",%i",SYNCTEX_VERT(node));
 
862
        printf(":%i",SYNCTEX_WIDTH(node));
 
863
        printf(",%i",SYNCTEX_HEIGHT(node));
 
864
        printf(",%i",SYNCTEX_DEPTH(node));
 
865
        SYNCTEX_PRINT_CHARINDEX;
 
866
        printf("SELF:%p",(void *)node);
 
867
        printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
 
868
        printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
 
869
        printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
 
870
        printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node));
 
871
    }
 
872
}
 
873
 
 
874
static void _synctex_log_vbox(synctex_node_t node) {
 
875
        if (node) {
 
876
        printf("%s",synctex_node_isa(node));
 
877
        printf(":%i",SYNCTEX_TAG(node));
 
878
        printf(",%i",SYNCTEX_LINE(node));
 
879
        printf(",%i",0);
 
880
        printf(":%i",SYNCTEX_HORIZ(node));
 
881
        printf(",%i",SYNCTEX_VERT(node));
 
882
        printf(":%i",SYNCTEX_WIDTH(node));
 
883
        printf(",%i",SYNCTEX_HEIGHT(node));
 
884
        printf(",%i",SYNCTEX_DEPTH(node));
 
885
        SYNCTEX_PRINT_CHARINDEX;
 
886
        printf("SELF:%p",(void *)node);
 
887
        printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
 
888
        printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
 
889
        printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
 
890
        printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node));
 
891
        printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node));
 
892
    }
 
893
}
 
894
 
 
895
static void _synctex_log_hbox(synctex_node_t node) {
 
896
        if (node) {
 
897
        printf("%s",synctex_node_isa(node));
 
898
        printf(":%i",SYNCTEX_TAG(node));
 
899
        printf(",%i~%i*%i",SYNCTEX_LINE(node),SYNCTEX_MEAN_LINE(node),SYNCTEX_NODE_WEIGHT(node));
 
900
        printf(",%i",0);
 
901
        printf(":%i",SYNCTEX_HORIZ(node));
 
902
        printf(",%i",SYNCTEX_VERT(node));
 
903
        printf(":%i",SYNCTEX_WIDTH(node));
 
904
        printf(",%i",SYNCTEX_HEIGHT(node));
 
905
        printf(",%i",SYNCTEX_DEPTH(node));
 
906
        printf("/%i",SYNCTEX_HORIZ_V(node));
 
907
        printf(",%i",SYNCTEX_VERT_V(node));
 
908
        printf(":%i",SYNCTEX_WIDTH_V(node));
 
909
        printf(",%i",SYNCTEX_HEIGHT_V(node));
 
910
        printf(",%i",SYNCTEX_DEPTH_V(node));
 
911
        SYNCTEX_PRINT_CHARINDEX;
 
912
        printf("SELF:%p",(void *)node);
 
913
        printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
 
914
        printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
 
915
        printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
 
916
        printf(" SYNCTEX_FRIEND:%p",(void *)SYNCTEX_FRIEND(node));
 
917
        printf(" SYNCTEX_NEXT_hbox:%p\n",(void *)SYNCTEX_NEXT_hbox(node));
 
918
    }
 
919
}
 
920
 
 
921
#   define SYNCTEX_DISPLAY(NODE) SYNCTEX_MSG_SEND(NODE,display)
 
922
 
 
923
void synctex_node_display(synctex_node_t node) {
 
924
        SYNCTEX_DISPLAY(node);
 
925
}
 
926
 
 
927
static void _synctex_display_input(synctex_node_t node) {
 
928
    if (node) {
 
929
        printf("....Input:%i:%s",
 
930
            SYNCTEX_TAG(node),
 
931
            SYNCTEX_NAME(node));
 
932
            SYNCTEX_PRINT_CHARINDEX;
 
933
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
934
    }
 
935
}
 
936
 
 
937
static void _synctex_display_sheet(synctex_node_t node) {
 
938
        if (node) {
 
939
                printf("....{%i",SYNCTEX_PAGE(node));
 
940
        SYNCTEX_PRINT_CHARINDEX;
 
941
                SYNCTEX_DISPLAY(SYNCTEX_CHILD(node));
 
942
                printf("....}\n");
 
943
                SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
944
        }
 
945
}
 
946
 
 
947
static void _synctex_display_vbox(synctex_node_t node) {
 
948
    if (node) {
 
949
        printf("....[%i,%i:%i,%i:%i,%i,%i",
 
950
            SYNCTEX_TAG(node),
 
951
            SYNCTEX_LINE(node),
 
952
            SYNCTEX_HORIZ(node),
 
953
            SYNCTEX_VERT(node),
 
954
            SYNCTEX_WIDTH(node),
 
955
            SYNCTEX_HEIGHT(node),
 
956
            SYNCTEX_DEPTH(node));
 
957
            SYNCTEX_PRINT_CHARINDEX;
 
958
        SYNCTEX_DISPLAY(SYNCTEX_CHILD(node));
 
959
        printf("....]\n");
 
960
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
961
    }
 
962
}
 
963
 
 
964
static void _synctex_display_hbox(synctex_node_t node) {
 
965
    if (node) {
 
966
        printf("....(%i,%i~%i*%i:%i,%i:%i,%i,%i",
 
967
            SYNCTEX_TAG(node),
 
968
            SYNCTEX_LINE(node),
 
969
            SYNCTEX_MEAN_LINE(node),
 
970
            SYNCTEX_NODE_WEIGHT(node),
 
971
            SYNCTEX_HORIZ(node),
 
972
            SYNCTEX_VERT(node),
 
973
            SYNCTEX_WIDTH(node),
 
974
            SYNCTEX_HEIGHT(node),
 
975
            SYNCTEX_DEPTH(node));
 
976
            SYNCTEX_PRINT_CHARINDEX;
 
977
        SYNCTEX_DISPLAY(SYNCTEX_CHILD(node));
 
978
        printf("....)\n");
 
979
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
980
    }
 
981
}
 
982
 
 
983
static void _synctex_display_void_vbox(synctex_node_t node) {
 
984
    if (node) {
 
985
        printf("....v%i,%i;%i,%i:%i,%i,%i",
 
986
            SYNCTEX_TAG(node),
 
987
            SYNCTEX_LINE(node),
 
988
            SYNCTEX_HORIZ(node),
 
989
            SYNCTEX_VERT(node),
 
990
            SYNCTEX_WIDTH(node),
 
991
            SYNCTEX_HEIGHT(node),
 
992
            SYNCTEX_DEPTH(node));
 
993
            SYNCTEX_PRINT_CHARINDEX;
 
994
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
995
    }
 
996
}
 
997
 
 
998
static void _synctex_display_void_hbox(synctex_node_t node) {
 
999
    if (node) {
 
1000
        printf("....h%i,%i:%i,%i:%i,%i,%i",
 
1001
            SYNCTEX_TAG(node),
 
1002
            SYNCTEX_LINE(node),
 
1003
            SYNCTEX_HORIZ(node),
 
1004
            SYNCTEX_VERT(node),
 
1005
            SYNCTEX_WIDTH(node),
 
1006
            SYNCTEX_HEIGHT(node),
 
1007
            SYNCTEX_DEPTH(node));
 
1008
            SYNCTEX_PRINT_CHARINDEX;
 
1009
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
1010
    }
 
1011
}
 
1012
 
 
1013
static void _synctex_display_glue(synctex_node_t node) {
 
1014
    if (node) {
 
1015
        printf("....glue:%i,%i:%i,%i",
 
1016
            SYNCTEX_TAG(node),
 
1017
            SYNCTEX_LINE(node),
 
1018
            SYNCTEX_HORIZ(node),
 
1019
            SYNCTEX_VERT(node));
 
1020
            SYNCTEX_PRINT_CHARINDEX;
 
1021
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
1022
    }
 
1023
}
 
1024
 
 
1025
static void _synctex_display_math(synctex_node_t node) {
 
1026
    if (node) {
 
1027
        printf("....math:%i,%i:%i,%i",
 
1028
            SYNCTEX_TAG(node),
 
1029
            SYNCTEX_LINE(node),
 
1030
            SYNCTEX_HORIZ(node),
 
1031
            SYNCTEX_VERT(node));
 
1032
            SYNCTEX_PRINT_CHARINDEX;
 
1033
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
1034
    }
 
1035
}
 
1036
 
 
1037
static void _synctex_display_kern(synctex_node_t node) {
 
1038
    if (node) {
 
1039
        printf("....kern:%i,%i:%i,%i:%i",
 
1040
            SYNCTEX_TAG(node),
 
1041
            SYNCTEX_LINE(node),
 
1042
            SYNCTEX_HORIZ(node),
 
1043
            SYNCTEX_VERT(node),
 
1044
            SYNCTEX_WIDTH(node));
 
1045
            SYNCTEX_PRINT_CHARINDEX;
 
1046
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
1047
    }
 
1048
}
 
1049
 
 
1050
static void _synctex_display_boundary(synctex_node_t node) {
 
1051
    if (node) {
 
1052
        printf("....boundary:%i,%i:%i,%i",
 
1053
            SYNCTEX_TAG(node),
 
1054
            SYNCTEX_LINE(node),
 
1055
            SYNCTEX_HORIZ(node),
 
1056
            SYNCTEX_VERT(node));
 
1057
            SYNCTEX_PRINT_CHARINDEX;
 
1058
        SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
 
1059
    }
 
1060
}
 
1061
 
 
1062
#       ifdef SYNCTEX_NOTHING
 
1063
#       pragma mark -
 
1064
#       pragma mark SCANNER
 
1065
#   endif
 
1066
 
 
1067
/*  Here are gathered all the possible status that the next scanning functions will return.
 
1068
 *  All these functions return a status, and pass their result through pointers.
 
1069
 *  Negative values correspond to errors.
 
1070
 *  The management of the buffer is causing some significant overhead.
 
1071
 *  Every function that may access the buffer returns a status related to the buffer and file state.
 
1072
 *  status >= SYNCTEX_STATUS_OK means the function worked as expected
 
1073
 *  status < SYNCTEX_STATUS_OK means the function did not work as expected
 
1074
 *  status == SYNCTEX_STATUS_NOT_OK means the function did not work as expected but there is still some material to parse.
 
1075
 *  status == SYNCTEX_STATUS_EOF means the function did not work as expected and there is no more material.
 
1076
 *  status<SYNCTEX_STATUS_EOF means an error
 
1077
 */
 
1078
 
 
1079
/*  When the end of the synctex file has been reached: */
 
1080
#   define SYNCTEX_STATUS_EOF 0
 
1081
/*  When the function could not return the value it was asked for: */
 
1082
#   define SYNCTEX_STATUS_NOT_OK (SYNCTEX_STATUS_EOF+1)
 
1083
/*  When the function returns the value it was asked for: */
 
1084
#   define SYNCTEX_STATUS_OK (SYNCTEX_STATUS_NOT_OK+1)
 
1085
/*  Generic error: */
 
1086
#   define SYNCTEX_STATUS_ERROR -1
 
1087
/*  Parameter error: */
 
1088
#   define SYNCTEX_STATUS_BAD_ARGUMENT -2
 
1089
 
 
1090
#   define SYNCTEX_FILE (scanner->file)
 
1091
 
 
1092
/*  Actually, the minimum buffer size is driven by integer and float parsing.
 
1093
 *  �0.123456789e123
 
1094
 */
 
1095
#   define SYNCTEX_BUFFER_MIN_SIZE 16
 
1096
#   define SYNCTEX_BUFFER_SIZE 32768
3805
1097
 
3806
1098
#       ifdef SYNCTEX_NOTHING
3807
1099
#       pragma mark -
3808
1100
#       pragma mark Prototypes
3809
1101
#   endif
3810
 
typedef struct {
3811
 
    size_t size;
3812
 
    synctex_status_t status;
3813
 
} synctex_zs_s;
3814
 
static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t size);
3815
 
static synctex_status_t _synctex_next_line(synctex_scanner_p scanner);
3816
 
static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char * the_string);
3817
 
 
3818
 
typedef struct synctex_ns_t {
3819
 
    synctex_node_p node;
3820
 
    synctex_status_t status;
3821
 
} synctex_ns_s;
3822
 
static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner);
3823
 
static synctex_status_t _synctex_scan_preamble(synctex_scanner_p scanner);
3824
 
typedef struct {
3825
 
    float value;
3826
 
    synctex_status_t status;
3827
 
} synctex_fs_s;
3828
 
static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner);
3829
 
static synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_p scanner);
3830
 
static synctex_status_t _synctex_scan_postamble(synctex_scanner_p scanner);
3831
 
static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box);
3832
 
static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner);
3833
 
int synctex_scanner_pre_x_offset(synctex_scanner_p scanner);
3834
 
int synctex_scanner_pre_y_offset(synctex_scanner_p scanner);
3835
 
const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner);
3836
 
 
3837
 
#       ifdef SYNCTEX_NOTHING
3838
 
#       pragma mark -
3839
 
#       pragma mark SCANNER UTILITIES
3840
 
#   endif
3841
 
 
3842
 
#   define SYNCTEX_FILE (scanner->reader->file)
3843
 
 
3844
 
/**
3845
 
 *  Try to ensure that the buffer contains at least size bytes.
 
1102
synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, size_t * size_ptr);
 
1103
synctex_status_t _synctex_next_line(synctex_scanner_t scanner);
 
1104
synctex_status_t _synctex_match_string(synctex_scanner_t scanner, const char * the_string);
 
1105
synctex_status_t _synctex_decode_int(synctex_scanner_t scanner, int* value_ref);
 
1106
synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value_ref);
 
1107
synctex_status_t _synctex_scan_input(synctex_scanner_t scanner);
 
1108
synctex_status_t _synctex_scan_preamble(synctex_scanner_t scanner);
 
1109
synctex_status_t _synctex_scan_float_and_dimension(synctex_scanner_t scanner, float * value_ref);
 
1110
synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_t scanner);
 
1111
synctex_status_t _synctex_scan_postamble(synctex_scanner_t scanner);
 
1112
synctex_status_t _synctex_setup_visible_box(synctex_node_t box);
 
1113
synctex_status_t _synctex_hbox_setup_visible(synctex_node_t node,int h, int v);
 
1114
synctex_status_t _synctex_scan_sheet(synctex_scanner_t scanner, synctex_node_t parent);
 
1115
synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner);
 
1116
synctex_status_t _synctex_scan_content(synctex_scanner_t scanner);
 
1117
int synctex_scanner_pre_x_offset(synctex_scanner_t scanner);
 
1118
int synctex_scanner_pre_y_offset(synctex_scanner_t scanner);
 
1119
const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner);
 
1120
int _synctex_node_is_box(synctex_node_t node);
 
1121
 
 
1122
/*  Try to ensure that the buffer contains at least size bytes.
3846
1123
 *  Passing a huge size argument means the whole buffer length.
3847
 
 *  Passing a 0 size argument means return the available buffer length, without reading the file.
3848
 
 *  In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL.
3849
 
 *  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.
 
1124
 *  Passing a null size argument means return the available buffer length, without reading the file.
 
1125
 *  In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL,
 
1126
 *  in which case, SYNCTEX_STATUS_BAD_ARGUMENT is returned.
 
1127
 *  The value returned in size_ptr is the number of bytes now available in the buffer.
 
1128
 *  This is a nonnegative integer, it may take the value 0.
3850
1129
 *  It is the responsibility of the caller to test whether this size is conforming to its needs.
3851
1130
 *  Negative values may return in case of error, actually
3852
 
 *  when there was an error reading the synctex file.
3853
 
 *  - parameter scanner: The owning scanner. When NULL, returns SYNCTEX_STATUS_BAD_ARGUMENT.
3854
 
 *  - parameter expected: expected number of bytes.
3855
 
 *  - returns: a size and a status.
3856
 
 */
3857
 
static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t expected) {
3858
 
    size_t size = 0;
3859
 
    if (NULL == scanner) {
3860
 
        return (synctex_zs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT};
3861
 
    }
3862
 
    if (expected>scanner->reader->size){
3863
 
        expected = scanner->reader->size;
3864
 
    }
3865
 
    size = SYNCTEX_END - SYNCTEX_CUR; /*  available is the number of unparsed chars in the buffer */
3866
 
    if (expected<=size) {
3867
 
        /*  There are already sufficiently many characters in the buffer */
3868
 
        return (synctex_zs_s){size,SYNCTEX_STATUS_OK};
3869
 
    }
3870
 
    if (SYNCTEX_FILE) {
3871
 
        /*  Copy the remaining part of the buffer to the beginning,
3872
 
         *  then read the next part of the file */
3873
 
        int already_read = 0;
 
1131
 *  when there was an error reading the synctex file. */
 
1132
synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, size_t * size_ptr) {
 
1133
        size_t available = 0;
 
1134
        if (NULL == scanner || NULL == size_ptr) {
 
1135
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1136
        }
 
1137
#   define size (* size_ptr)
 
1138
        if (size>SYNCTEX_BUFFER_SIZE){
 
1139
                size = SYNCTEX_BUFFER_SIZE;
 
1140
        }
 
1141
        available = SYNCTEX_END - SYNCTEX_CUR; /*  available is the number of unparsed chars in the buffer */
 
1142
        if (size<=available) {
 
1143
                /*  There are already sufficiently many characters in the buffer */
 
1144
                size = available;
 
1145
                return SYNCTEX_STATUS_OK;
 
1146
        }
 
1147
        if (SYNCTEX_FILE) {
 
1148
                /*  Copy the remaining part of the buffer to the beginning,
 
1149
                 *  then read the next part of the file */
 
1150
                int already_read = 0;
3874
1151
#   if defined(SYNCTEX_USE_CHARINDEX)
3875
 
        scanner->reader->charindex_offset += SYNCTEX_CUR - SYNCTEX_START;
 
1152
        scanner->charindex_offset += SYNCTEX_CUR - SYNCTEX_START;
3876
1153
#   endif
3877
 
        if (size) {
3878
 
            memmove(SYNCTEX_START, SYNCTEX_CUR, size);
3879
 
        }
3880
 
        SYNCTEX_CUR = SYNCTEX_START + size; /*  the next character after the move, will change. */
3881
 
        /*  Fill the buffer up to its end */
3882
 
        already_read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,(int)(SYNCTEX_BUFFER_SIZE - size));
3883
 
        if (already_read>0) {
3884
 
            /*  We assume that 0<already_read<=SYNCTEX_BUFFER_SIZE - size, such that
3885
 
             *  SYNCTEX_CUR + already_read = SYNCTEX_START + size  + already_read <= SYNCTEX_START + SYNCTEX_BUFFER_SIZE */
3886
 
            SYNCTEX_END = SYNCTEX_CUR + already_read;
3887
 
            /*  If the end of the file was reached, all the required SYNCTEX_BUFFER_SIZE - available
3888
 
             *  may not be filled with values from the file.
3889
 
             *  In that case, the buffer should stop properly after already_read characters. */
3890
 
            * SYNCTEX_END = '\0'; /* there is enough room */
3891
 
            SYNCTEX_CUR = SYNCTEX_START;
3892
 
            /*  May be available is less than size, the caller will have to test. */
3893
 
            return (synctex_zs_s){SYNCTEX_END - SYNCTEX_CUR,SYNCTEX_STATUS_OK};
3894
 
        } else if (0>already_read) {
3895
 
            /*  There is a possible error in reading the file */
3896
 
            int errnum = 0;
3897
 
            const char * error_string = gzerror(SYNCTEX_FILE, &errnum);
3898
 
            if (Z_ERRNO == errnum) {
3899
 
                /*  There is an error in zlib caused by the file system */
3900
 
                _synctex_error("gzread error from the file system (%i)",errno);
3901
 
                return (synctex_zs_s){0,SYNCTEX_STATUS_ERROR};
3902
 
            } else if (errnum) {
3903
 
                _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string);
3904
 
                return (synctex_zs_s){0,SYNCTEX_STATUS_ERROR};
3905
 
            }
3906
 
        }
 
1154
                if (available) {
 
1155
                        memmove(SYNCTEX_START, SYNCTEX_CUR, available);
 
1156
                }
 
1157
                SYNCTEX_CUR = SYNCTEX_START + available; /*  the next character after the move, will change. */
 
1158
                /*  Fill the buffer up to its end */
 
1159
                already_read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,(int)(SYNCTEX_BUFFER_SIZE - available));
 
1160
                if (already_read>0) {
 
1161
                        /*  We assume that 0<already_read<=SYNCTEX_BUFFER_SIZE - available, such that
 
1162
                         *  SYNCTEX_CUR + already_read = SYNCTEX_START + available  + already_read <= SYNCTEX_START + SYNCTEX_BUFFER_SIZE */
 
1163
                        SYNCTEX_END = SYNCTEX_CUR + already_read;
 
1164
                        /*  If the end of the file was reached, all the required SYNCTEX_BUFFER_SIZE - available
 
1165
                         *  may not be filled with values from the file.
 
1166
                         *  In that case, the buffer should stop properly after already_read characters. */
 
1167
                        * SYNCTEX_END = '\0';
 
1168
                        SYNCTEX_CUR = SYNCTEX_START;
 
1169
                        size = SYNCTEX_END - SYNCTEX_CUR; /* == old available + already_read*/
 
1170
                        return SYNCTEX_STATUS_OK; /*  May be available is less than size, the caller will have to test. */
 
1171
                } else if (0>already_read) {
 
1172
                        /*  There is a possible error in reading the file */
 
1173
                        int errnum = 0;
 
1174
                        const char * error_string = gzerror(SYNCTEX_FILE, &errnum);
 
1175
                        if (Z_ERRNO == errnum) {
 
1176
                                /*  There is an error in zlib caused by the file system */
 
1177
                                _synctex_error("gzread error from the file system (%i)",errno);
 
1178
                return SYNCTEX_STATUS_ERROR;
 
1179
                        } else if (errnum) {
 
1180
                                _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string);
 
1181
                return SYNCTEX_STATUS_ERROR;
 
1182
                        }
 
1183
                }
3907
1184
        /*  Nothing was read, we are at the end of the file. */
3908
1185
        gzclose(SYNCTEX_FILE);
3909
1186
        SYNCTEX_FILE = NULL;
3910
1187
        SYNCTEX_END = SYNCTEX_CUR;
3911
1188
        SYNCTEX_CUR = SYNCTEX_START;
3912
1189
        * SYNCTEX_END = '\0';/*  Terminate the string properly.*/
3913
 
        /*  there might be a bit of text left */
3914
 
        return (synctex_zs_s){SYNCTEX_END - SYNCTEX_CUR,SYNCTEX_STATUS_EOF};
 
1190
        size = SYNCTEX_END - SYNCTEX_CUR;
 
1191
        return SYNCTEX_STATUS_EOF; /*  there might be a bit of text left */
3915
1192
    }
3916
 
    /*  We cannot enlarge the buffer because the end of the file was reached. */
3917
 
    return (synctex_zs_s){size,SYNCTEX_STATUS_EOF};
 
1193
        /*  We cannot enlarge the buffer because the end of the file was reached. */
 
1194
        size = available;
 
1195
        return SYNCTEX_STATUS_EOF;
 
1196
#   undef size
3918
1197
}
3919
1198
 
3920
1199
/*  Used when parsing the synctex file.
3926
1205
 *  When the function returns with no error, SYNCTEX_CUR points to the first character of the next line, if any.
3927
1206
 *  J. Laurens: Sat May 10 07:52:31 UTC 2008
3928
1207
 */
3929
 
static synctex_status_t _synctex_next_line(synctex_scanner_p scanner) {
3930
 
    synctex_status_t status = SYNCTEX_STATUS_OK;
3931
 
    if (NULL == scanner) {
3932
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
3933
 
    }
 
1208
synctex_status_t _synctex_next_line(synctex_scanner_t scanner) {
 
1209
        synctex_status_t status = SYNCTEX_STATUS_OK;
 
1210
        size_t available = 0;
 
1211
        if (NULL == scanner) {
 
1212
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1213
        }
3934
1214
infinite_loop:
3935
 
    while(SYNCTEX_CUR<SYNCTEX_END) {
3936
 
        if (*SYNCTEX_CUR == '\n') {
3937
 
            ++SYNCTEX_CUR;
3938
 
            ++scanner->reader->line_number;
3939
 
            return _synctex_buffer_get_available_size(scanner, 1).status;
3940
 
        }
3941
 
        ++SYNCTEX_CUR;
3942
 
    }
3943
 
    /*  Here, we have SYNCTEX_CUR == SYNCTEX_END, such that the next call to _synctex_buffer_get_available_size
3944
 
     *  will read another bunch of synctex file. Little by little, we advance to the end of the file. */
3945
 
    status = _synctex_buffer_get_available_size(scanner, 1).status;
3946
 
    if (status<=SYNCTEX_STATUS_EOF) {
3947
 
        return status;
3948
 
    }
3949
 
    goto infinite_loop;
 
1215
        while(SYNCTEX_CUR<SYNCTEX_END) {
 
1216
                if (*SYNCTEX_CUR == '\n') {
 
1217
                        ++SYNCTEX_CUR;
 
1218
                        available = 1;
 
1219
                        return _synctex_buffer_get_available_size(scanner, &available);
 
1220
                }
 
1221
                ++SYNCTEX_CUR;
 
1222
        }
 
1223
        /*  Here, we have SYNCTEX_CUR == SYNCTEX_END, such that the next call to _synctex_buffer_get_available_size
 
1224
         *  will read another bunch of synctex file. Little by little, we advance to the end of the file. */
 
1225
        available = 1;
 
1226
        status = _synctex_buffer_get_available_size(scanner, &available);
 
1227
        if (status<=0) {
 
1228
                return status;
 
1229
        }
 
1230
        goto infinite_loop;
3950
1231
}
3951
1232
 
3952
1233
/*  Scan the given string.
3959
1240
 *  The given string might be as long as the maximum size_t value.
3960
1241
 *  As side effect, the buffer state may have changed if the given argument string can't fit into the buffer.
3961
1242
 */
3962
 
static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char * the_string) {
3963
 
    size_t tested_len = 0; /*  the number of characters at the beginning of the_string that match */
3964
 
    size_t remaining_len = 0; /*  the number of remaining characters of the_string that should match */
3965
 
    size_t available = 0;
3966
 
    synctex_zs_s zs = {0,0};
3967
 
    if (NULL == scanner || NULL == the_string) {
3968
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
3969
 
    }
3970
 
    remaining_len = strlen(the_string); /*  All the_string should match */
3971
 
    if (0 == remaining_len) {
3972
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
3973
 
    }
3974
 
    /*  How many characters available in the buffer? */
3975
 
    zs = _synctex_buffer_get_available_size(scanner,remaining_len);
3976
 
    if (zs.status<SYNCTEX_STATUS_EOF) {
3977
 
        return zs.status;
3978
 
    }
3979
 
    /*  Maybe we have less characters than expected because the buffer is too small. */
3980
 
    if (zs.size>=remaining_len) {
3981
 
        /*  The buffer is sufficiently big to hold the expected number of characters. */
3982
 
        if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) {
3983
 
            return SYNCTEX_STATUS_NOT_OK;
3984
 
        }
3985
 
    return_OK:
3986
 
        /*  Advance SYNCTEX_CUR to the next character after the_string. */
3987
 
        SYNCTEX_CUR += remaining_len;
3988
 
        return SYNCTEX_STATUS_OK;
3989
 
    } else if (strncmp((char *)SYNCTEX_CUR,the_string,zs.size)) {
3990
 
        /*  No need to go further, this is not the expected string in the buffer. */
3991
 
        return SYNCTEX_STATUS_NOT_OK;
3992
 
    } else if (SYNCTEX_FILE) {
3993
 
        /*  The buffer was too small to contain remaining_len characters.
3994
 
         *  We have to cut the string into pieces. */
3995
 
        z_off_t offset = 0L;
3996
 
        /*  the first part of the string is found, advance the_string to the next untested character. */
3997
 
        the_string += zs.size;
3998
 
        /*  update the remaining length and the parsed length. */
3999
 
        remaining_len -= zs.size;
4000
 
        tested_len += zs.size;
4001
 
        SYNCTEX_CUR += zs.size; /*  We validate the tested characters. */
4002
 
        if (0 == remaining_len) {
4003
 
            /*  Nothing left to test, we have found the given string. */
4004
 
            return SYNCTEX_STATUS_OK;
4005
 
        }
4006
 
        /*  We also have to record the current state of the file cursor because
4007
 
         *  if the_string does not match, all this should be a totally blank operation,
4008
 
         *  for which the file and buffer states should not be modified at all.
4009
 
         *  In fact, the states of the buffer before and after this function are in general different
4010
 
         *  but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR
4011
 
         *  can be safely discarded.  */
4012
 
        offset = gztell(SYNCTEX_FILE);
4013
 
        /*  offset now corresponds to the first character of the file that was not buffered. */
4014
 
        /*  SYNCTEX_CUR - SYNCTEX_START is the number of chars that where already buffered and
4015
 
         *  that match the head of the_string. If in fine the_string does not match, all these chars must be recovered
4016
 
         *  because the whole buffer contents is replaced in _synctex_buffer_get_available_size.
4017
 
         *  They were buffered from offset-len location in the file. */
4018
 
        offset -= SYNCTEX_CUR - SYNCTEX_START;
4019
 
    more_characters:
4020
 
        /*  There is still some work to be done, so read another bunch of file.
4021
 
         *  This is the second call to _synctex_buffer_get_available_size,
4022
 
         *  which means that the actual contents of the buffer will be discarded.
4023
 
         *  We will definitely have to recover the previous state in case we do not find the expected string. */
4024
 
        zs = _synctex_buffer_get_available_size(scanner,remaining_len);
4025
 
        if (zs.status<SYNCTEX_STATUS_EOF) {
4026
 
            return zs.status; /*  This is an error, no need to go further. */
4027
 
        }
4028
 
        if (zs.size==0) {
4029
 
            /*  Missing characters: recover the initial state of the file and return. */
4030
 
        return_NOT_OK:
4031
 
            if (offset != gzseek(SYNCTEX_FILE,offset,SEEK_SET)) {
4032
 
                /*  This is a critical error, we could not recover the previous state. */
4033
 
                _synctex_error("Can't seek file");
4034
 
                return SYNCTEX_STATUS_ERROR;
4035
 
            }
4036
 
            /*  Next time we are asked to fill the buffer,
4037
 
             *  we will read a complete bunch of text from the file. */
4038
 
            SYNCTEX_CUR = SYNCTEX_END;
4039
 
            return SYNCTEX_STATUS_NOT_OK;
4040
 
        }
4041
 
        if (zs.size<remaining_len) {
4042
 
            /*  We'll have to loop one more time. */
4043
 
            if (strncmp((char *)SYNCTEX_CUR,the_string,zs.size)) {
4044
 
                /*  This is not the expected string, recover the previous state and return. */
4045
 
                goto return_NOT_OK;
4046
 
            }
4047
 
            /*  Advance the_string to the first untested character. */
4048
 
            the_string += available;
4049
 
            /*  update the remaining length and the parsed length. */
4050
 
            remaining_len -= zs.size;
4051
 
            tested_len += zs.size;
4052
 
            SYNCTEX_CUR += zs.size; /*  We validate the tested characters. */
4053
 
            goto more_characters;
4054
 
        }
4055
 
        /*  This is the last step. */
4056
 
        if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) {
4057
 
            /*  This is not the expected string, recover the previous state and return. */
4058
 
            goto return_NOT_OK;
4059
 
        }
4060
 
        goto return_OK;
4061
 
    } else {
4062
 
        /*  The buffer can't contain the given string argument, and the EOF was reached */
4063
 
        return SYNCTEX_STATUS_EOF;
4064
 
    }
 
1243
synctex_status_t _synctex_match_string(synctex_scanner_t scanner, const char * the_string) {
 
1244
        size_t tested_len = 0; /*  the number of characters at the beginning of the_string that match */
 
1245
        size_t remaining_len = 0; /*  the number of remaining characters of the_string that should match */
 
1246
        size_t available = 0;
 
1247
        synctex_status_t status = 0;
 
1248
        if (NULL == scanner || NULL == the_string) {
 
1249
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1250
        }
 
1251
        remaining_len = strlen(the_string); /*  All the_string should match */
 
1252
        if (0 == remaining_len) {
 
1253
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1254
        }
 
1255
        /*  How many characters available in the buffer? */
 
1256
        available = remaining_len;
 
1257
        status = _synctex_buffer_get_available_size(scanner,&available);
 
1258
        if (status<SYNCTEX_STATUS_EOF) {
 
1259
                return status;
 
1260
        }
 
1261
        /*  Maybe we have less characters than expected because the buffer is too small. */
 
1262
        if (available>=remaining_len) {
 
1263
                /*  The buffer is sufficiently big to hold the expected number of characters. */
 
1264
                if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) {
 
1265
                        return SYNCTEX_STATUS_NOT_OK;
 
1266
                }
 
1267
return_OK:
 
1268
                /*  Advance SYNCTEX_CUR to the next character after the_string. */
 
1269
                SYNCTEX_CUR += remaining_len;
 
1270
                return SYNCTEX_STATUS_OK;
 
1271
        } else if (strncmp((char *)SYNCTEX_CUR,the_string,available)) {
 
1272
                        /*  No need to go further, this is not the expected string in the buffer. */
 
1273
                        return SYNCTEX_STATUS_NOT_OK;
 
1274
        } else if (SYNCTEX_FILE) {
 
1275
                /*  The buffer was too small to contain remaining_len characters.
 
1276
                 *  We have to cut the string into pieces. */
 
1277
                z_off_t offset = 0L;
 
1278
                /*  the first part of the string is found, advance the_string to the next untested character. */
 
1279
                the_string += available;
 
1280
                /*  update the remaining length and the parsed length. */
 
1281
                remaining_len -= available;
 
1282
                tested_len += available;
 
1283
                SYNCTEX_CUR += available; /*  We validate the tested characters. */
 
1284
                if (0 == remaining_len) {
 
1285
                        /*  Nothing left to test, we have found the given string, we return the length. */
 
1286
                        return tested_len;
 
1287
                }
 
1288
                /*  We also have to record the current state of the file cursor because
 
1289
                 *  if the_string does not match, all this should be a totally blank operation,
 
1290
                 *  for which the file and buffer states should not be modified at all.
 
1291
                 *  In fact, the states of the buffer before and after this function are in general different
 
1292
                 *  but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR
 
1293
                 *  can be safely discarded.  */
 
1294
                offset = gztell(SYNCTEX_FILE);
 
1295
                /*  offset now corresponds to the first character of the file that was not buffered. */
 
1296
                available = SYNCTEX_CUR - SYNCTEX_START; /*  available can be used as temporary placeholder. */
 
1297
                /*  available now corresponds to the number of chars that where already buffered and
 
1298
                 *  that match the head of the_string. If in fine the_string does not match, all these chars must be recovered
 
1299
                 *  because the buffer contents is completely replaced by _synctex_buffer_get_available_size.
 
1300
                 *  They were buffered from offset-len location in the file. */
 
1301
                offset -= available;
 
1302
more_characters:
 
1303
                /*  There is still some work to be done, so read another bunch of file.
 
1304
                 *  This is the second call to _synctex_buffer_get_available_size,
 
1305
                 *  which means that the actual contents of the buffer will be discarded.
 
1306
                 *  We will definitely have to recover the previous state in case we do not find the expected string. */
 
1307
                available = remaining_len;
 
1308
                status = _synctex_buffer_get_available_size(scanner,&available);
 
1309
                if (status<SYNCTEX_STATUS_EOF) {
 
1310
                        return status; /*  This is an error, no need to go further. */
 
1311
                }
 
1312
                if (available==0) {
 
1313
                        /*  Missing characters: recover the initial state of the file and return. */
 
1314
return_NOT_OK:
 
1315
                        if (offset != gzseek(SYNCTEX_FILE,offset,SEEK_SET)) {
 
1316
                                /*  This is a critical error, we could not recover the previous state. */
 
1317
                                _synctex_error("can't seek file");
 
1318
                                return SYNCTEX_STATUS_ERROR;
 
1319
                        }
 
1320
                        /*  Next time we are asked to fill the buffer,
 
1321
                         *  we will read a complete bunch of text from the file. */
 
1322
                        SYNCTEX_CUR = SYNCTEX_END;
 
1323
                        return SYNCTEX_STATUS_NOT_OK;
 
1324
                }
 
1325
                if (available<remaining_len) {
 
1326
                        /*  We'll have to loop one more time. */
 
1327
                        if (strncmp((char *)SYNCTEX_CUR,the_string,available)) {
 
1328
                                /*  This is not the expected string, recover the previous state and return. */
 
1329
                                goto return_NOT_OK;
 
1330
                        }
 
1331
                        /*  Advance the_string to the first untested character. */
 
1332
                        the_string += available;
 
1333
                        /*  update the remaining length and the parsed length. */
 
1334
                        remaining_len -= available;
 
1335
                        tested_len += available;
 
1336
                        SYNCTEX_CUR += available; /*  We validate the tested characters. */
 
1337
                        if (0 == remaining_len) {
 
1338
                                /*  Nothing left to test, we have found the given string. */
 
1339
                                return SYNCTEX_STATUS_OK;
 
1340
                        }
 
1341
                        goto more_characters;
 
1342
                }
 
1343
                /*  This is the last step. */
 
1344
                if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) {
 
1345
                        /*  This is not the expected string, recover the previous state and return. */
 
1346
                        goto return_NOT_OK;
 
1347
                }
 
1348
                goto return_OK;
 
1349
        } else {
 
1350
                /*  The buffer can't contain the given string argument, and the EOF was reached */
 
1351
                return SYNCTEX_STATUS_EOF;
 
1352
        }
4065
1353
}
4066
1354
 
4067
1355
/*  Used when parsing the synctex file.
4074
1362
 *  It is SYNCTEX_STATUS_OK if an int has been successfully parsed.
4075
1363
 *  The given scanner argument must not be NULL, on the contrary, value_ref may be NULL.
4076
1364
 */
4077
 
static synctex_is_s _synctex_decode_int(synctex_scanner_p scanner) {
4078
 
    char * ptr = NULL;
4079
 
    char * end = NULL;
4080
 
    synctex_zs_s zs = {0,0};
4081
 
    int result;
4082
 
    if (NULL == scanner) {
4083
 
        return (synctex_is_s){0, SYNCTEX_STATUS_BAD_ARGUMENT};
4084
 
    }
4085
 
    zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE);
4086
 
    if (zs.status<SYNCTEX_STATUS_EOF) {
4087
 
        return (synctex_is_s){0,zs.status};
4088
 
    }
4089
 
    if (zs.size==0) {
4090
 
        return (synctex_is_s){0,SYNCTEX_STATUS_NOT_OK};
4091
 
    }
4092
 
    ptr = SYNCTEX_CUR;
4093
 
    /*  Optionally parse the separator */
4094
 
    if (*ptr==':' || *ptr==',') {
4095
 
        ++ptr;
4096
 
        --zs.size;
4097
 
        if (zs.size==0) {
4098
 
            return (synctex_is_s){0,SYNCTEX_STATUS_NOT_OK};
4099
 
        }
4100
 
    }
4101
 
    result = (int)strtol(ptr, &end, 10);
4102
 
    if (end>ptr) {
4103
 
        SYNCTEX_CUR = end;
4104
 
        return (synctex_is_s){result,SYNCTEX_STATUS_OK};
4105
 
    }
4106
 
    return (synctex_is_s){result,SYNCTEX_STATUS_NOT_OK};
4107
 
}
4108
 
static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value) {
4109
 
    char * ptr = NULL;
4110
 
    char * end = NULL;
4111
 
    synctex_zs_s zs = {0, 0};
4112
 
    if (NULL == scanner) {
4113
 
        return (synctex_is_s){default_value, SYNCTEX_STATUS_BAD_ARGUMENT};
4114
 
    }
4115
 
    zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE);
4116
 
    if (zs.status<SYNCTEX_STATUS_EOF) {
4117
 
        return (synctex_is_s){default_value,zs.status};
4118
 
    }
4119
 
    if (zs.size==0) {
4120
 
        return (synctex_is_s){default_value,SYNCTEX_STATUS_OK};
4121
 
    }
4122
 
    ptr = SYNCTEX_CUR;
4123
 
    /*  Comma separator required */
4124
 
    if (*ptr==',') {
4125
 
        int result;
4126
 
        ++ptr;
4127
 
        --zs.size;
4128
 
        if (zs.size==0) {
4129
 
            return (synctex_is_s){default_value,SYNCTEX_STATUS_NOT_OK};
4130
 
        }
4131
 
        result = (int)strtol(ptr, &end, 10);
4132
 
        if (end>ptr) {
4133
 
            SYNCTEX_CUR = end;
4134
 
            return (synctex_is_s){result,SYNCTEX_STATUS_OK};
4135
 
        }
4136
 
        return (synctex_is_s){default_value,SYNCTEX_STATUS_NOT_OK};
4137
 
    }
4138
 
    return (synctex_is_s){default_value,SYNCTEX_STATUS_OK};
4139
 
}
4140
 
/*  Used when parsing the synctex file.
4141
 
 *  Decode an integer for a v field.
4142
 
 *  Try the _synctex_decode_int version and set the last v field scanned.
4143
 
 *  If it does not succeed, tries to match an '=' sign,
4144
 
 *  which is a shortcut for the last v field scanned.
4145
 
 */
4146
 
#   define SYNCTEX_INPUT_COMEQUALS ",="
4147
 
static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner) {
4148
 
    synctex_is_s is = _synctex_decode_int(scanner);
4149
 
    if (SYNCTEX_STATUS_OK == is.status) {
4150
 
        scanner->reader->lastv = is.integer;
4151
 
        return is;
4152
 
    }
4153
 
    is.status = _synctex_match_string(scanner,SYNCTEX_INPUT_COMEQUALS);
4154
 
    if (is.status<SYNCTEX_STATUS_OK) {
4155
 
        return is;
4156
 
    }
4157
 
    is.integer = scanner->reader->lastv;
4158
 
    return is;
 
1365
synctex_status_t _synctex_decode_int(synctex_scanner_t scanner, int* value_ref) {
 
1366
        char * ptr = NULL;
 
1367
        char * end = NULL;
 
1368
        int result = 0;
 
1369
        size_t available = 0;
 
1370
        synctex_status_t status = 0;
 
1371
        if (NULL == scanner) {
 
1372
                 return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1373
        }
 
1374
        available = SYNCTEX_BUFFER_MIN_SIZE;
 
1375
        status = _synctex_buffer_get_available_size(scanner, &available);
 
1376
        if (status<SYNCTEX_STATUS_EOF) {
 
1377
                return status;/*  Forward error. */
 
1378
        }
 
1379
        if (available==0) {
 
1380
                return SYNCTEX_STATUS_EOF;/*  it is the end of file. */
 
1381
        }
 
1382
        ptr = SYNCTEX_CUR;
 
1383
        if (*ptr==':' || *ptr==',') {
 
1384
                ++ptr;
 
1385
                --available;
 
1386
                if (available==0) {
 
1387
                        return SYNCTEX_STATUS_NOT_OK;/*  It is not possible to scan an int */
 
1388
                }
 
1389
        }
 
1390
        result = (int)strtol(ptr, &end, 10);
 
1391
        if (end>ptr) {
 
1392
                SYNCTEX_CUR = end;
 
1393
                if (value_ref) {
 
1394
                        * value_ref = result;
 
1395
                }
 
1396
                return SYNCTEX_STATUS_OK;/*  Successfully scanned an int */
 
1397
        }       
 
1398
        return SYNCTEX_STATUS_NOT_OK;/*  Could not scan an int */
4159
1399
}
4160
1400
 
4161
1401
/*  The purpose of this function is to read a string.
4164
1404
 *  If a string was properly decoded, it is returned in value_ref and
4165
1405
 *  the cursor points to the new line marker.
4166
1406
 *  The returned string was alloced on the heap, the caller is the owner and
4167
 
 *  is responsible to free it in due time,
4168
 
 *  unless it transfers the ownership to another object.
 
1407
 *  is responsible to free it in due time.
4169
1408
 *  If no string is parsed, * value_ref is undefined.
4170
1409
 *  The maximum length of a string that a scanner can decode is platform dependent, namely UINT_MAX.
4171
1410
 *  If you just want to blindly parse the file up to the end of the current line,
4176
1415
 *  If either scanner or value_ref is NULL, it is considered as an error and
4177
1416
 *  SYNCTEX_STATUS_BAD_ARGUMENT is returned.
4178
1417
 */
4179
 
static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner) {
4180
 
    char * end = NULL;
4181
 
    size_t len = 0;/*  The number of bytes to copy */
4182
 
    size_t already_len = 0;
4183
 
    synctex_zs_s zs = {0,0};
4184
 
    char * string = NULL;
4185
 
    if (NULL == scanner) {
4186
 
        return (synctex_ss_s){NULL,SYNCTEX_STATUS_BAD_ARGUMENT};
4187
 
    }
4188
 
    /*  The buffer must at least contain one character: the '\n' end of line marker */
4189
 
    if (SYNCTEX_CUR>=SYNCTEX_END) {
4190
 
more_characters:
4191
 
        zs = _synctex_buffer_get_available_size(scanner,1);
4192
 
        if (zs.status < SYNCTEX_STATUS_EOF) {
4193
 
            return (synctex_ss_s){NULL,zs.status};
4194
 
        } else if (0 == zs.size) {
4195
 
            return (synctex_ss_s){NULL,SYNCTEX_STATUS_EOF};
4196
 
        }
4197
 
    }
4198
 
    /*  Now we are sure that there is at least one available character, either because
4199
 
     *  SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */
4200
 
    /*  end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */
4201
 
    end = SYNCTEX_CUR;
4202
 
    /*  We scan all the characters up to the next '\n' */
4203
 
    while (end<SYNCTEX_END && *end != '\n') {
4204
 
        ++end;
4205
 
    }
4206
 
    /*  OK, we found where to stop:
4207
 
     *      either end == SYNCTEX_END
4208
 
     *      or *end == '\n' */
4209
 
    len = end - SYNCTEX_CUR;
4210
 
    if (len<UINT_MAX-already_len) {
4211
 
        if ((string = realloc(string,len+already_len+1)) != NULL) {
4212
 
            if (memcpy(string+already_len,SYNCTEX_CUR,len)) {
4213
 
                already_len += len;
4214
 
                string[already_len]='\0'; /*  Terminate the string */
4215
 
                SYNCTEX_CUR += len;/*  Eventually advance to the terminating '\n' */
4216
 
                if (SYNCTEX_CUR==SYNCTEX_END) {
4217
 
                    /* No \n found*/
4218
 
                    goto more_characters;
4219
 
                }
4220
 
                /* trim the trailing whites */
4221
 
                len = already_len;
4222
 
                while (len>0) {
4223
 
                    already_len = len--;
4224
 
                    if (string[len]!=' ') {
4225
 
                        break;
4226
 
                    }
4227
 
                }
4228
 
                string[already_len] = '\0';
4229
 
                return (synctex_ss_s){string,SYNCTEX_STATUS_OK};
4230
 
            }
4231
 
            free(string);
4232
 
            _synctex_error("could not copy memory (1).");
4233
 
            return (synctex_ss_s){NULL,SYNCTEX_STATUS_ERROR};
4234
 
        }
4235
 
    }
4236
 
    _synctex_error("could not (re)allocate memory (1).");
4237
 
    return (synctex_ss_s){NULL,SYNCTEX_STATUS_ERROR};
 
1418
synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value_ref) {
 
1419
        char * end = NULL;
 
1420
        size_t current_size = 0;
 
1421
        size_t new_size = 0;
 
1422
        size_t len = 0;/*  The number of bytes to copy */
 
1423
        size_t available = 0;
 
1424
        synctex_status_t status = 0;
 
1425
        if (NULL == scanner || NULL == value_ref) {
 
1426
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1427
        }
 
1428
        /*  The buffer must at least contain one character: the '\n' end of line marker */
 
1429
        if (SYNCTEX_CUR>=SYNCTEX_END) {
 
1430
                available = 1;
 
1431
                status = _synctex_buffer_get_available_size(scanner,&available);
 
1432
                if (status < 0) {
 
1433
                        return status;
 
1434
                }
 
1435
                if (0 == available) {
 
1436
                        return SYNCTEX_STATUS_EOF;
 
1437
                }
 
1438
        }
 
1439
        /*  Now we are sure that there is at least one available character, either because
 
1440
         *  SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */
 
1441
        /*  end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */
 
1442
        end = SYNCTEX_CUR;
 
1443
        * value_ref = NULL;/*  Initialize, it will be realloc'ed */
 
1444
        /*  We scan all the characters up to the next '\n' */
 
1445
next_character:
 
1446
        if (end<SYNCTEX_END) {
 
1447
                if (*end == '\n') {
 
1448
                        /*  OK, we found where to stop */
 
1449
                        len = end - SYNCTEX_CUR;
 
1450
                        if (current_size>UINT_MAX-len-1) {
 
1451
                                /*  But we have reached the limit: we do not have current_size+len+1>UINT_MAX.
 
1452
                                 *  We return the missing amount of memory.
 
1453
                                 *  This will never occur in practice. */
 
1454
                                return UINT_MAX-len-1 - current_size;
 
1455
                        }
 
1456
                        new_size = current_size+len;
 
1457
                        /*  We have current_size+len+1<=UINT_MAX
 
1458
                         *  or equivalently new_size<UINT_MAX,
 
1459
                         *  where we have assumed that len<UINT_MAX */
 
1460
                        if ((* value_ref = realloc(* value_ref,new_size+1)) != NULL) {
 
1461
                                if (memcpy((*value_ref)+current_size,SYNCTEX_CUR,len)) {
 
1462
                                        (* value_ref)[new_size]='\0'; /*  Terminate the string */
 
1463
                                        SYNCTEX_CUR += len;/*  Advance to the terminating '\n' */
 
1464
                                        return SYNCTEX_STATUS_OK;
 
1465
                                }
 
1466
                                free(* value_ref);
 
1467
                                * value_ref = NULL;
 
1468
                                _synctex_error("could not copy memory (1).");
 
1469
                                return SYNCTEX_STATUS_ERROR;
 
1470
                        }
 
1471
                        _synctex_error("could not allocate memory (1).");
 
1472
                        return SYNCTEX_STATUS_ERROR;
 
1473
                } else {
 
1474
                        ++end;
 
1475
                        goto next_character;
 
1476
                }
 
1477
        } else {
 
1478
                /*  end == SYNCTEX_END */
 
1479
                len = SYNCTEX_END - SYNCTEX_CUR;
 
1480
                if (current_size>UINT_MAX-len-1) {
 
1481
                        /*  We have reached the limit. */
 
1482
                        _synctex_error("limit reached (missing %i).",current_size-(UINT_MAX-len-1));
 
1483
                        return SYNCTEX_STATUS_ERROR;
 
1484
                }
 
1485
                new_size = current_size+len;
 
1486
                if ((* value_ref = realloc(* value_ref,new_size+1)) != NULL) {
 
1487
                        if (memcpy((*value_ref)+current_size,SYNCTEX_CUR,len)) {
 
1488
                                (* value_ref)[new_size]='\0'; /*  Terminate the string */
 
1489
                                SYNCTEX_CUR = SYNCTEX_END;/*  Advance the cursor to the end of the bufer */
 
1490
                                return SYNCTEX_STATUS_OK;
 
1491
                        }
 
1492
                        free(* value_ref);
 
1493
                        * value_ref = NULL;
 
1494
                        _synctex_error("could not copy memory (2).");
 
1495
                        return SYNCTEX_STATUS_ERROR;
 
1496
                }
 
1497
                /*  Huge memory problem */
 
1498
                _synctex_error("could not allocate memory (2).");
 
1499
                return SYNCTEX_STATUS_ERROR;
 
1500
        }
4238
1501
}
4239
1502
 
4240
1503
/*  Used when parsing the synctex file.
4241
1504
 *  Read an Input record.
4242
 
 *  - parameter scanner: non NULL scanner
4243
 
 *  - returns SYNCTEX_STATUS_OK on successful completions, others values otherwise.
4244
1505
 */
4245
 
static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner) {
4246
 
    synctex_node_p input = NULL;
4247
 
    synctex_status_t status = SYNCTEX_STATUS_BAD_ARGUMENT;
4248
 
    synctex_zs_s zs = {0,0};
4249
 
    if (NULL == scanner) {
4250
 
        return (synctex_ns_s){NULL,status};
4251
 
    }
4252
 
    if ((status=_synctex_match_string(scanner,SYNCTEX_INPUT_MARK))<SYNCTEX_STATUS_OK) {
4253
 
        return (synctex_ns_s){NULL,status};
4254
 
    }
4255
 
    /*  Create a node */
4256
 
    if (NULL == (input = _synctex_new_input(scanner))) {
4257
 
        _synctex_error("Could not create an input node.");
4258
 
        return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4259
 
    }
4260
 
    /*  Decode the tag  */
4261
 
    if ((status=_synctex_data_decode_tag(input))<SYNCTEX_STATUS_OK) {
4262
 
        _synctex_error("Bad format of input node.");
4263
 
        synctex_node_free(input);
4264
 
        return (synctex_ns_s){NULL,status};
4265
 
    }
4266
 
    /*  The next character is a field separator, we expect one character in the buffer. */
4267
 
    zs = _synctex_buffer_get_available_size(scanner, 1);
4268
 
    if (zs.status<=SYNCTEX_STATUS_ERROR) {
4269
 
        return (synctex_ns_s){NULL,status};
4270
 
    }
4271
 
    if (0 == zs.size) {
4272
 
        return (synctex_ns_s){NULL,SYNCTEX_STATUS_EOF};
4273
 
    }
4274
 
    /*  We can now safely advance to the next character, stepping over the field separator. */
4275
 
    ++SYNCTEX_CUR;
4276
 
    --zs.size;
4277
 
    /*  Then we scan the file name */
4278
 
    if ((status=_synctex_data_decode_name(input))<SYNCTEX_STATUS_OK) {
4279
 
        synctex_node_free(input);
4280
 
        _synctex_next_line(scanner);/* Ignore this whole line */
4281
 
        return (synctex_ns_s){NULL,status};
4282
 
    }
4283
 
    /*  Prepend this input node to the input linked list of the scanner */
4284
 
    __synctex_tree_set_sibling(input,scanner->input);/* input has no parent */
4285
 
    scanner->input = input;
 
1506
synctex_status_t _synctex_scan_input(synctex_scanner_t scanner) {
 
1507
        synctex_status_t status = 0;
 
1508
        size_t available = 0;
 
1509
        synctex_node_t input = NULL;
 
1510
        if (NULL == scanner) {
 
1511
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1512
        }
 
1513
        status = _synctex_match_string(scanner,SYNCTEX_INPUT_MARK);
 
1514
        if (status<SYNCTEX_STATUS_OK) {
 
1515
                return status;
 
1516
        }
 
1517
        /*  Create a node */
 
1518
        input = _synctex_new_input(scanner);
 
1519
        if (NULL == input) {
 
1520
                _synctex_error("could not create an input node.");
 
1521
                return SYNCTEX_STATUS_ERROR;
 
1522
        }
 
1523
        /*  Decode the synctag  */
 
1524
        status = _synctex_decode_int(scanner,&(SYNCTEX_TAG(input)));
 
1525
        if (status<SYNCTEX_STATUS_OK) {
 
1526
                _synctex_error("bad format of input node.");
 
1527
                SYNCTEX_FREE(input);
 
1528
                return status;
 
1529
        }
 
1530
        /*  The next character is a field separator, we expect one character in the buffer. */
 
1531
        available = 1;
 
1532
        status = _synctex_buffer_get_available_size(scanner, &available);
 
1533
        if (status<=SYNCTEX_STATUS_ERROR) {
 
1534
                return status;
 
1535
        }
 
1536
        if (0 == available) {
 
1537
                return SYNCTEX_STATUS_EOF;
 
1538
        }
 
1539
        /*  We can now safely advance to the next character, stepping over the field separator. */
 
1540
        ++SYNCTEX_CUR;
 
1541
        --available;
 
1542
        /*  Then we scan the file name */
 
1543
        status = _synctex_decode_string(scanner,&(SYNCTEX_NAME(input)));
 
1544
        if (status<SYNCTEX_STATUS_OK) {
 
1545
                SYNCTEX_FREE(input);
 
1546
                return status;
 
1547
        }
 
1548
        /*  Prepend this input node to the input linked list of the scanner */
 
1549
        SYNCTEX_SET_SIBLING(input,scanner->input);
 
1550
        scanner->input = input;
4286
1551
#   if SYNCTEX_VERBOSE
4287
 
    synctex_node_log(input);
 
1552
        synctex_node_log(input);
4288
1553
#   endif
4289
 
    return (synctex_ns_s){input,_synctex_next_line(scanner)};/*  read the line termination character, if any */
 
1554
        return _synctex_next_line(scanner);/*  read the line termination character, if any */
 
1555
        /*  Now, set up the path */
4290
1556
}
4291
1557
 
4292
 
typedef synctex_is_s (*synctex_decoder_t)(synctex_scanner_p);
 
1558
typedef synctex_status_t (*synctex_decoder_t)(synctex_scanner_t,void *);
 
1559
 
 
1560
synctex_status_t _synctex_scan_named(synctex_scanner_t scanner,const char * name,void * value_ref,synctex_decoder_t decoder);
4293
1561
 
4294
1562
/*  Used when parsing the synctex file.
4295
1563
 *  Read one of the settings.
4299
1567
 *  On return, the scanner points to the next character after the decoded object whatever it is.
4300
1568
 *  It is the responsibility of the caller to prepare the scanner for the next line.
4301
1569
 */
4302
 
static synctex_status_t _synctex_scan_named(synctex_scanner_p scanner,const char * name) {
4303
 
    synctex_status_t status = 0;
4304
 
    if (NULL == scanner || NULL == name) {
4305
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
4306
 
    }
 
1570
synctex_status_t _synctex_scan_named(synctex_scanner_t scanner,const char * name,void * value_ref,synctex_decoder_t decoder) {
 
1571
        synctex_status_t status = 0;
 
1572
        if (NULL == scanner || NULL == name || NULL == value_ref || NULL == decoder) {
 
1573
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1574
        }
4307
1575
not_found:
4308
 
    status = _synctex_match_string(scanner,name);
4309
 
    if (status<SYNCTEX_STATUS_NOT_OK) {
4310
 
        return status;
4311
 
    } else if (status == SYNCTEX_STATUS_NOT_OK) {
4312
 
        status = _synctex_next_line(scanner);
4313
 
        if (status<SYNCTEX_STATUS_OK) {
4314
 
            return status;
4315
 
        }
4316
 
        goto not_found;
4317
 
    }
4318
 
    return SYNCTEX_STATUS_OK;
 
1576
        status = _synctex_match_string(scanner,name);
 
1577
        if (status<SYNCTEX_STATUS_NOT_OK) {
 
1578
                return status;
 
1579
        } else if (status == SYNCTEX_STATUS_NOT_OK) {
 
1580
                status = _synctex_next_line(scanner);
 
1581
                if (status<SYNCTEX_STATUS_OK) {
 
1582
                        return status;
 
1583
                }
 
1584
                goto not_found;
 
1585
        }
 
1586
        /*  A line is found, scan the value */
 
1587
        return (*decoder)(scanner,value_ref);
4319
1588
}
4320
1589
 
4321
1590
/*  Used when parsing the synctex file.
4322
1591
 *  Read the preamble.
4323
1592
 */
4324
 
static synctex_status_t _synctex_scan_preamble(synctex_scanner_p scanner) {
4325
 
    synctex_status_t status = 0;
4326
 
    synctex_is_s is = {0,0};
4327
 
    synctex_ss_s ss = {NULL,0};
4328
 
    if (NULL == scanner) {
4329
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
4330
 
    }
4331
 
    status = _synctex_scan_named(scanner,"SyncTeX Version:");
4332
 
    if (status<SYNCTEX_STATUS_OK) {
4333
 
        return status;
4334
 
    }
4335
 
    is = _synctex_decode_int(scanner);
4336
 
    if (is.status<SYNCTEX_STATUS_OK) {
4337
 
        return is.status;
4338
 
    }
4339
 
    status = _synctex_next_line(scanner);
4340
 
    if (status<SYNCTEX_STATUS_OK) {
4341
 
        return status;
4342
 
    }
4343
 
    scanner->version = is.integer;
4344
 
    /*  Read all the input records */
4345
 
    do {
4346
 
        status = __synctex_parse_new_input(scanner).status;
4347
 
        if (status<SYNCTEX_STATUS_NOT_OK) {
4348
 
            return status;
4349
 
        }
4350
 
    } while(status == SYNCTEX_STATUS_OK);
4351
 
    /*  the loop exits when status == SYNCTEX_STATUS_NOT_OK */
4352
 
    /*  Now read all the required settings. */
4353
 
    if ((status=_synctex_scan_named(scanner,"Output:"))<SYNCTEX_STATUS_OK) {
4354
 
        return status;
4355
 
    }
4356
 
    if ((ss=_synctex_decode_string(scanner)).status<SYNCTEX_STATUS_OK) {
4357
 
        return is.status;
4358
 
    }
4359
 
    if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) {
4360
 
        return status;
4361
 
    }
4362
 
    scanner->output_fmt = ss.string;
4363
 
    if ((status=_synctex_scan_named(scanner,"Magnification:"))<SYNCTEX_STATUS_OK) {
4364
 
        return status;
4365
 
    }
4366
 
    if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) {
4367
 
        return is.status;
4368
 
    }
4369
 
    if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) {
4370
 
        return status;
4371
 
    }
4372
 
    scanner->pre_magnification = is.integer;
4373
 
    if ((status=_synctex_scan_named(scanner,"Unit:"))<SYNCTEX_STATUS_OK) {
4374
 
        return status;
4375
 
    }
4376
 
    if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) {
4377
 
        return is.status;
4378
 
    }
4379
 
    if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) {
4380
 
        return status;
4381
 
    }
4382
 
    scanner->pre_unit = is.integer;
4383
 
    if ((status=_synctex_scan_named(scanner,"X Offset:"))<SYNCTEX_STATUS_OK) {
4384
 
        return status;
4385
 
    }
4386
 
    if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) {
4387
 
        return is.status;
4388
 
    }
4389
 
    if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) {
4390
 
        return status;
4391
 
    }
4392
 
    scanner->pre_x_offset = is.integer;
4393
 
    if ((status=_synctex_scan_named(scanner,"Y Offset:"))<SYNCTEX_STATUS_OK) {
4394
 
        return status;
4395
 
    }
4396
 
    if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) {
4397
 
        return is.status;
4398
 
    }
4399
 
    if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) {
4400
 
        return status;
4401
 
    }
4402
 
    scanner->pre_y_offset = is.integer;
4403
 
    return SYNCTEX_STATUS_OK;
 
1593
synctex_status_t _synctex_scan_preamble(synctex_scanner_t scanner) {
 
1594
        synctex_status_t status = 0;
 
1595
        if (NULL == scanner) {
 
1596
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1597
        }
 
1598
        status = _synctex_scan_named(scanner,"SyncTeX Version:",&(scanner->version),(synctex_decoder_t)&_synctex_decode_int);
 
1599
        if (status<SYNCTEX_STATUS_OK) {
 
1600
                return status;
 
1601
        }
 
1602
        status = _synctex_next_line(scanner);
 
1603
        if (status<SYNCTEX_STATUS_OK) {
 
1604
                return status;
 
1605
        }
 
1606
        /*  Read all the input records */
 
1607
        do {
 
1608
                status = _synctex_scan_input(scanner);
 
1609
                if (status<SYNCTEX_STATUS_NOT_OK) {
 
1610
                        return status;
 
1611
                }
 
1612
        } while(status == SYNCTEX_STATUS_OK);
 
1613
        /*  the loop exits when status == SYNCTEX_STATUS_NOT_OK */
 
1614
        /*  Now read all the required settings. */
 
1615
        status = _synctex_scan_named(scanner,"Output:",&(scanner->output_fmt),(synctex_decoder_t)&_synctex_decode_string);
 
1616
        if (status<SYNCTEX_STATUS_NOT_OK) {
 
1617
                return status;
 
1618
        }
 
1619
        status = _synctex_next_line(scanner);
 
1620
        if (status<SYNCTEX_STATUS_OK) {
 
1621
                return status;
 
1622
        }
 
1623
        status = _synctex_scan_named(scanner,"Magnification:",&(scanner->pre_magnification),(synctex_decoder_t)&_synctex_decode_int);
 
1624
        if (status<SYNCTEX_STATUS_OK) {
 
1625
                return status;
 
1626
        }
 
1627
        status = _synctex_next_line(scanner);
 
1628
        if (status<SYNCTEX_STATUS_OK) {
 
1629
                return status;
 
1630
        }
 
1631
        status = _synctex_scan_named(scanner,"Unit:",&(scanner->pre_unit),(synctex_decoder_t)&_synctex_decode_int);
 
1632
        if (status<SYNCTEX_STATUS_OK) {
 
1633
                return status;
 
1634
        }
 
1635
        status = _synctex_next_line(scanner);
 
1636
        if (status<SYNCTEX_STATUS_OK) {
 
1637
                return status;
 
1638
        }
 
1639
        status = _synctex_scan_named(scanner,"X Offset:",&(scanner->pre_x_offset),(synctex_decoder_t)&_synctex_decode_int);
 
1640
        if (status<SYNCTEX_STATUS_OK) {
 
1641
                return status;
 
1642
        }
 
1643
        status = _synctex_next_line(scanner);
 
1644
        if (status<SYNCTEX_STATUS_OK) {
 
1645
                return status;
 
1646
        }
 
1647
        status = _synctex_scan_named(scanner,"Y Offset:",&(scanner->pre_y_offset),(synctex_decoder_t)&_synctex_decode_int);
 
1648
        if (status<SYNCTEX_STATUS_OK) {
 
1649
                return status;
 
1650
        }
 
1651
        return _synctex_next_line(scanner);
4404
1652
}
4405
1653
 
4406
1654
/*  parse a float with a dimension */
4407
 
static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner) {
4408
 
    synctex_fs_s fs = {0,0};
4409
 
    synctex_zs_s zs = {0,0};
4410
 
    char * endptr = NULL;
4411
 
#ifdef HAVE_SETLOCALE
4412
 
    char * loc = setlocale(LC_NUMERIC, NULL);
4413
 
#endif
4414
 
    if (NULL == scanner) {
4415
 
        return (synctex_fs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT};
4416
 
    }
4417
 
    zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE);
4418
 
    if (zs.status<SYNCTEX_STATUS_EOF) {
4419
 
        _synctex_error("Problem with float.");
4420
 
        return (synctex_fs_s){0,zs.status};
4421
 
    }
4422
 
#ifdef HAVE_SETLOCALE
4423
 
    setlocale(LC_NUMERIC, "C");
4424
 
#endif
4425
 
    fs.value = strtod(SYNCTEX_CUR,&endptr);
4426
 
#ifdef HAVE_SETLOCALE
4427
 
    setlocale(LC_NUMERIC, loc);
4428
 
#endif
4429
 
    if (endptr == SYNCTEX_CUR) {
4430
 
        _synctex_error("A float was expected.");
4431
 
        return (synctex_fs_s){0,SYNCTEX_STATUS_ERROR};
4432
 
    }
4433
 
    SYNCTEX_CUR = endptr;
4434
 
    if ((fs.status = _synctex_match_string(scanner,"in")) >= SYNCTEX_STATUS_OK) {
4435
 
        fs.value *= 72.27f*65536;
4436
 
    } else if (fs.status<SYNCTEX_STATUS_EOF) {
4437
 
    report_unit_error:
4438
 
        _synctex_error("problem with unit.");
4439
 
        return fs;
4440
 
    } else if ((fs.status = _synctex_match_string(scanner,"cm")) >= SYNCTEX_STATUS_OK) {
4441
 
        fs.value *= 72.27f*65536/2.54f;
4442
 
    } else if (fs.status<SYNCTEX_STATUS_EOF) {
4443
 
        goto report_unit_error;
4444
 
    } else if ((fs.status = _synctex_match_string(scanner,"mm")) >= SYNCTEX_STATUS_OK) {
4445
 
        fs.value *= 72.27f*65536/25.4f;
4446
 
    } else if (fs.status<SYNCTEX_STATUS_EOF) {
4447
 
        goto report_unit_error;
4448
 
    } else if ((fs.status = _synctex_match_string(scanner,"pt")) >= SYNCTEX_STATUS_OK) {
4449
 
        fs.value *= 65536.0f;
4450
 
    } else if (fs.status<SYNCTEX_STATUS_EOF) {
4451
 
        goto report_unit_error;
4452
 
    } else if ((fs.status = _synctex_match_string(scanner,"bp")) >= SYNCTEX_STATUS_OK) {
4453
 
        fs.value *= 72.27f/72*65536.0f;
4454
 
    }  else if (fs.status<SYNCTEX_STATUS_EOF) {
4455
 
        goto report_unit_error;
4456
 
    } else if ((fs.status = _synctex_match_string(scanner,"pc")) >= SYNCTEX_STATUS_OK) {
4457
 
        fs.value *= 12.0*65536.0f;
4458
 
    }  else if (fs.status<SYNCTEX_STATUS_EOF) {
4459
 
        goto report_unit_error;
4460
 
    } else if ((fs.status = _synctex_match_string(scanner,"sp")) >= SYNCTEX_STATUS_OK) {
4461
 
        fs.value *= 1.0f;
4462
 
    }  else if (fs.status<SYNCTEX_STATUS_EOF) {
4463
 
        goto report_unit_error;
4464
 
    } else if ((fs.status = _synctex_match_string(scanner,"dd")) >= SYNCTEX_STATUS_OK) {
4465
 
        fs.value *= 1238.0f/1157*65536.0f;
4466
 
    }  else if (fs.status<SYNCTEX_STATUS_EOF) {
4467
 
        goto report_unit_error;
4468
 
    } else if ((fs.status = _synctex_match_string(scanner,"cc")) >= SYNCTEX_STATUS_OK) {
4469
 
        fs.value *= 14856.0f/1157*65536;
4470
 
    } else if (fs.status<SYNCTEX_STATUS_EOF) {
4471
 
        goto report_unit_error;
4472
 
    } else if ((fs.status = _synctex_match_string(scanner,"nd")) >= SYNCTEX_STATUS_OK) {
4473
 
        fs.value *= 685.0f/642*65536;
4474
 
    }  else if (fs.status<SYNCTEX_STATUS_EOF) {
4475
 
        goto report_unit_error;
4476
 
    } else if ((fs.status = _synctex_match_string(scanner,"nc")) >= SYNCTEX_STATUS_OK) {
4477
 
        fs.value *= 1370.0f/107*65536;
4478
 
    } else if (fs.status<SYNCTEX_STATUS_EOF) {
4479
 
        goto report_unit_error;
4480
 
    }
4481
 
    return fs;
 
1655
synctex_status_t _synctex_scan_float_and_dimension(synctex_scanner_t scanner, float * value_ref) {
 
1656
        synctex_status_t status = 0;
 
1657
        char * endptr = NULL;
 
1658
        float f = 0;
 
1659
#ifdef HAVE_SETLOCALE
 
1660
        char * loc = setlocale(LC_NUMERIC, NULL);
 
1661
#endif
 
1662
        size_t available = 0;
 
1663
        if (NULL == scanner || NULL == value_ref) {
 
1664
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1665
        }
 
1666
        available = SYNCTEX_BUFFER_MIN_SIZE;
 
1667
        status = _synctex_buffer_get_available_size(scanner, &available);
 
1668
        if (status<SYNCTEX_STATUS_EOF) {
 
1669
                _synctex_error("problem with float.");
 
1670
                return status;
 
1671
        }
 
1672
#ifdef HAVE_SETLOCALE
 
1673
        setlocale(LC_NUMERIC, "C");
 
1674
#endif
 
1675
        f = strtod(SYNCTEX_CUR,&endptr);
 
1676
#ifdef HAVE_SETLOCALE
 
1677
        setlocale(LC_NUMERIC, loc);
 
1678
#endif
 
1679
        if (endptr == SYNCTEX_CUR) {
 
1680
                _synctex_error("a float was expected.");
 
1681
                return SYNCTEX_STATUS_ERROR;
 
1682
        }
 
1683
        SYNCTEX_CUR = endptr;
 
1684
        if ((status = _synctex_match_string(scanner,"in")) >= SYNCTEX_STATUS_OK) {
 
1685
                f *= 72.27f*65536;
 
1686
        } else if (status<SYNCTEX_STATUS_EOF) {
 
1687
report_unit_error:
 
1688
                _synctex_error("problem with unit.");
 
1689
                return status;
 
1690
        } else if ((status = _synctex_match_string(scanner,"cm")) >= SYNCTEX_STATUS_OK) {
 
1691
                f *= 72.27f*65536/2.54f;
 
1692
        } else if (status<0) {
 
1693
                goto report_unit_error;
 
1694
        } else if ((status = _synctex_match_string(scanner,"mm")) >= SYNCTEX_STATUS_OK) {
 
1695
                f *= 72.27f*65536/25.4f;
 
1696
        } else if (status<0) {
 
1697
                goto report_unit_error;
 
1698
        } else if ((status = _synctex_match_string(scanner,"pt")) >= SYNCTEX_STATUS_OK) {
 
1699
                f *= 65536.0f;
 
1700
        } else if (status<0) {
 
1701
                goto report_unit_error;
 
1702
        } else if ((status = _synctex_match_string(scanner,"bp")) >= SYNCTEX_STATUS_OK) {
 
1703
                f *= 72.27f/72*65536.0f;
 
1704
        }  else if (status<0) {
 
1705
                goto report_unit_error;
 
1706
        } else if ((status = _synctex_match_string(scanner,"pc")) >= SYNCTEX_STATUS_OK) {
 
1707
                f *= 12.0*65536.0f;
 
1708
        }  else if (status<0) {
 
1709
                goto report_unit_error;
 
1710
        } else if ((status = _synctex_match_string(scanner,"sp")) >= SYNCTEX_STATUS_OK) {
 
1711
                f *= 1.0f;
 
1712
        }  else if (status<0) {
 
1713
                goto report_unit_error;
 
1714
        } else if ((status = _synctex_match_string(scanner,"dd")) >= SYNCTEX_STATUS_OK) {
 
1715
                f *= 1238.0f/1157*65536.0f;
 
1716
        }  else if (status<0) {
 
1717
                goto report_unit_error;
 
1718
        } else if ((status = _synctex_match_string(scanner,"cc")) >= SYNCTEX_STATUS_OK) {
 
1719
                f *= 14856.0f/1157*65536;
 
1720
        } else if (status<0) {
 
1721
                goto report_unit_error;
 
1722
        } else if ((status = _synctex_match_string(scanner,"nd")) >= SYNCTEX_STATUS_OK) {
 
1723
                f *= 685.0f/642*65536;
 
1724
        }  else if (status<0) {
 
1725
                goto report_unit_error;
 
1726
        } else if ((status = _synctex_match_string(scanner,"nc")) >= SYNCTEX_STATUS_OK) {
 
1727
                f *= 1370.0f/107*65536;
 
1728
        } else if (status<0) {
 
1729
                goto report_unit_error;
 
1730
        }
 
1731
        *value_ref = f;
 
1732
        return SYNCTEX_STATUS_OK;
4482
1733
}
4483
1734
 
4484
1735
/*  parse the post scriptum
4485
1736
 *  SYNCTEX_STATUS_OK is returned on completion
4486
1737
 *  a negative error is returned otherwise */
4487
 
static synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_p scanner) {
4488
 
    synctex_status_t status = 0;
4489
 
    synctex_fs_s fs = {0,0};
4490
 
    char * endptr = NULL;
 
1738
synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_t scanner) {
 
1739
        synctex_status_t status = 0;
 
1740
        char * endptr = NULL;
4491
1741
#ifdef HAVE_SETLOCALE
4492
 
    char * loc = setlocale(LC_NUMERIC, NULL);
 
1742
        char * loc = setlocale(LC_NUMERIC, NULL);
4493
1743
#endif
4494
 
    if (NULL == scanner) {
4495
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
4496
 
    }
4497
 
    /*  Scan the file until a post scriptum line is found */
 
1744
        if (NULL == scanner) {
 
1745
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1746
        }
 
1747
        /*  Scan the file until a post scriptum line is found */
4498
1748
post_scriptum_not_found:
4499
 
    status = _synctex_match_string(scanner,"Post scriptum:");
4500
 
    if (status<SYNCTEX_STATUS_NOT_OK) {
4501
 
        return status;
4502
 
    }
4503
 
    if (status == SYNCTEX_STATUS_NOT_OK) {
4504
 
        status = _synctex_next_line(scanner);
4505
 
        if (status<SYNCTEX_STATUS_EOF) {
4506
 
            return status;
4507
 
        } else if (status<SYNCTEX_STATUS_OK) {
4508
 
            return SYNCTEX_STATUS_OK;/*  The EOF is found, we have properly scanned the file */
4509
 
        }
4510
 
        goto post_scriptum_not_found;
4511
 
    }
4512
 
    /*  We found the name, advance to the next line. */
 
1749
        status = _synctex_match_string(scanner,"Post scriptum:");
 
1750
        if (status<SYNCTEX_STATUS_NOT_OK) {
 
1751
                return status;
 
1752
        }
 
1753
        if (status == SYNCTEX_STATUS_NOT_OK) {
 
1754
                status = _synctex_next_line(scanner);
 
1755
                if (status<SYNCTEX_STATUS_EOF) {
 
1756
                        return status;
 
1757
                } else if (status<SYNCTEX_STATUS_OK) {
 
1758
                        return SYNCTEX_STATUS_OK;/*  The EOF is found, we have properly scanned the file */
 
1759
                }
 
1760
                goto post_scriptum_not_found;
 
1761
        }
 
1762
        /*  We found the name, advance to the next line. */
4513
1763
next_line:
4514
 
    status = _synctex_next_line(scanner);
4515
 
    if (status<SYNCTEX_STATUS_EOF) {
4516
 
        return status;
4517
 
    } else if (status<SYNCTEX_STATUS_OK) {
4518
 
        return SYNCTEX_STATUS_OK;/*  The EOF is found, we have properly scanned the file */
4519
 
    }
4520
 
    /*  Scanning the information */
4521
 
    status = _synctex_match_string(scanner,"Magnification:");
4522
 
    if (status == SYNCTEX_STATUS_OK ) {
4523
 
#ifdef HAVE_SETLOCALE
4524
 
        setlocale(LC_NUMERIC, "C");
4525
 
#endif
4526
 
        scanner->unit = strtod(SYNCTEX_CUR,&endptr);
4527
 
#ifdef HAVE_SETLOCALE
4528
 
        setlocale(LC_NUMERIC, loc);
4529
 
#endif
4530
 
        if (endptr == SYNCTEX_CUR) {
4531
 
            _synctex_error("bad magnification in the post scriptum, a float was expected.");
4532
 
            return SYNCTEX_STATUS_ERROR;
4533
 
        }
4534
 
        if (scanner->unit<=0) {
4535
 
            _synctex_error("bad magnification in the post scriptum, a positive float was expected.");
4536
 
            return SYNCTEX_STATUS_ERROR;
4537
 
        }
4538
 
        SYNCTEX_CUR = endptr;
4539
 
        goto next_line;
4540
 
    }
4541
 
    if (status<SYNCTEX_STATUS_EOF){
4542
 
    report_record_problem:
4543
 
        _synctex_error("Problem reading the Post Scriptum records");
4544
 
        return status; /*  echo the error. */
4545
 
    }
4546
 
    status = _synctex_match_string(scanner,"X Offset:");
4547
 
    if (status == SYNCTEX_STATUS_OK) {
4548
 
        fs = _synctex_scan_float_and_dimension(scanner);
4549
 
        if (fs.status<SYNCTEX_STATUS_OK) {
4550
 
            _synctex_error("Problem with X offset in the Post Scriptum.");
4551
 
            return fs.status;
4552
 
        }
4553
 
        scanner->x_offset = fs.value;
4554
 
        goto next_line;
4555
 
    } else if (status<SYNCTEX_STATUS_EOF){
4556
 
        goto report_record_problem;
4557
 
    }
4558
 
    status = _synctex_match_string(scanner,"Y Offset:");
4559
 
    if (status==SYNCTEX_STATUS_OK) {
4560
 
        fs = _synctex_scan_float_and_dimension(scanner);
4561
 
        if (fs.status<SYNCTEX_STATUS_OK) {
4562
 
            _synctex_error("Problem with Y offset in the Post Scriptum.");
4563
 
            return fs.status;
4564
 
        }
4565
 
        scanner->y_offset = fs.value;
4566
 
        goto next_line;
4567
 
    } else if (status<SYNCTEX_STATUS_EOF){
4568
 
        goto report_record_problem;
4569
 
    }
4570
 
    goto next_line;
 
1764
        status = _synctex_next_line(scanner);
 
1765
        if (status<SYNCTEX_STATUS_EOF) {
 
1766
                return status;
 
1767
        } else if (status<SYNCTEX_STATUS_OK) {
 
1768
                return SYNCTEX_STATUS_OK;/*  The EOF is found, we have properly scanned the file */
 
1769
        }
 
1770
        /*  Scanning the information */
 
1771
        status = _synctex_match_string(scanner,"Magnification:");
 
1772
        if (status == SYNCTEX_STATUS_OK ) {
 
1773
#ifdef HAVE_SETLOCALE
 
1774
                setlocale(LC_NUMERIC, "C");
 
1775
#endif
 
1776
                scanner->unit = strtod(SYNCTEX_CUR,&endptr);
 
1777
#ifdef HAVE_SETLOCALE
 
1778
                setlocale(LC_NUMERIC, loc);
 
1779
#endif
 
1780
                if (endptr == SYNCTEX_CUR) {
 
1781
                        _synctex_error("bad magnification in the post scriptum, a float was expected.");
 
1782
                        return SYNCTEX_STATUS_ERROR;
 
1783
                }
 
1784
                if (scanner->unit<=0) {
 
1785
                        _synctex_error("bad magnification in the post scriptum, a positive float was expected.");
 
1786
                        return SYNCTEX_STATUS_ERROR;
 
1787
                }
 
1788
                SYNCTEX_CUR = endptr;
 
1789
                goto next_line;
 
1790
        }
 
1791
        if (status<SYNCTEX_STATUS_EOF){
 
1792
report_record_problem:
 
1793
                _synctex_error("Problem reading the Post Scriptum records");
 
1794
                return status; /*  echo the error. */
 
1795
        }
 
1796
        status = _synctex_match_string(scanner,"X Offset:");
 
1797
        if (status == SYNCTEX_STATUS_OK) {
 
1798
                status = _synctex_scan_float_and_dimension(scanner, &(scanner->x_offset));
 
1799
                if (status<SYNCTEX_STATUS_OK) {
 
1800
                        _synctex_error("problem with X offset in the Post Scriptum.");
 
1801
                        return status;
 
1802
                }
 
1803
                goto next_line;
 
1804
        } else if (status<SYNCTEX_STATUS_EOF){
 
1805
                goto report_record_problem;
 
1806
        }
 
1807
        status = _synctex_match_string(scanner,"Y Offset:");
 
1808
        if (status==SYNCTEX_STATUS_OK) {
 
1809
                status = _synctex_scan_float_and_dimension(scanner, &(scanner->y_offset));
 
1810
                if (status<SYNCTEX_STATUS_OK) {
 
1811
                        _synctex_error("problem with Y offset in the Post Scriptum.");
 
1812
                        return status;
 
1813
                }
 
1814
                goto next_line;
 
1815
        } else if (status<SYNCTEX_STATUS_EOF){
 
1816
                goto report_record_problem;
 
1817
        }
 
1818
        goto next_line;
4571
1819
}
4572
1820
 
4573
1821
/*  SYNCTEX_STATUS_OK is returned if the postamble is read
4575
1823
 *  a negative error otherwise
4576
1824
 *  The postamble comprises the post scriptum section.
4577
1825
 */
4578
 
static synctex_status_t _synctex_scan_postamble(synctex_scanner_p scanner) {
4579
 
    synctex_status_t status = 0;
4580
 
    synctex_is_s is = {0,0};
4581
 
    if (NULL == scanner) {
4582
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
4583
 
    }
4584
 
    if (!scanner->flags.postamble && (status=_synctex_match_string(scanner,"Postamble:"))<SYNCTEX_STATUS_OK) {
4585
 
        return status;
4586
 
    }
 
1826
synctex_status_t _synctex_scan_postamble(synctex_scanner_t scanner) {
 
1827
        synctex_status_t status = 0;
 
1828
        if (NULL == scanner) {
 
1829
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1830
        }
 
1831
        status = _synctex_match_string(scanner,"Postamble:");
 
1832
        if (status < SYNCTEX_STATUS_OK) {
 
1833
                return status;
 
1834
        }
4587
1835
count_again:
4588
 
    if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) {
4589
 
        return status;
4590
 
    }
4591
 
    if ((status=_synctex_scan_named(scanner,"Count:"))< SYNCTEX_STATUS_EOF) {
4592
 
        return status; /*  forward the error */
4593
 
    } else if (status < SYNCTEX_STATUS_OK) { /*  No Count record found */
4594
 
        goto count_again;
4595
 
    }
4596
 
    if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) {
4597
 
        return is.status;
4598
 
    }
4599
 
    if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) {
4600
 
        return status;
4601
 
    }
4602
 
    scanner->count = is.integer;
4603
 
    /*  Now we scan the last part of the SyncTeX file: the Post Scriptum section. */
4604
 
    return _synctex_scan_post_scriptum(scanner);
 
1836
        status = _synctex_next_line(scanner);
 
1837
        if (status < SYNCTEX_STATUS_OK) {
 
1838
                return status;
 
1839
        }
 
1840
        status = _synctex_scan_named(scanner,"Count:",&(scanner->count),(synctex_decoder_t)&_synctex_decode_int);
 
1841
        if (status < SYNCTEX_STATUS_EOF) {
 
1842
                return status; /*  forward the error */
 
1843
        } else if (status < SYNCTEX_STATUS_OK) { /*  No Count record found */
 
1844
                status = _synctex_next_line(scanner); /*  Advance one more line */
 
1845
                if (status<SYNCTEX_STATUS_OK) {
 
1846
                        return status;
 
1847
                }
 
1848
                goto count_again;
 
1849
        }
 
1850
        /*  Now we scan the last part of the SyncTeX file: the Post Scriptum section. */
 
1851
        return _synctex_scan_post_scriptum(scanner);
4605
1852
}
4606
1853
 
4607
1854
/*  Horizontal boxes also have visible size.
4609
1856
 *  For example 0 width boxes may contain text.
4610
1857
 *  At creation time, the visible size is set to the values of the real size.
4611
1858
 */
4612
 
static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box) {
4613
 
    if (box) {
4614
 
        switch(synctex_node_type(box)) {
4615
 
            case synctex_node_type_hbox:
4616
 
                _synctex_data_set_h_V(box,_synctex_data_h(box));
4617
 
                _synctex_data_set_v_V(box,_synctex_data_v(box));
4618
 
                _synctex_data_set_width_V(box,_synctex_data_width(box));
4619
 
                _synctex_data_set_height_V(box,_synctex_data_height(box));
4620
 
                _synctex_data_set_depth_V(box,_synctex_data_depth(box));
4621
 
                return SYNCTEX_STATUS_OK;
4622
 
            default:
4623
 
                break;
4624
 
        }
4625
 
    }
4626
 
    return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1859
synctex_status_t _synctex_setup_visible_box(synctex_node_t box) {
 
1860
        if (box) {
 
1861
                switch(box->class->type) {
 
1862
                        case synctex_node_type_hbox:
 
1863
                                if (SYNCTEX_INFO(box) != NULL) {
 
1864
                                        SYNCTEX_HORIZ_V(box)  = SYNCTEX_HORIZ(box);
 
1865
                                        SYNCTEX_VERT_V(box)   = SYNCTEX_VERT(box);
 
1866
                                        SYNCTEX_WIDTH_V(box)  = SYNCTEX_WIDTH(box);
 
1867
                                        SYNCTEX_HEIGHT_V(box) = SYNCTEX_HEIGHT(box);
 
1868
                                        SYNCTEX_DEPTH_V(box)  = SYNCTEX_DEPTH(box);
 
1869
                                        return SYNCTEX_STATUS_OK;
 
1870
                                }
 
1871
                                return SYNCTEX_STATUS_ERROR;
 
1872
                }
 
1873
        }
 
1874
        return SYNCTEX_STATUS_BAD_ARGUMENT;
4627
1875
}
4628
1876
 
4629
1877
/*  This method is sent to an horizontal box to setup the visible size
4630
1878
 *  Some box have 0 width but do contain text material.
4631
1879
 *  With this method, one can enlarge the box to contain the given point (h,v).
4632
1880
 */
4633
 
static synctex_status_t _synctex_make_hbox_contain_point(synctex_node_p node,synctex_point_s point) {
4634
 
    int min, max, n;
4635
 
    if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) {
4636
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
4637
 
    }
4638
 
    if ((n = _synctex_data_width_V(node))<0) {
4639
 
        max = _synctex_data_h_V(node);
4640
 
        min = max+n;
4641
 
        if (point.h<min) {
4642
 
            _synctex_data_set_width_V(node,point.h-max);
4643
 
        } else if (point.h>max) {
4644
 
            _synctex_data_set_h_V(node,point.h);
4645
 
            _synctex_data_set_width_V(node,min-point.h);
4646
 
        }
4647
 
    } else {
4648
 
        min = _synctex_data_h_V(node);
4649
 
        max = min+n;
4650
 
        if (point.h<min) {
4651
 
            _synctex_data_set_h_V(node,point.h);
4652
 
            _synctex_data_set_width_V(node,max - point.h);
4653
 
        } else if (point.h>max) {
4654
 
            _synctex_data_set_width_V(node,point.h - min);
4655
 
        }
4656
 
    }
4657
 
    n = _synctex_data_v_V(node);
4658
 
    min = n - _synctex_data_height_V(node);
4659
 
    max = n + _synctex_data_depth_V(node);
4660
 
    if (point.v<min) {
4661
 
        _synctex_data_set_height_V(node,n-point.v);
4662
 
    } else if (point.v>max) {
4663
 
        _synctex_data_set_depth_V(node,point.v-n);
4664
 
    }
4665
 
    return SYNCTEX_STATUS_OK;
4666
 
}
4667
 
static synctex_status_t _synctex_make_hbox_contain_box(synctex_node_p node,synctex_box_s box) {
4668
 
    int min, max, n;
4669
 
    if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) {
4670
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
4671
 
    }
4672
 
    if ((n = _synctex_data_width_V(node))<0) {
4673
 
        max = _synctex_data_h_V(node);
4674
 
        min = max+n;
4675
 
        if (box.min.h <min) {
4676
 
            _synctex_data_set_width_V(node,box.min.h-max);
4677
 
        } else if (box.max.h>max) {
4678
 
            _synctex_data_set_h_V(node,box.max.h);
4679
 
            _synctex_data_set_width_V(node,min-box.max.h);
4680
 
        }
4681
 
    } else {
4682
 
        min = _synctex_data_h_V(node);
4683
 
        max = min+n;
4684
 
        if (box.min.h<min) {
4685
 
            _synctex_data_set_h_V(node,box.min.h);
4686
 
            _synctex_data_set_width_V(node,max - box.min.h);
4687
 
        } else if (box.max.h>max) {
4688
 
            _synctex_data_set_width_V(node,box.max.h - min);
4689
 
        }
4690
 
    }
4691
 
    n = _synctex_data_v_V(node);
4692
 
    min = n - _synctex_data_height_V(node);
4693
 
    max = n + _synctex_data_depth_V(node);
4694
 
    if (box.min.v<min) {
4695
 
        _synctex_data_set_height_V(node,n-box.min.v);
4696
 
    } else if (box.max.v>max) {
4697
 
        _synctex_data_set_depth_V(node,box.max.v-n);
4698
 
    }
4699
 
    return SYNCTEX_STATUS_OK;
4700
 
}
4701
 
#       ifdef SYNCTEX_NOTHING
4702
 
#       pragma mark -
4703
 
#       pragma mark SPECIAL CHARACTERS
 
1881
synctex_status_t _synctex_hbox_setup_visible(synctex_node_t node,int h, int v) {
 
1882
#       ifdef __DARWIN_UNIX03
 
1883
#       pragma unused(v)
4704
1884
#   endif
4705
 
 
 
1885
        int itsBtm, itsTop;
 
1886
        if (NULL == node || node->class->type != synctex_node_type_hbox) {
 
1887
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1888
        }
 
1889
        if (SYNCTEX_WIDTH_V(node)<0) {
 
1890
                itsBtm = SYNCTEX_HORIZ_V(node);
 
1891
                itsTop = SYNCTEX_HORIZ_V(node)-SYNCTEX_WIDTH_V(node);
 
1892
                if (h<itsBtm) {
 
1893
                        SYNCTEX_HORIZ_V(node) = h;
 
1894
                        SYNCTEX_WIDTH_V(node) = SYNCTEX_HORIZ_V(node) - itsTop;
 
1895
                } else if (h>itsTop) {
 
1896
                        SYNCTEX_WIDTH_V(node) = SYNCTEX_HORIZ_V(node) - h;
 
1897
                }
 
1898
        } else {
 
1899
                itsBtm = SYNCTEX_HORIZ_V(node);
 
1900
                itsTop = SYNCTEX_HORIZ_V(node)+SYNCTEX_WIDTH_V(node);
 
1901
                if (h<itsBtm) {
 
1902
                        SYNCTEX_HORIZ_V(node) = h;
 
1903
                        SYNCTEX_WIDTH_V(node) = itsTop - SYNCTEX_HORIZ_V(node);
 
1904
                } else if (h>itsTop) {
 
1905
                        SYNCTEX_WIDTH_V(node) = h - SYNCTEX_HORIZ_V(node);
 
1906
                }
 
1907
        }
 
1908
        return SYNCTEX_STATUS_OK;
 
1909
}
4706
1910
 
4707
1911
/*  Here are the control characters that strat each line of the synctex output file.
4708
1912
 *  Their values define the meaning of the line.
4709
1913
 */
4710
1914
#   define SYNCTEX_CHAR_BEGIN_SHEET '{'
4711
1915
#   define SYNCTEX_CHAR_END_SHEET   '}'
4712
 
#   define SYNCTEX_CHAR_BEGIN_FORM  '<'
4713
 
#   define SYNCTEX_CHAR_END_FORM    '>'
4714
1916
#   define SYNCTEX_CHAR_BEGIN_VBOX  '['
4715
1917
#   define SYNCTEX_CHAR_END_VBOX    ']'
4716
1918
#   define SYNCTEX_CHAR_BEGIN_HBOX  '('
4720
1922
#   define SYNCTEX_CHAR_VOID_HBOX   'h'
4721
1923
#   define SYNCTEX_CHAR_KERN        'k'
4722
1924
#   define SYNCTEX_CHAR_GLUE        'g'
4723
 
#   define SYNCTEX_CHAR_RULE        'r'
4724
1925
#   define SYNCTEX_CHAR_MATH        '$'
4725
 
#   define SYNCTEX_CHAR_FORM_REF    'f'
4726
1926
#   define SYNCTEX_CHAR_BOUNDARY    'x'
4727
 
#   define SYNCTEX_CHAR_CHARACTER   'c'
4728
 
#   define SYNCTEX_CHAR_COMMENT     '%'
4729
 
 
4730
 
#       ifdef SYNCTEX_NOTHING
4731
 
#       pragma mark -
4732
 
#       pragma mark SCANNERS & PARSERS
4733
 
#   endif
4734
 
 
4735
 
#   define SYNCTEX_DECODE_FAILED(NODE,WHAT) \
4736
 
(_synctex_data_decode_##WHAT(NODE)<SYNCTEX_STATUS_OK)
4737
 
#   define SYNCTEX_DECODE_FAILED_V(NODE,WHAT) \
4738
 
(_synctex_data_decode_##WHAT##_v(NODE)<SYNCTEX_STATUS_OK)
4739
 
 
4740
 
#define SYNCTEX_NS_NULL (synctex_ns_s){NULL,SYNCTEX_STATUS_NOT_OK}
4741
 
static synctex_ns_s _synctex_parse_new_sheet(synctex_scanner_p scanner) {
4742
 
    synctex_node_p node;
4743
 
    if ((node = _synctex_new_sheet(scanner))) {
4744
 
        if (
4745
 
            SYNCTEX_DECODE_FAILED(node,page)) {
4746
 
            _synctex_error("Bad sheet record.");
4747
 
        } else if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4748
 
            _synctex_error("Missing end of sheet.");
4749
 
        } else {
4750
 
            /* Now set the owner */
4751
 
            if (scanner->sheet) {
4752
 
                synctex_node_p last_sheet = scanner->sheet;
4753
 
                synctex_node_p next_sheet = NULL;
4754
 
                while ((next_sheet = __synctex_tree_sibling(last_sheet))) {
4755
 
                    last_sheet = next_sheet;
4756
 
                }
4757
 
                /* sheets have no parent */
4758
 
                __synctex_tree_set_sibling(last_sheet,node);
4759
 
            } else {
4760
 
                scanner->sheet = node;
4761
 
            }
4762
 
            return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4763
 
        }
4764
 
        _synctex_free_node(node);
4765
 
    }
4766
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4767
 
}
4768
 
/**
4769
 
 *  - requirement: scanner != NULL
4770
 
 */
4771
 
static synctex_ns_s _synctex_parse_new_form(synctex_scanner_p scanner) {
4772
 
    synctex_node_p node;
4773
 
    if ((node = _synctex_new_form(scanner))) {
4774
 
        if (
4775
 
            SYNCTEX_DECODE_FAILED(node,tag)) {
4776
 
            _synctex_error("Bad sheet record.");
4777
 
        } else if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4778
 
            _synctex_error("Missing end of form.");
4779
 
        } else {
4780
 
            /* Now set the owner */
4781
 
            if (scanner->form) {
4782
 
                synctex_node_p last_form = scanner->form;
4783
 
                synctex_node_p next_form = NULL;
4784
 
                while ((next_form = __synctex_tree_sibling(last_form))) {
4785
 
                    last_form = next_form;
4786
 
                }
4787
 
                __synctex_tree_set_sibling(last_form,node);
4788
 
            } else {
4789
 
                scanner->form = node;
4790
 
            }
4791
 
            return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4792
 
        }
4793
 
        _synctex_free_node(node);
4794
 
    }
4795
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4796
 
}
4797
 
#   define SYNCTEX_SHOULD_DECODE_FAILED(NODE,WHAT) \
4798
 
(_synctex_data_has_##WHAT(NODE) &&(_synctex_data_decode_##WHAT(NODE)<SYNCTEX_STATUS_OK))
4799
 
#   define SYNCTEX_SHOULD_DECODE_FAILED_V(NODE,WHAT) \
4800
 
(_synctex_data_has_##WHAT(NODE) &&(_synctex_data_decode_##WHAT##_v(NODE)<SYNCTEX_STATUS_OK))
4801
 
 
4802
 
static synctex_status_t _synctex_data_decode_tlchvwhd(synctex_node_p node) {
4803
 
    return SYNCTEX_SHOULD_DECODE_FAILED(node,tag)
4804
 
    || SYNCTEX_SHOULD_DECODE_FAILED(node,line)
4805
 
    || SYNCTEX_SHOULD_DECODE_FAILED(node,column)
4806
 
    || SYNCTEX_SHOULD_DECODE_FAILED(node,h)
4807
 
    || SYNCTEX_SHOULD_DECODE_FAILED_V(node,v)
4808
 
    || SYNCTEX_SHOULD_DECODE_FAILED(node,width)
4809
 
    || SYNCTEX_SHOULD_DECODE_FAILED(node,height)
4810
 
    || SYNCTEX_SHOULD_DECODE_FAILED(node,depth);
4811
 
}
4812
 
static synctex_ns_s _synctex_parse_new_vbox(synctex_scanner_p scanner) {
4813
 
    synctex_node_p node;
4814
 
    if ((node = _synctex_new_vbox(scanner))) {
4815
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4816
 
            _synctex_error("Bad vbox record.");
4817
 
            _synctex_next_line(scanner);
4818
 
        out:
4819
 
            _synctex_free_node(node);
4820
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4821
 
        }
4822
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4823
 
            _synctex_error("Missing end of vbox.");
4824
 
            goto out;
4825
 
        }
4826
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4827
 
    }
4828
 
    _synctex_next_line(scanner);
4829
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4830
 
}
4831
 
SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend_tlc(synctex_node_p node);
4832
 
static synctex_ns_s _synctex_parse_new_hbox(synctex_scanner_p scanner) {
4833
 
    synctex_node_p node;
4834
 
    if ((node = _synctex_new_hbox(scanner))) {
4835
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4836
 
            _synctex_error("Bad hbox record.");
4837
 
            _synctex_next_line(scanner);
4838
 
        out:
4839
 
            _synctex_free_node(node);
4840
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4841
 
        }
4842
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4843
 
            _synctex_error("Missing end of hbox.");
4844
 
            goto out;
4845
 
        }
4846
 
        if (_synctex_setup_visible_hbox(node)<SYNCTEX_STATUS_OK) {
4847
 
            _synctex_error("Unexpected error (_synctex_parse_new_hbox).");
4848
 
            goto out;
4849
 
        }
4850
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4851
 
    }
4852
 
    _synctex_next_line(scanner);
4853
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4854
 
}
4855
 
static synctex_ns_s _synctex_parse_new_void_vbox(synctex_scanner_p scanner) {
4856
 
    synctex_node_p node;
4857
 
    if ((node = _synctex_new_void_vbox(scanner))) {
4858
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4859
 
            _synctex_error("Bad void vbox record.");
4860
 
            _synctex_next_line(scanner);
4861
 
        out:
4862
 
            _synctex_free_node(node);
4863
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4864
 
        }
4865
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4866
 
            _synctex_error("Missing end of container.");
4867
 
            goto out;
4868
 
        }
4869
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4870
 
    }
4871
 
    _synctex_next_line(scanner);
4872
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4873
 
}
4874
 
static synctex_ns_s _synctex_parse_new_void_hbox(synctex_scanner_p scanner) {
4875
 
    synctex_node_p node;
4876
 
    if ((node = _synctex_new_void_hbox(scanner))) {
4877
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4878
 
            _synctex_error("Bad void hbox record.");
4879
 
            _synctex_next_line(scanner);
4880
 
        out:
4881
 
            _synctex_free_node(node);
4882
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4883
 
        }
4884
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4885
 
            _synctex_error("Missing end of container.");
4886
 
            goto out;
4887
 
        }
4888
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4889
 
    }
4890
 
    _synctex_next_line(scanner);
4891
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4892
 
}
4893
 
static synctex_ns_s _synctex_parse_new_kern(synctex_scanner_p scanner) {
4894
 
    synctex_node_p node;
4895
 
    if ((node = _synctex_new_kern(scanner))) {
4896
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4897
 
            _synctex_error("Bad kern record.");
4898
 
            _synctex_next_line(scanner);
4899
 
        out:
4900
 
            _synctex_free_node(node);
4901
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4902
 
        }
4903
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4904
 
            _synctex_error("Missing end of container.");
4905
 
            goto out;
4906
 
        }
4907
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4908
 
    }
4909
 
    _synctex_next_line(scanner);
4910
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4911
 
}
4912
 
static synctex_ns_s _synctex_parse_new_glue(synctex_scanner_p scanner) {
4913
 
    synctex_node_p node;
4914
 
    if ((node = _synctex_new_glue(scanner))) {
4915
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4916
 
            _synctex_error("Bad glue record.");
4917
 
            _synctex_next_line(scanner);
4918
 
        out:
4919
 
            _synctex_free_node(node);
4920
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4921
 
        }
4922
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4923
 
            _synctex_error("Missing end of container.");
4924
 
            goto out;
4925
 
        }
4926
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4927
 
    }
4928
 
    _synctex_next_line(scanner);
4929
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4930
 
}
4931
 
static synctex_ns_s _synctex_parse_new_rule(synctex_scanner_p scanner) {
4932
 
    synctex_node_p node;
4933
 
    if ((node = _synctex_new_rule(scanner))) {
4934
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4935
 
            _synctex_error("Bad rule record.");
4936
 
            _synctex_next_line(scanner);
4937
 
        out:
4938
 
            _synctex_free_node(node);
4939
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4940
 
        }
4941
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4942
 
            _synctex_error("Missing end of container.");
4943
 
            goto out;
4944
 
        }
4945
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4946
 
    }
4947
 
    _synctex_next_line(scanner);
4948
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4949
 
}
4950
 
static synctex_ns_s _synctex_parse_new_math(synctex_scanner_p scanner) {
4951
 
    synctex_node_p node;
4952
 
    if ((node = _synctex_new_math(scanner))) {
4953
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4954
 
            _synctex_error("Bad math record.");
4955
 
            _synctex_next_line(scanner);
4956
 
        out:
4957
 
            _synctex_free_node(node);
4958
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4959
 
        }
4960
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4961
 
            _synctex_error("Missing end of container.");
4962
 
            goto out;
4963
 
        }
4964
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4965
 
    }
4966
 
    _synctex_next_line(scanner);
4967
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4968
 
}
4969
 
static synctex_ns_s _synctex_parse_new_boundary(synctex_scanner_p scanner) {
4970
 
    synctex_node_p node;
4971
 
    if ((node = _synctex_new_boundary(scanner))) {
4972
 
        if (_synctex_data_decode_tlchvwhd(node)) {
4973
 
            _synctex_error("Bad boundary record.");
4974
 
            _synctex_next_line(scanner);
4975
 
        out:
4976
 
            _synctex_free_node(node);
4977
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4978
 
        }
4979
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4980
 
            _synctex_error("Missing end of container.");
4981
 
            goto out;
4982
 
        }
4983
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4984
 
    }
4985
 
    _synctex_next_line(scanner);
4986
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4987
 
}
4988
 
SYNCTEX_INLINE static synctex_ns_s _synctex_parse_new_ref(synctex_scanner_p scanner) {
4989
 
    synctex_node_p node;
4990
 
    if ((node = _synctex_new_ref(scanner))) {
4991
 
        if (SYNCTEX_DECODE_FAILED(node,tag)
4992
 
            || SYNCTEX_DECODE_FAILED(node,h)
4993
 
            || SYNCTEX_DECODE_FAILED_V(node,v)) {
4994
 
            _synctex_error("Bad form ref record.");
4995
 
            _synctex_next_line(scanner);
4996
 
        out:
4997
 
            _synctex_free_node(node);
4998
 
            return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4999
 
        }
5000
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5001
 
            _synctex_error("Missing end of container.");
5002
 
            goto out;
5003
 
        }
5004
 
        return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
5005
 
    }
5006
 
    _synctex_next_line(scanner);
5007
 
    return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
5008
 
}
5009
 
#   undef SYNCTEX_DECODE_FAILED
5010
 
#   undef SYNCTEX_DECODE_FAILED_V
5011
 
 
5012
 
SYNCTEX_INLINE static synctex_point_s _synctex_data_point(synctex_node_p node);
5013
 
SYNCTEX_INLINE static synctex_point_s _synctex_data_point_V(synctex_node_p node);
5014
 
SYNCTEX_INLINE static synctex_point_s _synctex_data_set_point(synctex_node_p node, synctex_point_s point);
5015
 
SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node);
5016
 
SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node);
5017
 
SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node);
5018
 
 
5019
 
SYNCTEX_INLINE static synctex_node_p _synctex_input_register_line(synctex_node_p input,synctex_node_p node) {
5020
 
    if (node && _synctex_data_tag(input) != _synctex_data_tag(node)) {
5021
 
        input = synctex_scanner_input_with_tag(node->class_->scanner,_synctex_data_tag(node));
5022
 
    }
5023
 
    if (_synctex_data_line(node)>_synctex_data_line(input)) {
5024
 
        _synctex_data_set_line(input,_synctex_data_line(node));
5025
 
    }
5026
 
    return input;
5027
 
}
5028
 
/**
5029
 
 *  Free node and its siblings and return its detached child.
5030
 
 */
5031
 
SYNCTEX_INLINE static synctex_node_p _synctex_handle_pop_child(synctex_node_p handle) {
5032
 
    synctex_node_p child = _synctex_tree_reset_child(handle);
5033
 
    synctex_node_free(handle);
5034
 
    return child;
5035
 
}
5036
 
/**
5037
 
 *  Set the tlc of all the x nodes that are targets of
5038
 
 *  x_handle and its sibling.
5039
 
 *  Reset the target of x_handle and deletes its siblings.
5040
 
 *  child is a node that has just been parsed and is not a boundary node.
5041
 
 */
5042
 
SYNCTEX_INLINE static void _synctex_handle_set_tlc(synctex_node_p x_handle, synctex_node_p child, synctex_bool_t make_friend) {
5043
 
    if (x_handle) {
5044
 
        synctex_node_p sibling = x_handle;
5045
 
        if (child) {
5046
 
            synctex_node_p target;
5047
 
            while ((target = synctex_node_target(sibling))) {
5048
 
                _synctex_data_set_tlc(target,child);
5049
 
                if (make_friend) {
5050
 
                    _synctex_node_make_friend_tlc(target);
5051
 
                }
5052
 
                if ((sibling = __synctex_tree_sibling(sibling))) {
5053
 
                    continue;
5054
 
                } else {
5055
 
                    break;
5056
 
                }
5057
 
            }
5058
 
        }
5059
 
        _synctex_tree_reset_target(x_handle);
5060
 
        sibling = __synctex_tree_reset_sibling(x_handle);
5061
 
        synctex_node_free(sibling);
5062
 
    }
5063
 
}
5064
 
/**
5065
 
 *  When we have parsed a box, we must register
5066
 
 *  all the contained heading boundary nodes
5067
 
 *  that have not yet been registered.
5068
 
 *  Those handles will be deleted when poping.
5069
 
 */
5070
 
SYNCTEX_INLINE static void _synctex_handle_make_friend_tlc(synctex_node_p node) {
5071
 
    while (node) {
5072
 
        synctex_node_p target = _synctex_tree_reset_target(node);
5073
 
        _synctex_node_make_friend_tlc(target);
5074
 
        node = __synctex_tree_sibling(node);
5075
 
    }
5076
 
}
5077
 
/**
5078
 
 *  Scan sheets, forms and input records.
5079
 
 *  - parameter scanner: owning scanner
5080
 
 *  - returns: status
5081
 
 */
5082
 
static synctex_status_t __synctex_parse_sfi(synctex_scanner_p scanner) {
5083
 
    synctex_status_t status = SYNCTEX_STATUS_OK;
5084
 
    synctex_zs_s zs = {0,0};
5085
 
    synctex_ns_s input = SYNCTEX_NS_NULL;
5086
 
    synctex_node_p sheet = NULL;
5087
 
    synctex_node_p form = NULL;
5088
 
    synctex_node_p parent = NULL;
5089
 
    synctex_node_p child = NULL;
5090
 
    /*
5091
 
     *  Experimentations lead to the forthcoming conclusion:
5092
 
     *  Sometimes, the first nodes of a box have the wrong line number.
5093
 
     *  These are only boundary (x) nodes.
5094
 
     *  We observed that boundary nodes do have the proper line number
5095
 
     *  if they follow a node with a different type.
5096
 
     *  We keep track of these leading x nodes in a handle tree.
5097
 
     */
5098
 
    synctex_node_p x_handle = NULL;
5099
 
#   define SYNCTEX_RETURN(STATUS) \
5100
 
        synctex_node_free(x_handle);\
5101
 
        return STATUS
5102
 
    synctex_node_p last_k = NULL;
5103
 
    synctex_node_p last_g = NULL;
5104
 
    synctex_ns_s ns = SYNCTEX_NS_NULL;
5105
 
    int form_depth = 0;
5106
 
    int ignored_form_depth = 0;
5107
 
    synctex_bool_t try_input = synctex_YES;
5108
 
    if (!(x_handle = _synctex_new_handle(scanner))) {
5109
 
        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5110
 
    }
5111
 
#       ifdef SYNCTEX_NOTHING
5112
 
#       pragma mark MAIN LOOP
5113
 
#   endif
5114
 
main_loop:
5115
 
    status = SYNCTEX_STATUS_OK;
5116
 
    sheet = form = parent = child = NULL;
5117
 
#   define SYNCTEX_START_SCAN(WHAT)\
5118
 
(*SYNCTEX_CUR == SYNCTEX_CHAR_##WHAT)
5119
 
    if (SYNCTEX_CUR<SYNCTEX_END) {
5120
 
        if (SYNCTEX_START_SCAN(BEGIN_FORM)) {
5121
 
#       ifdef SYNCTEX_NOTHING
5122
 
#       pragma mark + SCAN FORM
5123
 
#   endif
5124
 
        scan_form:
5125
 
            ns = _synctex_parse_new_form(scanner);
5126
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5127
 
                ++form_depth;
5128
 
                if (_synctex_tree_parent(form)) {
5129
 
                    /* This form is already being parsed */
5130
 
                    ++ignored_form_depth;
5131
 
                    goto ignore_loop;
5132
 
                }
5133
 
                _synctex_tree_set_parent(ns.node,form);
5134
 
                form = ns.node;
5135
 
                parent = form;
5136
 
                child = NULL;
5137
 
                last_k = last_g = NULL;
5138
 
                goto content_loop;
5139
 
            }
5140
 
            if (form || sheet) {
5141
 
                last_k = last_g = NULL;
5142
 
                goto content_loop;
5143
 
            }
5144
 
            try_input = synctex_YES;
5145
 
            goto main_loop;
5146
 
        } else if (SYNCTEX_START_SCAN(BEGIN_SHEET)) {
5147
 
#       ifdef SYNCTEX_NOTHING
5148
 
#       pragma mark + SCAN SHEET
5149
 
#   endif
5150
 
            try_input = synctex_YES;
5151
 
            ns = _synctex_parse_new_sheet(scanner);
5152
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5153
 
                sheet = ns.node;
5154
 
                parent = sheet;
5155
 
                last_k = last_g = NULL;
5156
 
                goto content_loop;
5157
 
            }
5158
 
            goto main_loop;
5159
 
        } else if (SYNCTEX_START_SCAN(ANCHOR)) {
5160
 
#       ifdef SYNCTEX_NOTHING
5161
 
#       pragma mark + SCAN ANCHOR
5162
 
#   endif
5163
 
        scan_anchor:
5164
 
            ++SYNCTEX_CUR;
5165
 
            if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5166
 
                _synctex_error("Missing anchor.");
5167
 
                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5168
 
            }
5169
 
            if (form || sheet) {
5170
 
                last_k = last_g = NULL;
5171
 
                goto content_loop;
5172
 
            }
5173
 
            try_input = synctex_YES;
5174
 
            goto main_loop;
5175
 
        } else if (SYNCTEX_START_SCAN(ANCHOR)) {
5176
 
#       ifdef SYNCTEX_NOTHING
5177
 
#       pragma mark + SCAN COMMENT
5178
 
#   endif
5179
 
            ++SYNCTEX_CUR;
5180
 
            _synctex_next_line(scanner);
5181
 
            try_input = synctex_YES;
5182
 
            goto main_loop;
5183
 
        } else if (try_input) {
5184
 
#       ifdef SYNCTEX_NOTHING
5185
 
#       pragma mark + SCAN INPUT
5186
 
#   endif
5187
 
            try_input = synctex_NO;
5188
 
            do {
5189
 
                input = __synctex_parse_new_input(scanner);
5190
 
            } while (input.status == SYNCTEX_STATUS_OK);
5191
 
            goto main_loop;
5192
 
        }
5193
 
        status = _synctex_match_string(scanner,"Postamble:");
5194
 
        if (status==SYNCTEX_STATUS_OK) {
5195
 
            scanner->flags.postamble = 1;
5196
 
            SYNCTEX_RETURN(status);
5197
 
        }
5198
 
        status = _synctex_next_line(scanner);
5199
 
        if (status<SYNCTEX_STATUS_OK) {
5200
 
            SYNCTEX_RETURN(status);
5201
 
        }
5202
 
   }
5203
 
    /* At least 1 more character */
5204
 
    zs = _synctex_buffer_get_available_size(scanner,1);
5205
 
    if (zs.size == 0){
5206
 
        _synctex_error("Incomplete synctex file, postamble missing.");
5207
 
        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5208
 
    }
5209
 
    goto main_loop;
5210
 
    /*  Unreachable. */
5211
 
#       ifdef SYNCTEX_NOTHING
5212
 
#       pragma mark IGNORE LOOP
5213
 
#   endif
5214
 
ignore_loop:
5215
 
    ns = SYNCTEX_NS_NULL;
5216
 
    if (SYNCTEX_CUR<SYNCTEX_END) {
5217
 
        if (SYNCTEX_START_SCAN(BEGIN_FORM)) {
5218
 
            ++ignored_form_depth;
5219
 
        } else if (SYNCTEX_START_SCAN(END_FORM)) {
5220
 
            --ignored_form_depth;
5221
 
        }
5222
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5223
 
            _synctex_error("Incomplete container.");
5224
 
            SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5225
 
        }
5226
 
    } else {
5227
 
        zs = _synctex_buffer_get_available_size(scanner,1);
5228
 
        if (zs.size == 0){
5229
 
            _synctex_error("Incomplete synctex file, postamble missing.");
5230
 
            SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5231
 
        }
5232
 
    }
5233
 
    if (ignored_form_depth) {
5234
 
        goto ignore_loop;
5235
 
    } else {
5236
 
        last_k = last_g = NULL;
5237
 
        goto content_loop;
5238
 
    }
5239
 
 
5240
 
#       ifdef SYNCTEX_NOTHING
5241
 
#       pragma mark CONTENT LOOP
5242
 
#   endif
5243
 
content_loop:
5244
 
    /*  Either in a form, a sheet or a box.
5245
 
     *  - in a sheet, "{" is not possible, only boxes and "}" at top level.
5246
 
     *  - in a form, "{" is not possible, only boxes, "<" and ">" at top level.
5247
 
     *  - in a box, the unique possibility is '<', '[', '(' or ">".
5248
 
     *  We still keep the '(' for a sheet, because that dos not cost too much.
5249
 
     *  We must also consider void boxes as children.
5250
 
     */
5251
 
    /* forms are everywhere */
5252
 
    ns = SYNCTEX_NS_NULL;
5253
 
#if SYNCTEX_VERBOSE
5254
 
    synctex_scanner_set_display_switcher(scanner,-1);
5255
 
    printf("NEW CONTENT LOOP\n");
5256
 
#if SYNCTEX_DEBUG>500
5257
 
    synctex_node_display(sheet);
5258
 
#endif
5259
 
#endif
5260
 
    if (SYNCTEX_CUR<SYNCTEX_END) {
5261
 
        if (SYNCTEX_START_SCAN(BEGIN_FORM)) {
5262
 
            goto scan_form;
5263
 
        } else if (SYNCTEX_START_SCAN(BEGIN_VBOX)) {
5264
 
#       ifdef SYNCTEX_NOTHING
5265
 
#       pragma mark + SCAN VBOX
5266
 
#   endif
5267
 
            ns = _synctex_parse_new_vbox(scanner);
5268
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5269
 
                x_handle = _synctex_new_handle_with_child(x_handle);
5270
 
                if (child) {
5271
 
                    _synctex_node_set_sibling(child,ns.node);
5272
 
                } else {
5273
 
                    _synctex_node_set_child(parent,ns.node);
5274
 
                }
5275
 
                parent = ns.node;
5276
 
                child = _synctex_tree_last(parent);
5277
 
#   if SYNCTEX_VERBOSE
 
1927
 
 
1928
#   define SYNCTEX_RETURN(STATUS) return STATUS;
 
1929
 
 
1930
/*  Used when parsing the synctex file. A '{' character has just been parsed.
 
1931
 *  The purpose is to gobble everything until the closing '}'.
 
1932
 *  Actually only one nesting depth has been observed when using the clip option
 
1933
 *  of \includegraphics option. Here we use arbitrary level of depth.
 
1934
 */
 
1935
synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner) {
 
1936
    unsigned int depth = 0;
 
1937
deeper:
 
1938
    ++depth;
 
1939
    if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
1940
        _synctex_error("Unexpected end of nested sheet (1).");
 
1941
        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
1942
    }
 
1943
scan_next_line:
 
1944
    if (SYNCTEX_CUR<SYNCTEX_END) {
 
1945
                if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
 
1946
                        ++SYNCTEX_CUR;
 
1947
                        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
1948
                                _synctex_error("Unexpected end of nested sheet (2).");
 
1949
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
1950
                        }
 
1951
            if (--depth>0) {
 
1952
                goto scan_next_line;
 
1953
            } else {
 
1954
                SYNCTEX_RETURN(SYNCTEX_STATUS_OK);
 
1955
            }
 
1956
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) {
 
1957
                        ++SYNCTEX_CUR;
 
1958
                        goto deeper;
 
1959
            
 
1960
                } else if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
1961
            _synctex_error("Unexpected end of nested sheet (3).");
 
1962
            SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
1963
        }
 
1964
    }
 
1965
    _synctex_error("Unexpected end of nested sheet (4).");
 
1966
    SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
1967
}
 
1968
 
 
1969
/*  Used when parsing the synctex file.
 
1970
 *  The sheet argument is a newly created sheet node that will hold the contents.
 
1971
 *  Something is returned in case of error.
 
1972
 */
 
1973
synctex_status_t _synctex_scan_sheet(synctex_scanner_t scanner, synctex_node_t sheet) {
 
1974
        synctex_node_t parent = sheet;
 
1975
        synctex_node_t child = NULL;
 
1976
        synctex_node_t sibling = NULL;
 
1977
        synctex_node_t box = sheet;
 
1978
        int friend_index = 0;
 
1979
        synctex_info_t * info = NULL;
 
1980
        synctex_status_t status = 0;
 
1981
        size_t available = 0;
 
1982
        if ((NULL == scanner) || (NULL == sheet)) {
 
1983
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
1984
        }
 
1985
        /*  We MUST start with a box, so at this level, the unique possibility is '[', '(' or "}". */
 
1986
prepare_loop:
 
1987
        if (SYNCTEX_CUR<SYNCTEX_END) {
 
1988
                if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_VBOX) {
 
1989
scan_vbox:
 
1990
                        if ((child = _synctex_new_vbox(scanner)) && (info = SYNCTEX_INFO(child))) {
 
1991
#               define SYNCTEX_DECODE_FAILED(WHAT) \
 
1992
                                        (_synctex_decode_int(scanner,&(info[WHAT].INT))<SYNCTEX_STATUS_OK)
 
1993
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
1994
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
1995
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
1996
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
1997
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
1998
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
 
1999
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
 
2000
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2001
                                        _synctex_error("Bad vbox record.");
 
2002
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2003
                                }
 
2004
                                SYNCTEX_SET_CHILD(parent,child);
 
2005
                                parent = child;
 
2006
                                child = NULL;
 
2007
                                goto child_loop;/*  next created node will be a child */
 
2008
                        } else {
 
2009
                                _synctex_error("Can't create vbox record.");
 
2010
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2011
                        }
 
2012
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_HBOX) {
 
2013
scan_hbox:
 
2014
                        if ((child = _synctex_new_hbox(scanner)) && (info = SYNCTEX_INFO(child))) {
 
2015
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2016
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2017
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2018
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2019
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2020
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
 
2021
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
 
2022
                                                || _synctex_setup_visible_box(child)<SYNCTEX_STATUS_OK
 
2023
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2024
                                        _synctex_error("Bad hbox record.");
 
2025
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2026
                                }
 
2027
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2028
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
 
2029
                                SYNCTEX_SET_CHILD(parent,child);
 
2030
                                parent = child;
 
2031
                                child = NULL;
 
2032
                                goto child_loop;/*  next created node will be a child */
 
2033
                        } else {
 
2034
                                _synctex_error("Can't create hbox record.");
 
2035
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2036
                        }
 
2037
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
 
2038
scan_teehs:
 
2039
                        ++SYNCTEX_CUR;
 
2040
                        if (NULL == parent || parent->class->type != synctex_node_type_sheet
 
2041
                                        || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2042
                                _synctex_error("Unexpected end of sheet.");
 
2043
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2044
                        }
 
2045
#           if SYNCTEX_VERBOSE
5278
2046
                synctex_node_log(parent);
5279
 
#   endif
5280
 
                input.node = _synctex_input_register_line(input.node,parent);
5281
 
                last_k = last_g = NULL;
5282
 
                goto content_loop;
5283
 
            }
5284
 
        } else if (SYNCTEX_START_SCAN(END_VBOX)) {
5285
 
            if (synctex_node_type(parent) == synctex_node_type_vbox) {
5286
 
#       ifdef SYNCTEX_NOTHING
5287
 
#       pragma mark + SCAN XOBV
5288
 
#   endif
5289
 
                ++SYNCTEX_CUR;
5290
 
                if (NULL == _synctex_tree_child(parent) && !form) {
5291
 
                    /*  only void v boxes are friends */
5292
 
                    _synctex_node_make_friend_tlc(parent);
5293
 
                }
5294
 
                child = parent;
5295
 
                parent = _synctex_tree_parent(child);
5296
 
                if (!form) {
5297
 
                    _synctex_handle_make_friend_tlc(x_handle);
5298
 
                }
5299
 
                x_handle = _synctex_handle_pop_child(x_handle);
5300
 
                _synctex_handle_set_tlc(x_handle,child,!form);
5301
 
#   if SYNCTEX_VERBOSE
 
2047
#           endif
 
2048
                        SYNCTEX_RETURN(SYNCTEX_STATUS_OK);
 
2049
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) {
 
2050
                        /*  Addendum to version 1.10 to manage nested sheets  */
 
2051
                        ++SYNCTEX_CUR;
 
2052
                        if (_synctex_scan_nested_sheet(scanner)<SYNCTEX_STATUS_OK) {
 
2053
                                _synctex_error("Unexpected nested sheet.");
 
2054
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2055
                        }
 
2056
                        goto prepare_loop;
 
2057
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
 
2058
scan_anchor:
 
2059
                        ++SYNCTEX_CUR;
 
2060
                        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2061
                                _synctex_error("Missing anchor.");
 
2062
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2063
                        }
 
2064
                        goto prepare_loop;
 
2065
                } else {
 
2066
                        /*  _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
 
2067
                        ++SYNCTEX_CUR;
 
2068
                        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2069
                                _synctex_error("Unexpected end.");
 
2070
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2071
                        }
 
2072
                        goto prepare_loop;
 
2073
                }
 
2074
        } else {
 
2075
                available = 1;
 
2076
                status = _synctex_buffer_get_available_size(scanner,&available);
 
2077
                 if (status<SYNCTEX_STATUS_OK && available>0){
 
2078
                        _synctex_error("Uncomplete sheet(0)");
 
2079
                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2080
                }
 
2081
        goto prepare_loop;
 
2082
        }
 
2083
/*  The child loop means that we go down one level, when we just created a box node,
 
2084
 *  the next node created is a child of this box. */
 
2085
child_loop:
 
2086
        if (SYNCTEX_CUR<SYNCTEX_END) {
 
2087
                if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_VBOX) {
 
2088
                        goto scan_vbox;
 
2089
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_VBOX) {
 
2090
scan_xobv:
 
2091
                        ++SYNCTEX_CUR;
 
2092
                        if (NULL != parent && parent->class->type == synctex_node_type_vbox) {
 
2093
                                #define SYNCTEX_UPDATE_BOX_FRIEND(NODE)\
 
2094
                                friend_index = ((SYNCTEX_INFO(NODE))[SYNCTEX_TAG_IDX].INT+(SYNCTEX_INFO(NODE))[SYNCTEX_LINE_IDX].INT)%(scanner->number_of_lists);\
 
2095
                                SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\
 
2096
                                (scanner->lists_of_friends)[friend_index] = NODE;
 
2097
                                if (NULL == SYNCTEX_CHILD(parent)) {
 
2098
                                        /*  only void boxes are friends */
 
2099
                                        SYNCTEX_UPDATE_BOX_FRIEND(parent);
 
2100
                                }
 
2101
                                child = parent;
 
2102
                                parent = SYNCTEX_PARENT(child);
 
2103
                        } else {
 
2104
                                _synctex_error("Unexpected end of vbox, ignored.");
 
2105
                        }
 
2106
                        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2107
                                _synctex_error("Uncomplete sheet.");
 
2108
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2109
                        }
 
2110
#           if SYNCTEX_VERBOSE
5302
2111
                synctex_node_log(child);
5303
 
#   endif
5304
 
                if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5305
 
                    _synctex_error("Incomplete container.");
5306
 
                    SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5307
 
                }
5308
 
                last_k = last_g = NULL;
5309
 
                goto content_loop;
5310
 
            }
5311
 
        } else if (SYNCTEX_START_SCAN(BEGIN_HBOX)) {
5312
 
#       ifdef SYNCTEX_NOTHING
5313
 
#       pragma mark + SCAN HBOX
5314
 
#   endif
5315
 
#   if defined(SYNCTEX_USE_CHARINDEX)
5316
 
            synctex_charindex_t char_index = (synctex_charindex_t)(scanner->reader->charindex_offset+SYNCTEX_CUR-SYNCTEX_START);
5317
 
            synctex_lineindex_t line_index = scanner->reader->line_number;
5318
 
#   endif
5319
 
            ns = _synctex_parse_new_hbox(scanner);
5320
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5321
 
                x_handle = _synctex_new_handle_with_child(x_handle);
5322
 
                if (child) {
5323
 
                    _synctex_node_set_sibling(child,ns.node);
5324
 
                } else {
5325
 
                    _synctex_node_set_child(parent,ns.node);
5326
 
                }
5327
 
                parent = ns.node;
5328
 
                /*  add a box boundary node at the start */
5329
 
                if ((child = _synctex_new_box_bdry(scanner))) {
5330
 
#   if defined(SYNCTEX_USE_CHARINDEX)
5331
 
                    child->line_index=line_index;
5332
 
                    child->char_index=char_index;
5333
 
#   endif
5334
 
                    _synctex_node_set_child(parent,child);
5335
 
                    _synctex_data_set_tlchv(child,parent);
5336
 
                    if (!form) {
5337
 
                        __synctex_node_make_friend_tlc(child);
5338
 
                    }
5339
 
                } else {
5340
 
                    _synctex_error("Can't create box bdry record.");
5341
 
                }
5342
 
#   if SYNCTEX_VERBOSE
5343
 
                synctex_node_log(parent);
5344
 
#   endif
5345
 
                input.node = _synctex_input_register_line(input.node,parent);
5346
 
                last_k = last_g = NULL;
5347
 
                goto content_loop;
5348
 
            }
5349
 
        } else if (SYNCTEX_START_SCAN(END_HBOX)) {
5350
 
            if (synctex_node_type(parent) == synctex_node_type_hbox) {
5351
 
#       ifdef SYNCTEX_NOTHING
5352
 
#       pragma mark + SCAN XOBH
5353
 
#   endif
5354
 
                ++SYNCTEX_CUR;
5355
 
                /*  setting the next horizontal box at the end ensures
5356
 
                 * that a child is recorded before any of its ancestors.
5357
 
                 */
5358
 
                if (form == NULL /* && sheet != NULL*/ ) {
5359
 
                    _synctex_tree_set_next_hbox(parent,_synctex_tree_next_hbox(sheet));
5360
 
                    _synctex_tree_set_next_hbox(sheet,parent);
5361
 
                }
5362
 
                {
5363
 
                    /*  Update the mean line number */
5364
 
                    synctex_node_p node = _synctex_tree_child(parent);
5365
 
                    synctex_node_p sibling = NULL;
5366
 
                    /*  Ignore the first node (a box_bdry) */
5367
 
                    if (node && (sibling = __synctex_tree_sibling(node))) {
5368
 
                        unsigned int node_weight = 0;
5369
 
                        unsigned int cumulated_line_numbers = 0;
5370
 
                        _synctex_data_set_line(node, _synctex_data_line(sibling));
5371
 
                        node = sibling;
5372
 
                        do {
5373
 
                            if (synctex_node_type(node)==synctex_node_type_hbox) {
5374
 
                                if (_synctex_data_weight(node)) {
5375
 
                                    node_weight += _synctex_data_weight(node);
5376
 
                                    cumulated_line_numbers += _synctex_data_mean_line(node)*_synctex_data_weight(node);
5377
 
                                } else {
5378
 
                                    ++node_weight;
5379
 
                                    cumulated_line_numbers += _synctex_data_mean_line(node);
5380
 
                                }
 
2112
#           endif
 
2113
                        goto sibling_loop;
 
2114
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_HBOX) {
 
2115
                        goto scan_hbox;
 
2116
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_HBOX) {
 
2117
scan_xobh:
 
2118
                        ++SYNCTEX_CUR;
 
2119
                        if ((parent) && parent->class->type == synctex_node_type_hbox) {
 
2120
            /*  Update the mean line number */
 
2121
                synctex_node_t node = SYNCTEX_CHILD(parent);
 
2122
                if (node) {
 
2123
                    unsigned int node_weight = 0;
 
2124
                    unsigned int cumulated_line_numbers = 0;
 
2125
                    do {
 
2126
                        if (synctex_node_type(node)==synctex_node_type_hbox) {
 
2127
                            if (SYNCTEX_NODE_WEIGHT(node)) {
 
2128
                                node_weight += SYNCTEX_NODE_WEIGHT(node);
 
2129
                                cumulated_line_numbers += SYNCTEX_MEAN_LINE(node)*SYNCTEX_NODE_WEIGHT(node);
5381
2130
                            } else {
5382
2131
                                ++node_weight;
5383
 
                                cumulated_line_numbers += synctex_node_line(node);
5384
 
                            }
5385
 
                        } while ((node = __synctex_tree_sibling(node)));
5386
 
                        _synctex_data_set_mean_line(parent,(cumulated_line_numbers + node_weight/2)/node_weight);
5387
 
                        _synctex_data_set_weight(parent,node_weight);
5388
 
                    } else {
5389
 
                        _synctex_data_set_mean_line(parent,_synctex_data_line(parent));
5390
 
                        _synctex_data_set_weight(parent,1);
5391
 
                    }
5392
 
                    if ((sibling = _synctex_new_box_bdry(scanner))) {
5393
 
#   if defined(SYNCTEX_USE_CHARINDEX)
5394
 
                        sibling->line_index=child->line_index;
5395
 
                        sibling->char_index=child->char_index;
5396
 
#   endif
5397
 
                        _synctex_node_set_sibling(child,sibling);
5398
 
                        {
5399
 
                            synctex_node_p N = child;
5400
 
                            while (synctex_node_type(N) == synctex_node_type_ref) {
5401
 
                                N = _synctex_tree_arg_sibling(N);
5402
 
                            }
5403
 
                            _synctex_data_set_tlc(sibling,N);
5404
 
                        }
5405
 
                        _synctex_data_set_h(sibling,_synctex_data_h_V(parent)+_synctex_data_width_V(parent));
5406
 
                        _synctex_data_set_v(sibling,_synctex_data_v_V(parent));
5407
 
                        child = sibling;
5408
 
                    } else {
5409
 
                        _synctex_error("Can't create box bdry record.");
5410
 
                    }
5411
 
                    sibling = _synctex_tree_child(parent);
5412
 
                    _synctex_data_set_point(sibling,_synctex_data_point_V(parent));
5413
 
                    if (last_k && last_g && (child = synctex_node_child(parent))) {
5414
 
                        /* Find the node preceding last_k */
5415
 
                        synctex_node_p next;
5416
 
                        while ((next = __synctex_tree_sibling(child))) {
5417
 
                            if (next == last_k) {
5418
 
                                _synctex_data_set_tlc(last_k,child);
5419
 
                                _synctex_data_set_tlc(last_g,child);
5420
 
                                break;
5421
 
                            }
5422
 
                            child = next;
5423
 
                        }
5424
 
                    }
5425
 
                    child = parent;
5426
 
                    parent = _synctex_tree_parent(child);
5427
 
                    if (!form) {
5428
 
                        _synctex_handle_make_friend_tlc(x_handle);
5429
 
                    }
5430
 
                    x_handle = _synctex_handle_pop_child(x_handle);
5431
 
                    _synctex_handle_set_tlc(x_handle,child,!form);
5432
 
                    _synctex_make_hbox_contain_box(parent,                                    _synctex_data_box_V(child));
5433
 
#   if SYNCTEX_VERBOSE
5434
 
                    synctex_node_log(child);
5435
 
#   endif
5436
 
                }
5437
 
                if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5438
 
                    _synctex_error("Incomplete container.");
5439
 
                    SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5440
 
                }
5441
 
                last_k = last_g = NULL;
5442
 
                goto content_loop;
5443
 
            }
5444
 
        } else if (SYNCTEX_START_SCAN(VOID_VBOX)) {
5445
 
#       ifdef SYNCTEX_NOTHING
5446
 
#       pragma mark + SCAN VOID VBOX
5447
 
#   endif
5448
 
            ns = _synctex_parse_new_void_vbox(scanner);
5449
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5450
 
                if (child) {
5451
 
                    _synctex_node_set_sibling(child,ns.node);
5452
 
                } else {
5453
 
                    _synctex_node_set_child(parent,ns.node);
5454
 
                }
5455
 
                child = ns.node;
5456
 
                _synctex_handle_set_tlc(x_handle, child,!form);
5457
 
#   if SYNCTEX_VERBOSE
5458
 
                synctex_node_log(child);
5459
 
#   endif
5460
 
                input.node = _synctex_input_register_line(input.node,child);
5461
 
                last_k = last_g = NULL;
5462
 
                goto content_loop;
5463
 
            }
5464
 
        } else if (SYNCTEX_START_SCAN(VOID_HBOX)) {
5465
 
#       ifdef SYNCTEX_NOTHING
5466
 
#       pragma mark + SCAN VOID HBOX
5467
 
#   endif
5468
 
            ns = _synctex_parse_new_void_hbox(scanner);
5469
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5470
 
                if (_synctex_data_width(ns.node)<0) {
5471
 
                    printf("Negative width\n");
5472
 
                }
5473
 
                if (child) {
5474
 
                    _synctex_node_set_sibling(child,ns.node);
5475
 
                } else {
5476
 
                    _synctex_node_set_child(parent,ns.node);
5477
 
                }
5478
 
                child = ns.node;
5479
 
                _synctex_handle_set_tlc(x_handle, child,!form);
5480
 
                _synctex_make_hbox_contain_box(parent,_synctex_data_box(child));
5481
 
#   if SYNCTEX_VERBOSE
5482
 
                synctex_node_log(child);
5483
 
#   endif
5484
 
                input.node = _synctex_input_register_line(input.node,child);
5485
 
                last_k = last_g = NULL;
5486
 
                goto content_loop;
5487
 
            }
5488
 
        } else if (SYNCTEX_START_SCAN(KERN)) {
5489
 
#       ifdef SYNCTEX_NOTHING
5490
 
#       pragma mark + SCAN KERN
5491
 
#   endif
5492
 
            ns = _synctex_parse_new_kern(scanner);
5493
 
        continue_scan:
5494
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5495
 
                if (child) {
5496
 
                    _synctex_node_set_sibling(child,ns.node);
5497
 
                } else {
5498
 
                    _synctex_node_set_child(parent,ns.node);
5499
 
                }
5500
 
                child = ns.node;
5501
 
                if (!form) {
5502
 
                    __synctex_node_make_friend_tlc(child);
5503
 
                }
5504
 
                _synctex_handle_set_tlc(x_handle, child,!form);
5505
 
                _synctex_make_hbox_contain_box(parent,_synctex_data_xob(child));
5506
 
#   if SYNCTEX_VERBOSE
5507
 
                synctex_node_log(child);
5508
 
#   endif
5509
 
                input.node = _synctex_input_register_line(input.node,child);
5510
 
                last_k = child;
5511
 
                last_g = NULL;
5512
 
                goto content_loop;
5513
 
            }
5514
 
        } else if (SYNCTEX_START_SCAN(GLUE)) {
5515
 
#       ifdef SYNCTEX_NOTHING
5516
 
#       pragma mark + SCAN GLUE
5517
 
#   endif
5518
 
            ns = _synctex_parse_new_glue(scanner);
5519
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5520
 
                if (child) {
5521
 
                    _synctex_node_set_sibling(child,ns.node);
5522
 
                } else {
5523
 
                    _synctex_node_set_child(parent,ns.node);
5524
 
                }
5525
 
                child = ns.node;
5526
 
                if (!form) {
5527
 
                    __synctex_node_make_friend_tlc(child);
5528
 
                }
5529
 
                _synctex_handle_set_tlc(x_handle, child,!form);
5530
 
                _synctex_make_hbox_contain_point(parent,_synctex_data_point(child));
5531
 
#   if SYNCTEX_VERBOSE
5532
 
                synctex_node_log(child);
5533
 
#   endif
5534
 
                input.node = _synctex_input_register_line(input.node,child);
5535
 
                if (last_k) {
5536
 
                    last_g = child;
5537
 
                } else {
5538
 
                    last_k = last_g = NULL;
5539
 
                }
5540
 
                goto content_loop;
5541
 
            }
5542
 
        } else if (SYNCTEX_START_SCAN(RULE)) {
5543
 
#       ifdef SYNCTEX_NOTHING
5544
 
#       pragma mark + SCAN RULE
5545
 
#   endif
5546
 
            ns = _synctex_parse_new_rule(scanner);
5547
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5548
 
                if (child) {
5549
 
                    _synctex_node_set_sibling(child,ns.node);
5550
 
                } else {
5551
 
                    _synctex_node_set_child(parent,ns.node);
5552
 
                }
5553
 
                child = ns.node;
5554
 
                if (!form) {
5555
 
                    __synctex_node_make_friend_tlc(child);
5556
 
                }
5557
 
                _synctex_handle_set_tlc(x_handle, child,!form);
5558
 
                /* Rules are sometimes far too big
5559
 
_synctex_make_hbox_contain_box(parent,_synctex_data_box(child));
5560
 
                 */
5561
 
#   if SYNCTEX_VERBOSE
5562
 
                synctex_node_log(child);
5563
 
#   endif
5564
 
                input.node = _synctex_input_register_line(input.node,child);
5565
 
                last_k = last_g = NULL;
5566
 
                goto content_loop;
5567
 
            }
5568
 
        } else if (SYNCTEX_START_SCAN(MATH)) {
5569
 
#       ifdef SYNCTEX_NOTHING
5570
 
#       pragma mark + SCAN MATH
5571
 
#   endif
5572
 
            ns = _synctex_parse_new_math(scanner);
5573
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5574
 
                if (child) {
5575
 
                    _synctex_node_set_sibling(child,ns.node);
5576
 
                } else {
5577
 
                    _synctex_node_set_child(parent,ns.node);
5578
 
                }
5579
 
                child = ns.node;
5580
 
                if (!form) {
5581
 
                    __synctex_node_make_friend_tlc(child);
5582
 
                }
5583
 
                _synctex_handle_set_tlc(x_handle, child,!form);
5584
 
                _synctex_make_hbox_contain_point(parent,_synctex_data_point(child));
5585
 
#   if SYNCTEX_VERBOSE
5586
 
                synctex_node_log(child);
5587
 
#   endif
5588
 
                input.node = _synctex_input_register_line(input.node,child);
5589
 
                last_k = last_g = NULL;
5590
 
                goto content_loop;
5591
 
            }
5592
 
        } else if (SYNCTEX_START_SCAN(FORM_REF)) {
5593
 
#       ifdef SYNCTEX_NOTHING
5594
 
#       pragma mark + SCAN FORM REF
5595
 
#   endif
5596
 
#if SYNCTEX_DEBUG>500
5597
 
            synctex_node_display(parent);
5598
 
            synctex_node_display(child);
5599
 
#endif
5600
 
            ns = _synctex_parse_new_ref(scanner);
5601
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5602
 
                if (child) {
5603
 
                    _synctex_node_set_sibling(child,ns.node);
5604
 
                } else {
5605
 
                    _synctex_node_set_child(parent,ns.node);
5606
 
                }
5607
 
                child = ns.node;
5608
 
                if (form) {
5609
 
                    if (scanner->ref_in_form) {
5610
 
                        synctex_tree_set_friend(child,scanner->ref_in_form);
5611
 
                    }
5612
 
                    scanner->ref_in_form = child;
5613
 
                } else {
5614
 
                    if (scanner->ref_in_sheet) {
5615
 
                        synctex_tree_set_friend(child,scanner->ref_in_sheet);
5616
 
                    }
5617
 
                    scanner->ref_in_sheet = child;
5618
 
                }
5619
 
#   if SYNCTEX_VERBOSE
5620
 
                synctex_node_log(child);
5621
 
#   endif
5622
 
                last_k = last_g = NULL;
5623
 
                goto content_loop;
5624
 
            }
5625
 
        } else if (SYNCTEX_START_SCAN(BOUNDARY)) {
5626
 
#       ifdef SYNCTEX_NOTHING
5627
 
#       pragma mark + SCAN BOUNDARY
5628
 
#   endif
5629
 
            ns = _synctex_parse_new_boundary(scanner);
5630
 
            if (ns.status == SYNCTEX_STATUS_OK) {
5631
 
                if (child) {
5632
 
                    _synctex_node_set_sibling(child,ns.node);
5633
 
                } else {
5634
 
                    _synctex_node_set_child(parent,ns.node);
5635
 
                }
5636
 
                if (synctex_node_type(child)==synctex_node_type_box_bdry
5637
 
                    || _synctex_tree_target(x_handle)) {
5638
 
                    child = _synctex_tree_reset_child(x_handle);
5639
 
                    child = _synctex_new_handle_with_child(child);
5640
 
                    __synctex_tree_set_sibling(child, x_handle);
5641
 
                    x_handle = child;
5642
 
                    _synctex_tree_set_target(x_handle,ns.node);
5643
 
                } else if (!form) {
5644
 
                    __synctex_node_make_friend_tlc(ns.node);
5645
 
                }
5646
 
                child = ns.node;
5647
 
                _synctex_make_hbox_contain_point(parent,_synctex_data_point(child));
5648
 
#   if SYNCTEX_VERBOSE
5649
 
                synctex_node_log(child);
5650
 
#   endif
5651
 
                input.node = _synctex_input_register_line(input.node,child);
5652
 
                last_k = last_g = NULL;
5653
 
                goto content_loop;
5654
 
            }
5655
 
        } else if (SYNCTEX_START_SCAN(CHARACTER)) {
5656
 
#       ifdef SYNCTEX_NOTHING
5657
 
#       pragma mark + SCAN CHARACTER
5658
 
#   endif
5659
 
            ++SYNCTEX_CUR;
5660
 
            if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5661
 
                _synctex_error("Missing end of container.");
5662
 
                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5663
 
            }
5664
 
            last_k = last_g = NULL;
5665
 
            goto content_loop;
5666
 
        } else if (SYNCTEX_START_SCAN(ANCHOR)) {
5667
 
#       ifdef SYNCTEX_NOTHING
5668
 
#       pragma mark + SCAN ANCHOR
5669
 
#   endif
5670
 
            goto scan_anchor;
5671
 
        } else if (SYNCTEX_START_SCAN(END_SHEET)) {
5672
 
            if (sheet && parent == sheet) {
5673
 
#       ifdef SYNCTEX_NOTHING
5674
 
#       pragma mark + SCAN TEEHS
5675
 
#   endif
5676
 
                ++SYNCTEX_CUR;
5677
 
                if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5678
 
                    _synctex_error("Missing anchor.");
5679
 
                }
5680
 
                parent = sheet = NULL;
5681
 
                goto main_loop;
5682
 
            }
5683
 
        } else if (SYNCTEX_START_SCAN(END_FORM)) {
5684
 
            if (parent == form && form_depth > 0) {
5685
 
#       ifdef SYNCTEX_NOTHING
5686
 
#       pragma mark + SCAN MROF
5687
 
#   endif
5688
 
                ++SYNCTEX_CUR;
5689
 
                --form_depth;
5690
 
                if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK
5691
 
                    && (form_depth || sheet)) {
5692
 
                    _synctex_error("Missing end of container.");
5693
 
                    SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5694
 
                }
5695
 
                if ((parent = _synctex_tree_parent(form))) {
5696
 
                    _synctex_tree_reset_parent(form);
5697
 
                    child = form;
5698
 
                    form = parent;
5699
 
                    goto content_loop;
5700
 
                } else if (sheet) {
5701
 
                    form = NULL;
5702
 
                    parent = sheet;
5703
 
                    child = synctex_node_last_sibling(child);
5704
 
                    goto content_loop;
5705
 
                }
5706
 
                goto main_loop;
5707
 
            }
5708
 
        }
5709
 
        _synctex_error("Ignored record <%.20s...>(line %i)\n",SYNCTEX_CUR, scanner->reader->line_number+1);
5710
 
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5711
 
            _synctex_error("Missing end of sheet/form.");
5712
 
            SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5713
 
        }
5714
 
        last_k = last_g = NULL;
5715
 
        goto content_loop;
5716
 
    }
5717
 
    zs = _synctex_buffer_get_available_size(scanner,1);
5718
 
    if (zs.size == 0){
5719
 
        _synctex_error("Incomplete synctex file, postamble missing.");
5720
 
        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5721
 
    }
5722
 
    last_k = last_g = NULL;
5723
 
    goto content_loop;
5724
 
}
5725
 
#undef SYNCTEX_RETURN
5726
 
/**
5727
 
 *  Replace ref in its tree hierarchy by a single box
5728
 
 *  proxy to the contents of the associated form.
5729
 
 *  - argument ref: a ref node with no friend
5730
 
 *  - return the proxy created.
5731
 
 *  - note: Does nothing if ref is not owned.
5732
 
 *  - note: On return, ref will have no parent nor sibling.
5733
 
 *      The caller is responsible for releasing ref.
5734
 
 *  - note: this is where root proxies are created.
5735
 
 *  - note: the target of the root proxy is the content
5736
 
 *      of a form.
5737
 
 */
5738
 
SYNCTEX_INLINE static synctex_ns_s __synctex_replace_ref(synctex_node_p ref) {
5739
 
    synctex_ns_s ns = {NULL,SYNCTEX_STATUS_OK};
5740
 
    synctex_node_p parent;
5741
 
    if ((parent = _synctex_tree_parent(ref))) {
5742
 
        synctex_node_p sibling = __synctex_tree_reset_sibling(ref);
5743
 
        synctex_node_p arg_sibling = synctex_node_arg_sibling(ref);
5744
 
        /*  arg_sibling != NULL because the child of a box
5745
 
         *  is always a box boundary, not a ref. */
5746
 
        synctex_node_p target = synctex_form_content(ref->class_->scanner, _synctex_data_tag(ref));
5747
 
        /*  The target is a single node (box)
5748
 
         *  with children and no siblings. */
5749
 
        if ((ns.node = __synctex_new_proxy_from_ref_to(ref, target))) {
5750
 
            /*  Insert this proxy instead of ref. */
5751
 
            _synctex_node_set_sibling(arg_sibling,ns.node);
5752
 
            /*  Then append the original sibling of ref. */
5753
 
            _synctex_node_set_sibling(ns.node,sibling);
5754
 
#   if defined(SYNCTEX_USE_CHARINDEX)
5755
 
            if (synctex_node_type(sibling) == synctex_node_type_box_bdry) {
5756
 
                /*  The sibling is the last box boundary
5757
 
                 *  which may have a less accurate information */
5758
 
                sibling->char_index = arg_sibling->char_index;
5759
 
                sibling->line_index = arg_sibling->line_index;
5760
 
            }
5761
 
#endif
5762
 
#if SYNCTEX_DEBUG>500
5763
 
            printf("!  Ref replacement:\n");
5764
 
            synctex_node_log(ref);
5765
 
            synctex_node_display(synctex_node_sibling(ref));
5766
 
#endif
5767
 
        } else /*  simply remove ref */ {
5768
 
            _synctex_tree_set_sibling(arg_sibling,sibling);
5769
 
        }
5770
 
        __synctex_tree_reset_parent(ref);
5771
 
    } else {
5772
 
        _synctex_error("!  Missing parent in __synctex_replace_ref. "
5773
 
                       "Please report.");
5774
 
        ns.status = SYNCTEX_STATUS_BAD_ARGUMENT;
5775
 
    }
5776
 
    return ns;
5777
 
}
5778
 
/**
5779
 
 *  - argument ref: is the starting point of a linked list
5780
 
 *      of refs. The link is made through the friend field.
5781
 
 *  - returns: the status and the list of all the proxies
5782
 
 *      created. The link is made through the friend field.
5783
 
 *  - note: All refs are freed
5784
 
 */
5785
 
SYNCTEX_INLINE static synctex_ns_s _synctex_post_process_ref(synctex_node_p ref) {
5786
 
    synctex_ns_s ns = {NULL, SYNCTEX_STATUS_OK};
5787
 
    while (ref) {
5788
 
        synctex_node_p next_ref = _synctex_tree_reset_friend(ref);
5789
 
        synctex_ns_s sub_ns = __synctex_replace_ref(ref);
5790
 
        if (sub_ns.status < ns.status) {
5791
 
            ns.status = sub_ns.status;
5792
 
        } else {
5793
 
            /*  Insert all the created proxies in the list
5794
 
             *  sub_ns.node is the last friend,
5795
 
             */
5796
 
            synctex_tree_set_friend(sub_ns.node,ns.node);
5797
 
            ns.node = sub_ns.node;
5798
 
        }
5799
 
        synctex_node_free(ref);
5800
 
        ref = next_ref;
5801
 
    }
5802
 
    return ns;
5803
 
}
5804
 
typedef synctex_node_p (* synctex_processor_f)(synctex_node_p node);
5805
 
/**
5806
 
 *  Apply the processor f to the tree hierarchy rooted at proxy.
5807
 
 *  proxy has replaced a form ref, no children yet.
5808
 
 *  As a side effect all the hierarchy of nodes will be created.
5809
 
 */
5810
 
SYNCTEX_INLINE static synctex_status_t _synctex_post_process_proxy(synctex_node_p proxy, synctex_processor_f f) {
5811
 
    while(proxy) {
5812
 
        synctex_node_p next_proxy = _synctex_tree_friend(proxy);
5813
 
        synctex_node_p halt = __synctex_tree_sibling(proxy);
5814
 
        /*  if proxy is the last sibling, halt is NULL.
5815
 
         *  Find what should be a next node,
5816
 
         *  without creating new nodes. */
5817
 
        if (!halt) {
5818
 
            synctex_node_p parent = _synctex_tree_parent(proxy);
5819
 
            halt = __synctex_tree_sibling(parent);
5820
 
            while (!halt && parent) {
5821
 
                parent = _synctex_tree_parent(parent);
5822
 
                halt = __synctex_tree_sibling(parent);
5823
 
            }
5824
 
        }
5825
 
        do {
5826
 
#if SYNCTEX_DEBUG>500
5827
 
            printf("POST PROCESSING %s\n",_synctex_node_abstract(proxy));
5828
 
            {
5829
 
                int i,j = 0;
5830
 
                for (i=0;i<proxy->class_->scanner->number_of_lists;++i) {
5831
 
                    synctex_node_p N = proxy->class_->scanner->lists_of_friends[i];
5832
 
                    do {
5833
 
                        if (N==proxy) {
5834
 
                            ++j;
5835
 
                            printf("%s",_synctex_node_abstract(N));
5836
 
                        }
5837
 
                    } while ((N = _synctex_tree_friend(N)));
5838
 
                }
5839
 
                if (j) {
5840
 
                    printf("\nBeforehand %i match\n",j);
5841
 
                }
5842
 
            }
5843
 
#endif
5844
 
            f(proxy);
5845
 
#if SYNCTEX_DEBUG>500
5846
 
            {
5847
 
                int i,j = 0;
5848
 
                for (i=0;i<proxy->class_->scanner->number_of_lists;++i) {
5849
 
                    synctex_node_p N = proxy->class_->scanner->lists_of_friends[i];
5850
 
                    do {
5851
 
                        if (N==proxy) {
5852
 
                            ++j;
5853
 
                            printf("%s",_synctex_node_abstract(N));
5854
 
                        }
5855
 
                    } while ((N = _synctex_tree_friend(N)));
5856
 
                }
5857
 
                if (j) {
5858
 
                    printf("\n%i match\n",j);
5859
 
                }
5860
 
            }
5861
 
#endif
5862
 
            /*  Side effect: create the hierarchy on the fly */
5863
 
            proxy = synctex_node_next(proxy); /*  Change is here */
5864
 
#if SYNCTEX_DEBUG>500
5865
 
            if (proxy) {
5866
 
                int i,j = 0;
5867
 
                for (i=0;i<proxy->class_->scanner->number_of_lists;++i) {
5868
 
                    synctex_node_p N = proxy->class_->scanner->lists_of_friends[i];
5869
 
                    do {
5870
 
                        if (N==proxy) {
5871
 
                            ++j;
5872
 
                            printf("%s",_synctex_node_abstract(N));
5873
 
                        }
5874
 
                    } while ((N = _synctex_tree_friend(N)));
5875
 
                }
5876
 
                if (j) {
5877
 
                    printf("\nnext %i match\n",j);
5878
 
                }
5879
 
            }
5880
 
#endif
5881
 
        } while (proxy && proxy != halt);
5882
 
        proxy = next_proxy;
5883
 
    }
5884
 
    return SYNCTEX_STATUS_OK;
5885
 
}
5886
 
/**
5887
 
 *  Replace all the form refs by root box proxies.
5888
 
 *  Create the node hierarchy and update the friends.
5889
 
 *  On entry, the refs are collected as a friend list
5890
 
 *  in either a form or a sheet
5891
 
 *  - parameter: the owning scanner
5892
 
 */
5893
 
SYNCTEX_INLINE static synctex_status_t _synctex_post_process(synctex_scanner_p scanner) {
5894
 
    synctex_status_t status = SYNCTEX_STATUS_OK;
5895
 
    synctex_ns_s ns = {NULL,SYNCTEX_STATUS_NOT_OK};
5896
 
#if SYNCTEX_DEBUG>500
5897
 
    printf("!  entering _synctex_post_process.\n");
5898
 
    synctex_node_display(scanner->sheet);
5899
 
    synctex_node_display(scanner->form);
5900
 
#endif
5901
 
    /*  replace form refs inside forms by box proxies */
5902
 
    ns = _synctex_post_process_ref(scanner->ref_in_form);
5903
 
    scanner->ref_in_form = NULL;/*  it was just released */
5904
 
    if (ns.status<status) {
5905
 
        status = ns.status;
5906
 
    }
5907
 
#if SYNCTEX_DEBUG>500
5908
 
    printf("!  ref replaced in form _synctex_post_process.\n");
5909
 
    synctex_node_display(scanner->form);
5910
 
#endif
5911
 
    /*  Create all the form proxy nodes on the fly.
5912
 
     *  ns.node is the root of the list of
5913
 
     *  newly created proxies.
5914
 
     *  There might be a problem with cascading proxies.
5915
 
     *  In order to be properly managed, the data must
5916
 
     *  be organized in the right way.
5917
 
     *  The inserted form must be defined before
5918
 
     *  the inserting one. *TeX will take care of that.   */
5919
 
    ns.status = _synctex_post_process_proxy(ns.node,&_synctex_tree_reset_friend);
5920
 
    if (ns.status<status) {
5921
 
        status = ns.status;
5922
 
    }
5923
 
    /*  replace form refs inside sheets by box proxies */
5924
 
    ns = _synctex_post_process_ref(scanner->ref_in_sheet);
5925
 
    if (ns.status<status) {
5926
 
        status = ns.status;
5927
 
    }
5928
 
    scanner->ref_in_sheet = NULL;
5929
 
#if SYNCTEX_DEBUG>500
5930
 
    printf("!  ref replaced in sheet _synctex_post_process.\n");
5931
 
    synctex_node_display(scanner->sheet);
5932
 
#endif
5933
 
#if 0
5934
 
    {
5935
 
        int i;
5936
 
        for (i=0;i<scanner->number_of_lists;++i) {
5937
 
            synctex_node_p P = ns.node;
5938
 
            do {
5939
 
                synctex_node_p N = scanner->lists_of_friends[i];
5940
 
                do {
5941
 
                    if (P == N) {
5942
 
                        printf("Already registered.\n");
5943
 
                        synctex_node_display(N);
5944
 
                        break;
5945
 
                    }
5946
 
                } while ((N = _synctex_tree_friend(N)));
5947
 
            } while((P = _synctex_tree_friend(P)));
5948
 
        }
5949
 
    }
5950
 
#endif
5951
 
#if SYNCTEX_DEBUG>10000
5952
 
    {
5953
 
        int i;
5954
 
        for (i=0;i<scanner->number_of_lists;++i) {
5955
 
            synctex_node_p P = scanner->lists_of_friends[i];
5956
 
            int j = 0;
5957
 
            while (P) {
5958
 
                ++j;
5959
 
                synctex_node_log(P);
5960
 
                P = _synctex_tree_friend(P);
5961
 
            }
5962
 
            if (j) {
5963
 
                printf("friends %i -> # %i\n",i,j);
5964
 
            }
5965
 
        }
5966
 
    }
5967
 
#endif
5968
 
    ns.status = _synctex_post_process_proxy(ns.node,&__synctex_proxy_make_friend_and_next_hbox);
5969
 
    if (ns.status<status) {
5970
 
        status = ns.status;
5971
 
    }
5972
 
#if SYNCTEX_DEBUG>500
5973
 
    printf("!  exiting _synctex_post_process.\n");
5974
 
    synctex_node_display(scanner->sheet);
5975
 
    synctex_node_display(scanner->form);
5976
 
    printf("!  display all.\n");
5977
 
    synctex_node_display(scanner->sheet);
5978
 
    synctex_node_display(scanner->form);
5979
 
#endif
5980
 
    return status;
5981
 
}
 
2132
                                cumulated_line_numbers += SYNCTEX_MEAN_LINE(node);
 
2133
                            }
 
2134
                        } else {
 
2135
                            ++node_weight;
 
2136
                            cumulated_line_numbers += SYNCTEX_LINE(node);
 
2137
                        }
 
2138
                    } while ((node = SYNCTEX_SIBLING(node)));
 
2139
                    SYNCTEX_MEAN_LINE(parent)=(cumulated_line_numbers + node_weight/2)/node_weight;
 
2140
                    SYNCTEX_NODE_WEIGHT(parent)=node_weight;
 
2141
                } else {
 
2142
                    SYNCTEX_MEAN_LINE(parent)=SYNCTEX_LINE(parent);
 
2143
                    SYNCTEX_NODE_WEIGHT(parent)=1;
 
2144
                }
 
2145
                                if (NULL == child) {
 
2146
                                        /*  Only boxes with no children are friends,
 
2147
                                         *  boxes with children are indirectly friends through one of their contained nodes. */
 
2148
                                        SYNCTEX_UPDATE_BOX_FRIEND(parent);
 
2149
                                }
 
2150
                                /*  setting the next horizontal box at the end ensures that a child is recorded before any of its ancestors. */
 
2151
                                SYNCTEX_SET_NEXT_hbox(box,parent);
 
2152
                                box = parent;
 
2153
                                child = parent;
 
2154
                                parent = SYNCTEX_PARENT(child);
 
2155
                        } else {
 
2156
                                _synctex_error("Unexpected end of hbox, ignored.");
 
2157
                        }
 
2158
                        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2159
                                _synctex_error("Uncomplete sheet.");
 
2160
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2161
                        }
 
2162
#           if SYNCTEX_VERBOSE
 
2163
                synctex_node_log(child);
 
2164
#           endif
 
2165
                        goto sibling_loop;
 
2166
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_VBOX) {
 
2167
                        if (NULL != (child = _synctex_new_void_vbox(scanner))
 
2168
                                        && NULL != (info = SYNCTEX_INFO(child))) {
 
2169
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2170
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2171
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2172
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2173
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2174
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
 
2175
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
 
2176
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2177
                                        _synctex_error("Bad void vbox record.");
 
2178
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2179
                                }
 
2180
                                SYNCTEX_SET_CHILD(parent,child);
 
2181
                                #define SYNCTEX_UPDATE_FRIEND(NODE)\
 
2182
                                friend_index = (info[SYNCTEX_TAG_IDX].INT+info[SYNCTEX_LINE_IDX].INT)%(scanner->number_of_lists);\
 
2183
                                SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\
 
2184
                                (scanner->lists_of_friends)[friend_index] = NODE;
 
2185
                                SYNCTEX_UPDATE_FRIEND(child);
 
2186
#               if SYNCTEX_VERBOSE
 
2187
                    synctex_node_log(child);
 
2188
#               endif
 
2189
                                goto sibling_loop;
 
2190
                        } else {
 
2191
                                _synctex_error("Can't create vbox record.");
 
2192
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2193
                        }
 
2194
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_HBOX) {
 
2195
                        if (NULL != (child = _synctex_new_void_hbox(scanner))
 
2196
                                        && NULL != (info = SYNCTEX_INFO(child))) {
 
2197
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2198
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2199
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2200
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2201
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2202
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
 
2203
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
 
2204
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2205
                                        _synctex_error("Bad void hbox record.");
 
2206
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2207
                                }
 
2208
                                SYNCTEX_SET_CHILD(parent,child);
 
2209
                                SYNCTEX_UPDATE_FRIEND(child);
 
2210
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2211
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
 
2212
#               if SYNCTEX_VERBOSE
 
2213
                    synctex_node_log(child);
 
2214
#               endif
 
2215
                                goto sibling_loop;
 
2216
                        } else {
 
2217
                                _synctex_error("Can't create void hbox record.");
 
2218
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2219
                        }
 
2220
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_KERN) {
 
2221
                        if (NULL != (child = _synctex_new_kern(scanner))
 
2222
                                        && NULL != (info = SYNCTEX_INFO(child))) {
 
2223
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2224
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2225
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2226
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2227
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2228
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2229
                                        _synctex_error("Bad kern record.");
 
2230
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2231
                                }
 
2232
                                SYNCTEX_SET_CHILD(parent,child);
 
2233
                                SYNCTEX_UPDATE_FRIEND(child);
 
2234
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2235
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child)-SYNCTEX_WIDTH(child),SYNCTEX_VERT(child));
 
2236
#               if SYNCTEX_VERBOSE
 
2237
                    synctex_node_log(child);
 
2238
#               endif
 
2239
                                goto sibling_loop;
 
2240
                        } else {
 
2241
                                _synctex_error("Can't create kern record.");
 
2242
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2243
                        }
 
2244
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_GLUE) {
 
2245
                        if (NULL != (child = _synctex_new_glue(scanner))
 
2246
                                        && NULL != (info = SYNCTEX_INFO(child))) {
 
2247
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2248
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2249
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2250
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2251
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2252
                                        _synctex_error("Bad glue record.");
 
2253
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2254
                                }
 
2255
                                SYNCTEX_SET_CHILD(parent,child);
 
2256
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2257
                                SYNCTEX_UPDATE_FRIEND(child);
 
2258
#               if SYNCTEX_VERBOSE
 
2259
                    synctex_node_log(child);
 
2260
#               endif
 
2261
                                goto sibling_loop;
 
2262
                        } else {
 
2263
                                _synctex_error("Can't create glue record.");
 
2264
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2265
                        }
 
2266
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_MATH) {
 
2267
                        if (NULL != (child = _synctex_new_math(scanner))
 
2268
                                        && NULL != (info = SYNCTEX_INFO(child))) {
 
2269
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2270
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2271
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2272
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2273
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2274
                                        _synctex_error("Bad math record.");
 
2275
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2276
                                }
 
2277
                                SYNCTEX_SET_CHILD(parent,child);
 
2278
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2279
                                SYNCTEX_UPDATE_FRIEND(child);
 
2280
#               if SYNCTEX_VERBOSE
 
2281
                    synctex_node_log(child);
 
2282
#               endif
 
2283
                                goto sibling_loop;
 
2284
                        } else {
 
2285
                                _synctex_error("Can't create math record.");
 
2286
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2287
                        }
 
2288
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BOUNDARY) {
 
2289
                        if (NULL != (child = _synctex_new_boundary(scanner))
 
2290
                                        && NULL != (info = SYNCTEX_INFO(child))) {
 
2291
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2292
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2293
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2294
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2295
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2296
                                        _synctex_error("Bad boundary record.");
 
2297
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2298
                                }
 
2299
                                SYNCTEX_SET_CHILD(parent,child);
 
2300
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2301
                                SYNCTEX_UPDATE_FRIEND(child);
 
2302
#               if SYNCTEX_VERBOSE
 
2303
                    synctex_node_log(child);
 
2304
#               endif
 
2305
                                goto sibling_loop;
 
2306
                        } else {
 
2307
                                _synctex_error("Can't create math record.");
 
2308
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2309
                        }
 
2310
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
 
2311
                        goto scan_teehs;
 
2312
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) {
 
2313
                        /*  Addendum to version 1.10 to manage nested sheets  */
 
2314
                        ++SYNCTEX_CUR;
 
2315
                        if (_synctex_scan_nested_sheet(scanner)<SYNCTEX_STATUS_OK) {
 
2316
                                _synctex_error("Unexpected nested sheet.");
 
2317
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2318
                        }
 
2319
                        goto child_loop;
 
2320
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
 
2321
                        goto scan_anchor;
 
2322
                } else {
 
2323
                        /*  _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
 
2324
                        ++SYNCTEX_CUR;
 
2325
                        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2326
                                _synctex_error("Unexpected end.");
 
2327
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2328
                        }
 
2329
                        goto child_loop;
 
2330
                }
 
2331
        } else {
 
2332
                available = 1;
 
2333
                status = _synctex_buffer_get_available_size(scanner,&available);
 
2334
                 if (status<SYNCTEX_STATUS_OK && available>0){
 
2335
                        _synctex_error("Uncomplete sheet(0)");
 
2336
                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2337
                } else {
 
2338
                        goto child_loop;
 
2339
                }
 
2340
        }
 
2341
/*  The vertical loop means that we are on the same level, for example when we just ended a box.
 
2342
 *  If a node is created now, it will be a sibling of the current node, sharing the same parent. */
 
2343
sibling_loop:
 
2344
        if (SYNCTEX_CUR<SYNCTEX_END) {
 
2345
                if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_VBOX) {
 
2346
                        if (NULL != (sibling = _synctex_new_vbox(scanner))
 
2347
                                        && NULL != (info = SYNCTEX_INFO(sibling))) {
 
2348
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2349
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2350
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2351
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2352
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2353
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
 
2354
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
 
2355
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2356
                                        _synctex_error("Bad vbox record (2).");
 
2357
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2358
                                }
 
2359
                                SYNCTEX_SET_SIBLING(child,sibling);
 
2360
                                parent = sibling;
 
2361
                                child = NULL;
 
2362
                                goto child_loop;
 
2363
                        } else {
 
2364
                                _synctex_error("Can't create vbox record (2).");
 
2365
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2366
                        }
 
2367
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_VBOX) {
 
2368
                        goto scan_xobv;
 
2369
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_HBOX) {
 
2370
                        if (NULL != (sibling = _synctex_new_hbox(scanner)) &&
 
2371
                                        NULL != (info = SYNCTEX_INFO(sibling))) {
 
2372
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2373
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2374
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2375
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2376
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2377
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
 
2378
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
 
2379
                                                || _synctex_setup_visible_box(sibling)<SYNCTEX_STATUS_OK
 
2380
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2381
                                        _synctex_error("Bad hbox record (2).");
 
2382
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2383
                                }
 
2384
                                SYNCTEX_SET_SIBLING(child,sibling);
 
2385
                                child = sibling;
 
2386
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2387
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
 
2388
#               if SYNCTEX_VERBOSE
 
2389
                    synctex_node_log(child);
 
2390
#               endif
 
2391
                                parent = child;
 
2392
                                child = NULL;
 
2393
                                goto child_loop;
 
2394
                        } else {
 
2395
                                _synctex_error("Can't create hbox record (2).");
 
2396
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2397
                        }
 
2398
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_HBOX) {
 
2399
                        goto scan_xobh;
 
2400
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_VBOX) {
 
2401
                        if (NULL != (sibling = _synctex_new_void_vbox(scanner)) &&
 
2402
                                        NULL != (info = SYNCTEX_INFO(sibling))) {
 
2403
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2404
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2405
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2406
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2407
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2408
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
 
2409
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
 
2410
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2411
                                        _synctex_error("Bad void vbox record (2).");
 
2412
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2413
                                }
 
2414
                                SYNCTEX_SET_SIBLING(child,sibling);
 
2415
                                child = sibling;
 
2416
#               if SYNCTEX_VERBOSE
 
2417
                    synctex_node_log(child);
 
2418
#               endif
 
2419
                                SYNCTEX_UPDATE_FRIEND(child);
 
2420
                                goto sibling_loop;
 
2421
                        } else {
 
2422
                                _synctex_error("can't create void vbox record (2).");
 
2423
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2424
                        }
 
2425
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_HBOX) {
 
2426
                        if (NULL != (sibling = _synctex_new_void_hbox(scanner)) &&
 
2427
                                        NULL != (info = SYNCTEX_INFO(sibling))) {
 
2428
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2429
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2430
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2431
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2432
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2433
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
 
2434
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
 
2435
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2436
                                        _synctex_error("Bad void hbox record (2).");
 
2437
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2438
                                }
 
2439
                                SYNCTEX_SET_SIBLING(child,sibling);
 
2440
                                child = sibling;
 
2441
#               if SYNCTEX_VERBOSE
 
2442
                    synctex_node_log(child);
 
2443
#               endif
 
2444
                                SYNCTEX_UPDATE_FRIEND(child);
 
2445
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2446
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
 
2447
                                goto sibling_loop;
 
2448
                        } else {
 
2449
                                _synctex_error("can't create void hbox record (2).");
 
2450
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2451
                        }
 
2452
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_KERN) {
 
2453
                        if (NULL != (sibling = _synctex_new_kern(scanner))
 
2454
                                        && NULL != (info = SYNCTEX_INFO(sibling))) {
 
2455
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2456
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2457
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2458
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2459
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
 
2460
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2461
                                        _synctex_error("Bad kern record (2).");
 
2462
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2463
                                }
 
2464
                                SYNCTEX_SET_SIBLING(child,sibling);
 
2465
                                child = sibling;
 
2466
#               if SYNCTEX_VERBOSE
 
2467
                    synctex_node_log(child);
 
2468
#               endif
 
2469
                                SYNCTEX_UPDATE_FRIEND(child);
 
2470
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2471
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child)-SYNCTEX_WIDTH(child),SYNCTEX_VERT(child));
 
2472
                                goto sibling_loop;
 
2473
                        } else {
 
2474
                                _synctex_error("Can't create kern record (2).");
 
2475
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2476
                        }
 
2477
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_GLUE) {
 
2478
                        if (NULL != (sibling = _synctex_new_glue(scanner))
 
2479
                                        && NULL != (info = SYNCTEX_INFO(sibling))) {
 
2480
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2481
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2482
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2483
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2484
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2485
                                        _synctex_error("Bad glue record (2).");
 
2486
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2487
                                }
 
2488
                                SYNCTEX_SET_SIBLING(child,sibling);
 
2489
                                child = sibling;
 
2490
#               if SYNCTEX_VERBOSE
 
2491
                    synctex_node_log(child);
 
2492
#               endif
 
2493
                                SYNCTEX_UPDATE_FRIEND(child);
 
2494
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2495
                                goto sibling_loop;
 
2496
                        } else {
 
2497
                                _synctex_error("Can't create glue record (2).");
 
2498
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2499
                        }
 
2500
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_MATH) {
 
2501
                        if (NULL != (sibling = _synctex_new_math(scanner))
 
2502
                                        && NULL != (info = SYNCTEX_INFO(sibling))) {
 
2503
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2504
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2505
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2506
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2507
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2508
                                        _synctex_error("Bad math record (2).");
 
2509
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2510
                                }
 
2511
                                SYNCTEX_SET_SIBLING(child,sibling);
 
2512
                                child = sibling;
 
2513
#               if SYNCTEX_VERBOSE
 
2514
                    synctex_node_log(child);
 
2515
#               endif
 
2516
                                SYNCTEX_UPDATE_FRIEND(child);
 
2517
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2518
                                goto sibling_loop;
 
2519
                        } else {
 
2520
                                _synctex_error("Can't create math record (2).");
 
2521
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2522
                        }
 
2523
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BOUNDARY) {
 
2524
                        if (NULL != (sibling = _synctex_new_boundary(scanner))
 
2525
                                        && NULL != (info = SYNCTEX_INFO(sibling))) {
 
2526
                                if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
 
2527
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
 
2528
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
 
2529
                                                || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
 
2530
                                                || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2531
                                        _synctex_error("Bad boundary record (2).");
 
2532
                                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2533
                                }
 
2534
                                SYNCTEX_SET_SIBLING(child,sibling);
 
2535
                                child = sibling;
 
2536
#               if SYNCTEX_VERBOSE
 
2537
                    synctex_node_log(child);
 
2538
#               endif
 
2539
                                SYNCTEX_UPDATE_FRIEND(child);
 
2540
                                _synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
 
2541
                                goto sibling_loop;
 
2542
                        } else {
 
2543
                                _synctex_error("Can't create boundary record (2).");
 
2544
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2545
                        }
 
2546
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
 
2547
                        goto scan_teehs;
 
2548
                } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
 
2549
                        ++SYNCTEX_CUR;
 
2550
                        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2551
                                _synctex_error("Missing anchor (2).");
 
2552
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2553
                        }
 
2554
                        goto sibling_loop;
 
2555
                } else {
 
2556
                        ++SYNCTEX_CUR;
 
2557
                        /* _synctex_error("Ignored record %c(2)\n",*SYNCTEX_CUR); */
 
2558
                        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2559
                                SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2560
                        }
 
2561
                        goto sibling_loop;
 
2562
                }
 
2563
        } else {
 
2564
                available = 1;
 
2565
                status = _synctex_buffer_get_available_size(scanner,&available);
 
2566
                if (status<SYNCTEX_STATUS_OK && available>0){
 
2567
                        goto sibling_loop;
 
2568
                } else {
 
2569
                        _synctex_error("Uncomplete sheet(2)");
 
2570
                        SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
 
2571
                }
 
2572
        }
 
2573
#   undef SYNCTEX_DECODE_FAILED
 
2574
}
 
2575
 
 
2576
#   define SYNCTEX_APPEND_SHEET(SCANNER,SHEET) if (SCANNER->sheet) {\
 
2577
        synctex_node_t last_sheet = SCANNER->sheet;\
 
2578
        synctex_node_t next_sheet = NULL;\
 
2579
        while ((next_sheet = SYNCTEX_SIBLING(last_sheet))) {\
 
2580
            last_sheet = next_sheet;\
 
2581
        }\
 
2582
                SYNCTEX_SET_SIBLING(last_sheet,SHEET);\
 
2583
    } else {\
 
2584
        SCANNER->sheet = SHEET;\
 
2585
    }
 
2586
 
5982
2587
/*  Used when parsing the synctex file
5983
2588
 */
5984
 
static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner) {
5985
 
    if (NULL == scanner) {
5986
 
        return SYNCTEX_STATUS_BAD_ARGUMENT;
5987
 
    }
5988
 
    scanner->reader->lastv = -1;
5989
 
    synctex_status_t status = 0;
5990
 
    /*  Find where this section starts */
 
2589
synctex_status_t _synctex_scan_content(synctex_scanner_t scanner) {
 
2590
        synctex_node_t sheet = NULL;
 
2591
        synctex_status_t status = 0;
 
2592
        if (NULL == scanner) {
 
2593
                return SYNCTEX_STATUS_BAD_ARGUMENT;
 
2594
        }
 
2595
        /*  set up the lists of friends */
 
2596
        if (NULL == scanner->lists_of_friends) {
 
2597
                scanner->number_of_lists = 1024;
 
2598
                scanner->lists_of_friends = (synctex_node_t *)_synctex_malloc(scanner->number_of_lists*sizeof(synctex_node_t));
 
2599
                if (NULL == scanner->lists_of_friends) {
 
2600
                        _synctex_error("malloc:2");
 
2601
                        return SYNCTEX_STATUS_ERROR;
 
2602
                }
 
2603
        }
 
2604
        /*  Find where this section starts */
5991
2605
content_not_found:
5992
 
    status = _synctex_match_string(scanner,"Content:");
5993
 
    if (status<SYNCTEX_STATUS_EOF) {
5994
 
        return status;
5995
 
    }
5996
 
    if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5997
 
        _synctex_error("Incomplete Content.");
5998
 
        return SYNCTEX_STATUS_ERROR;
5999
 
    }
6000
 
    if (status == SYNCTEX_STATUS_NOT_OK) {
6001
 
        goto content_not_found;
6002
 
    }
6003
 
    status = __synctex_parse_sfi(scanner);
6004
 
    if (status == SYNCTEX_STATUS_OK) {
6005
 
        status = _synctex_post_process(scanner);
6006
 
    }
6007
 
    return status;
6008
 
}
6009
 
synctex_scanner_p synctex_scanner_new() {
6010
 
    synctex_scanner_p scanner =(synctex_scanner_p)_synctex_malloc(sizeof(synctex_scanner_s));
6011
 
    if (scanner) {
6012
 
        if (!(scanner->reader = _synctex_malloc(sizeof(synctex_reader_s)))) {
6013
 
            _synctex_free(scanner);
6014
 
            return NULL;
6015
 
        }
6016
 
#       ifdef SYNCTEX_NOTHING
6017
 
#       pragma mark -
6018
 
#   endif
6019
 
#   define DEFINE_synctex_scanner_class(NAME)\
6020
 
    scanner->class_[synctex_node_type_##NAME] = synctex_class_##NAME;\
6021
 
(scanner->class_[synctex_node_type_##NAME]).scanner = scanner
6022
 
        DEFINE_synctex_scanner_class(input);
6023
 
        DEFINE_synctex_scanner_class(sheet);
6024
 
        DEFINE_synctex_scanner_class(form);
6025
 
        DEFINE_synctex_scanner_class(hbox);
6026
 
        DEFINE_synctex_scanner_class(void_hbox);
6027
 
        DEFINE_synctex_scanner_class(vbox);
6028
 
        DEFINE_synctex_scanner_class(void_vbox);
6029
 
        DEFINE_synctex_scanner_class(kern);
6030
 
        DEFINE_synctex_scanner_class(glue);
6031
 
        DEFINE_synctex_scanner_class(rule);
6032
 
        DEFINE_synctex_scanner_class(math);
6033
 
        DEFINE_synctex_scanner_class(boundary);
6034
 
        DEFINE_synctex_scanner_class(box_bdry);
6035
 
        DEFINE_synctex_scanner_class(ref);
6036
 
        DEFINE_synctex_scanner_class(proxy_hbox);
6037
 
        DEFINE_synctex_scanner_class(proxy_vbox);
6038
 
        DEFINE_synctex_scanner_class(proxy);
6039
 
        DEFINE_synctex_scanner_class(proxy_last);
6040
 
        DEFINE_synctex_scanner_class(handle);
6041
 
        /*  set up the lists of friends */
6042
 
        scanner->number_of_lists = 1024;
6043
 
        scanner->lists_of_friends = (synctex_node_r)_synctex_malloc(scanner->number_of_lists*sizeof(synctex_node_p));
6044
 
        if (NULL == scanner->lists_of_friends) {
6045
 
            synctex_scanner_free(scanner);
6046
 
            _synctex_error("malloc:2");
6047
 
            return NULL;
6048
 
        }
6049
 
        scanner->display_switcher = 100;
6050
 
        scanner->display_prompt = (char *)_synctex_display_prompt+strlen(_synctex_display_prompt)-1;
6051
 
    }
6052
 
    return scanner;
6053
 
}
 
2606
        status = _synctex_match_string(scanner,"Content:");
 
2607
        if (status<SYNCTEX_STATUS_EOF) {
 
2608
                return status;
 
2609
        }
 
2610
        if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
 
2611
                _synctex_error("Uncomplete Content.");
 
2612
                return SYNCTEX_STATUS_ERROR;
 
2613
        }
 
2614
        if (status == SYNCTEX_STATUS_NOT_OK) {
 
2615
                goto content_not_found;
 
2616
        }
 
2617
next_sheet:
 
2618
        if (*SYNCTEX_CUR != SYNCTEX_CHAR_BEGIN_SHEET) {
 
2619
                status = _synctex_scan_postamble(scanner);
 
2620
                if (status < SYNCTEX_STATUS_EOF) {
 
2621
                        _synctex_error("Bad content.");
 
2622
                        return status;
 
2623
                }
 
2624
                if (status<SYNCTEX_STATUS_OK) {
 
2625
                        status = _synctex_next_line(scanner);
 
2626
                        if (status < SYNCTEX_STATUS_OK) {
 
2627
                                _synctex_error("Bad content.");
 
2628
                                return status;
 
2629
                        }
 
2630
                        goto next_sheet;
 
2631
                }
 
2632
                return SYNCTEX_STATUS_OK;
 
2633
        }
 
2634
        /*  Create a new sheet node */
 
2635
        sheet = _synctex_new_sheet(scanner);
 
2636
        status = _synctex_decode_int(scanner,&(SYNCTEX_PAGE(sheet)));
 
2637
        if (status<SYNCTEX_STATUS_OK) {
 
2638
                _synctex_error("Missing sheet number.");
 
2639
bail:
 
2640
                SYNCTEX_FREE(sheet);
 
2641
                return SYNCTEX_STATUS_ERROR;
 
2642
        }
 
2643
        status = _synctex_next_line(scanner);
 
2644
        if (status<SYNCTEX_STATUS_OK) {
 
2645
                _synctex_error("Uncomplete file.");
 
2646
                goto bail;
 
2647
        }
 
2648
        status = _synctex_scan_sheet(scanner,sheet);
 
2649
        if (status<SYNCTEX_STATUS_OK) {
 
2650
                _synctex_error("Bad sheet content.");
 
2651
                goto bail;
 
2652
        }
 
2653
        SYNCTEX_APPEND_SHEET(scanner,sheet);
 
2654
        sheet = NULL;
 
2655
        /*  Now read the list of Inputs between 2 sheets. */
 
2656
        do {
 
2657
                status = _synctex_scan_input(scanner);
 
2658
                if (status<SYNCTEX_STATUS_EOF) {
 
2659
                        _synctex_error("Bad input section.");
 
2660
                        goto bail;
 
2661
                }
 
2662
        }
 
2663
        while(status >= SYNCTEX_STATUS_OK);
 
2664
        goto next_sheet;
 
2665
}
 
2666
 
 
2667
int _synctex_open(const char * output, const char * build_directory, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_modeRef);
 
2668
 
6054
2669
/*  Where the synctex scanner is created. */
6055
 
synctex_scanner_p synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) {
6056
 
    synctex_scanner_p scanner = synctex_scanner_new();
6057
 
    if (NULL == scanner) {
6058
 
        _synctex_error("malloc problem");
6059
 
        return NULL;
6060
 
    }
6061
 
    if (synctex_reader_init_with_output_file(scanner->reader, output, build_directory)) {
6062
 
        return parse? synctex_scanner_parse(scanner):scanner;
6063
 
    }
6064
 
    // don't warn to terminal if no file is present, this is a library.
6065
 
    // _synctex_error("No file?");
6066
 
    synctex_scanner_free(scanner);
6067
 
    return NULL;
 
2670
synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) {
 
2671
        gzFile file = NULL;
 
2672
        char * synctex = NULL;
 
2673
        synctex_scanner_t scanner = NULL;
 
2674
        synctex_io_mode_t io_mode = 0;
 
2675
        /*  Here we assume that int are smaller than void * */
 
2676
        if (sizeof(int)>sizeof(void*)) {
 
2677
                _synctex_error("INTERNAL INCONSISTENCY: int's are unexpectedly bigger than pointers, bailing out.");
 
2678
                return NULL;
 
2679
        }
 
2680
        /*  We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */
 
2681
        if (SYNCTEX_BUFFER_SIZE >= UINT_MAX) {
 
2682
                _synctex_error("Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (1)");
 
2683
                return NULL;
 
2684
        }
 
2685
        /*  for integers: */
 
2686
        if (SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE) {
 
2687
                _synctex_error("Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (2)");
 
2688
                return NULL;
 
2689
        }
 
2690
        /*  now open the synctex file */
 
2691
        if (_synctex_open(output,build_directory,&synctex,&file,synctex_ADD_QUOTES,&io_mode) || !file) {
 
2692
                if (_synctex_open(output,build_directory,&synctex,&file,synctex_DONT_ADD_QUOTES,&io_mode) || !file) {
 
2693
                        return NULL;
 
2694
                }
 
2695
        }
 
2696
        scanner = (synctex_scanner_t)_synctex_malloc(sizeof(_synctex_scanner_t));
 
2697
        if (NULL == scanner) {
 
2698
                _synctex_error("malloc problem");
 
2699
                free(synctex);
 
2700
                gzclose(file);
 
2701
                return NULL;
 
2702
        }
 
2703
        /*  make a private copy of output for the scanner */
 
2704
        if (NULL == (scanner->output = (char *)malloc(strlen(output)+1))){
 
2705
                _synctex_error("!  synctex_scanner_new_with_output_file: Memory problem (2), scanner's output is not reliable.");
 
2706
        } else if (scanner->output != strcpy(scanner->output,output)) {
 
2707
                _synctex_error("!  synctex_scanner_new_with_output_file: Copy problem, scanner's output is not reliable.");
 
2708
        }
 
2709
        scanner->synctex = synctex;/*  Now the scanner owns synctex */
 
2710
        SYNCTEX_FILE = file;
 
2711
        return parse? synctex_scanner_parse(scanner):scanner;
 
2712
}
 
2713
 
 
2714
/*      This functions opens the file at the "output" given location.
 
2715
 *  It manages the problem of quoted filenames that appear with pdftex and filenames containing the space character.
 
2716
 *  In TeXLive 2008, the synctex file created with pdftex did contain unexpected quotes.
 
2717
 *      This function will remove them if possible.
 
2718
 *  All the reference arguments will take a value on return. They must be non NULL.
 
2719
 *      0 on success, non 0 on error. */
 
2720
static int __synctex_open(const char * output, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_mode_ref) {
 
2721
        if (synctex_name_ref && file_ref && io_mode_ref) {
 
2722
        /*  1 local variables that uses dynamic memory */
 
2723
        char * synctex_name = NULL;
 
2724
        gzFile the_file = NULL;
 
2725
        char * quoteless_synctex_name = NULL;
 
2726
                size_t size = 0;
 
2727
        synctex_io_mode_t io_mode = *io_mode_ref;
 
2728
                const char * mode = _synctex_get_io_mode_name(io_mode);
 
2729
                /*  now create the synctex file name */
 
2730
                size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1;
 
2731
                synctex_name = (char *)malloc(size);
 
2732
                if (NULL == synctex_name) {
 
2733
                        _synctex_error("!  __synctex_open: Memory problem (1)\n");
 
2734
                        return 1;
 
2735
                }
 
2736
                /*  we have reserved for synctex enough memory to copy output (including its 2 eventual quotes), both suffices,
 
2737
                 *  including the terminating character. size is free now. */
 
2738
                if (synctex_name != strcpy(synctex_name,output)) {
 
2739
                        _synctex_error("!  __synctex_open: Copy problem\n");
 
2740
return_on_error:
 
2741
                        free(synctex_name);
 
2742
                        free(quoteless_synctex_name);
 
2743
                        return 2;
 
2744
                }
 
2745
                /*  remove the last path extension if any */
 
2746
                _synctex_strip_last_path_extension(synctex_name);
 
2747
                if (!strlen(synctex_name)) {
 
2748
                        goto return_on_error;           
 
2749
                }
 
2750
                /*  now insert quotes. */
 
2751
                if (add_quotes) {
 
2752
                        char * quoted = NULL;
 
2753
                        if (_synctex_copy_with_quoting_last_path_component(synctex_name,&quoted,size) || (NULL == quoted)) {
 
2754
                                /*      There was an error or quoting does not make sense: */
 
2755
                                goto return_on_error;
 
2756
                        }
 
2757
                        quoteless_synctex_name = synctex_name;
 
2758
                        synctex_name = quoted;
 
2759
                }
 
2760
                /*      Now add to synctex_name the first path extension. */
 
2761
                if (synctex_name != strcat(synctex_name,synctex_suffix)){
 
2762
                        _synctex_error("!  __synctex_open: Concatenation problem (can't add suffix '%s')\n",synctex_suffix);
 
2763
                        goto return_on_error;
 
2764
                }
 
2765
                /*      Add to quoteless_synctex_name as well, if relevant. */
 
2766
                if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix))){
 
2767
                        free(quoteless_synctex_name);
 
2768
                        quoteless_synctex_name = NULL;
 
2769
                }
 
2770
                if (NULL == (the_file = gzopen(synctex_name,mode))) {
 
2771
                        /*  Could not open this file */
 
2772
                        if (errno != ENOENT) {
 
2773
                                /*  The file does exist, this is a lower level error, I can't do anything. */
 
2774
                                _synctex_error("could not open %s, error %i\n",synctex_name,errno);
 
2775
                                goto return_on_error;
 
2776
                        }
 
2777
                        /*  Apparently, there is no uncompressed synctex file. Try the compressed version */
 
2778
                        if (synctex_name != strcat(synctex_name,synctex_suffix_gz)){
 
2779
                                _synctex_error("!  __synctex_open: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz);
 
2780
                                goto return_on_error;
 
2781
                        }
 
2782
                        io_mode |= synctex_io_gz_mask;
 
2783
                        mode = _synctex_get_io_mode_name(io_mode); /* the file is a compressed and is a binary file, this caused errors on Windows */
 
2784
                        /*      Add the suffix to the quoteless_synctex_name as well. */
 
2785
                        if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix_gz))){
 
2786
                                free(quoteless_synctex_name);
 
2787
                                quoteless_synctex_name = NULL;
 
2788
                        }
 
2789
                        if (NULL == (the_file = gzopen(synctex_name,mode))) {
 
2790
                                /*  Could not open this file */
 
2791
                                if (errno != ENOENT) {
 
2792
                                        /*  The file does exist, this is a lower level error, I can't do anything. */
 
2793
                                        _synctex_error("Could not open %s, error %i\n",synctex_name,errno);
 
2794
                                }
 
2795
                                goto return_on_error;
 
2796
                        }
 
2797
                }
 
2798
                /*      At this point, the file is properly open.
 
2799
                 *  If we are in the add_quotes mode, we change the file name by removing the quotes. */
 
2800
                if (quoteless_synctex_name) {
 
2801
                        gzclose(the_file);
 
2802
                        if (rename(synctex_name,quoteless_synctex_name)) {
 
2803
                                _synctex_error("Could not rename %s to %s, error %i\n",synctex_name,quoteless_synctex_name,errno);
 
2804
                                /*      We could not rename, reopen the file with the quoted name. */
 
2805
                                if (NULL == (the_file = gzopen(synctex_name,mode))) {
 
2806
                                        /*  No luck, could not re open this file, something has happened meanwhile */
 
2807
                                        if (errno != ENOENT) {
 
2808
                                                /*  The file does not exist any more, it has certainly be removed somehow
 
2809
                         *  this is a lower level error, I can't do anything. */
 
2810
                                                _synctex_error("Could not open again %s, error %i\n",synctex_name,errno);
 
2811
                                        }
 
2812
                                        goto return_on_error;
 
2813
                                }
 
2814
                        } else {
 
2815
                /*  The file has been successfully renamed */
 
2816
                                if (NULL == (the_file = gzopen(quoteless_synctex_name,mode))) {
 
2817
                                        /*  Could not open this file */
 
2818
                                        if (errno != ENOENT) {
 
2819
                                                /*  The file does exist, this is a lower level error, I can't do anything. */
 
2820
                                                _synctex_error("Could not open renamed %s, error %i\n",quoteless_synctex_name,errno);
 
2821
                                        }
 
2822
                                        goto return_on_error;
 
2823
                                }
 
2824
                                /*  The quote free file name should replace the old one:*/
 
2825
                                free(synctex_name);
 
2826
                                synctex_name = quoteless_synctex_name;
 
2827
                                quoteless_synctex_name = NULL;
 
2828
                        }
 
2829
                }
 
2830
        /*  The operation is successfull, return the arguments by value.    */
 
2831
        * file_ref = the_file;
 
2832
        * io_mode_ref = io_mode;
 
2833
        * synctex_name_ref = synctex_name;
 
2834
                return 0;
 
2835
        }
 
2836
        return 3;       /*      Bad parameter.  */
 
2837
}
 
2838
 
 
2839
/*      Opens the ouput file, taking into account the eventual build_directory.
 
2840
 *      0 on success, non 0 on error. */
 
2841
int _synctex_open(const char * output, const char * build_directory, char ** synctex_name_ref, gzFile * file_ref, synctex_bool_t add_quotes, synctex_io_mode_t * io_mode_ref) {
 
2842
#       define synctex_name (*synctex_name_ref)
 
2843
#       define the_file (*file_ref)
 
2844
        int result = __synctex_open(output,synctex_name_ref,file_ref,add_quotes,io_mode_ref);
 
2845
        if ((result || !*file_ref) && build_directory && strlen(build_directory)) {
 
2846
                char * build_output;
 
2847
                const char *lpc;
 
2848
                size_t size;
 
2849
                synctex_bool_t is_absolute;
 
2850
                build_output = NULL;
 
2851
                lpc = _synctex_last_path_component(output);
 
2852
                size = strlen(build_directory)+strlen(lpc)+2;   /*  One for the '/' and one for the '\0'.   */
 
2853
                is_absolute = _synctex_path_is_absolute(build_directory);
 
2854
                if (!is_absolute) {
 
2855
                        size += strlen(output);
 
2856
                }
 
2857
                if ((build_output = (char *)malloc(size))) {
 
2858
                        if (is_absolute) {
 
2859
                                build_output[0] = '\0';
 
2860
                        } else {
 
2861
                                if (build_output != strcpy(build_output,output)) {
 
2862
                                        free(build_output);
 
2863
                                        return -4;
 
2864
                                }
 
2865
                                build_output[lpc-output]='\0';
 
2866
                        }
 
2867
                        if (build_output == strcat(build_output,build_directory)) {
 
2868
                                /*      Append a path separator if necessary. */
 
2869
                                if (!SYNCTEX_IS_PATH_SEPARATOR(build_output[strlen(build_directory)-1])) {
 
2870
                                        if (build_output != strcat(build_output,"/")) {
 
2871
                                                free(build_output);
 
2872
                                                return -2;
 
2873
                                        }
 
2874
                                }
 
2875
                                /*      Append the last path component of the output. */
 
2876
                                if (build_output != strcat(build_output,lpc)) {
 
2877
                                        free(build_output);
 
2878
                                        return -3;
 
2879
                                }
 
2880
                                result = __synctex_open(build_output,synctex_name_ref,file_ref,add_quotes,io_mode_ref);
 
2881
                                free(build_output);
 
2882
                                return result;
 
2883
                        }
 
2884
                        free(build_output);
 
2885
                }
 
2886
                return -1;
 
2887
        }
 
2888
        return result;
 
2889
#       undef synctex_name
 
2890
#       undef the_file
6068
2891
}
6069
2892
 
6070
2893
/*  The scanner destructor
6071
2894
 */
6072
 
int synctex_scanner_free(synctex_scanner_p scanner) {
6073
 
    int node_count = 0;
6074
 
    if (scanner) {
6075
 
        synctex_node_free(scanner->sheet);
6076
 
        synctex_node_free(scanner->form);
6077
 
        synctex_node_free(scanner->input);
6078
 
        synctex_reader_free(scanner->reader);
6079
 
        SYNCTEX_SCANNER_FREE_HANDLE(scanner);
6080
 
        synctex_iterator_free(scanner->iterator);
6081
 
        free(scanner->output_fmt);
6082
 
        free(scanner->lists_of_friends);
6083
 
#if SYNCTEX_USE_NODE_COUNT>0
6084
 
        node_count = scanner->node_count;
6085
 
#endif
6086
 
        free(scanner);
6087
 
    }
6088
 
    return node_count;
 
2895
void synctex_scanner_free(synctex_scanner_t scanner) {
 
2896
        if (NULL == scanner) {
 
2897
                return;
 
2898
        }
 
2899
        if (SYNCTEX_FILE) {
 
2900
                gzclose(SYNCTEX_FILE);
 
2901
                SYNCTEX_FILE = NULL;
 
2902
        }
 
2903
        SYNCTEX_FREE(scanner->sheet);
 
2904
        SYNCTEX_FREE(scanner->input);
 
2905
        free(SYNCTEX_START);
 
2906
        free(scanner->output_fmt);
 
2907
        free(scanner->output);
 
2908
        free(scanner->synctex);
 
2909
        free(scanner->lists_of_friends);
 
2910
        free(scanner);
6089
2911
}
6090
2912
 
6091
2913
/*  Where the synctex scanner parses the contents of the file. */
6092
 
synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner) {
6093
 
    synctex_status_t status = 0;
6094
 
    if (!scanner || scanner->flags.has_parsed) {
6095
 
        return scanner;
6096
 
    }
6097
 
    scanner->flags.has_parsed=1;
6098
 
    scanner->pre_magnification = 1000;
6099
 
    scanner->pre_unit = 8192;
6100
 
    scanner->pre_x_offset = scanner->pre_y_offset = 578;
6101
 
    /*  initialize the offset with a fake improbable value,
6102
 
     *  If there is a post scriptum section, this value will be overridden by the real life value */
6103
 
    scanner->x_offset = scanner->y_offset = 6.027e23f;
6104
 
    scanner->reader->line_number = 1;
6105
 
    
6106
 
    synctex_scanner_set_display_switcher(scanner, 1000);
6107
 
    SYNCTEX_END = SYNCTEX_START+SYNCTEX_BUFFER_SIZE;
6108
 
    /*  SYNCTEX_END always points to a null terminating character.
6109
 
     *  Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1.
6110
 
     *  At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */
6111
 
    *SYNCTEX_END = '\0';
6112
 
    SYNCTEX_CUR = SYNCTEX_END;
 
2914
synctex_scanner_t synctex_scanner_parse(synctex_scanner_t scanner) {
 
2915
        synctex_status_t status = 0;
 
2916
        if (!scanner || scanner->flags.has_parsed) {
 
2917
                return scanner;
 
2918
        }
 
2919
        scanner->flags.has_parsed=1;
 
2920
        scanner->pre_magnification = 1000;
 
2921
        scanner->pre_unit = 8192;
 
2922
        scanner->pre_x_offset = scanner->pre_y_offset = 578;
 
2923
        /*  initialize the offset with a fake unprobable value,
 
2924
         *  If there is a post scriptum section, this value will be overriden by the real life value */
 
2925
        scanner->x_offset = scanner->y_offset = 6.027e23f;
 
2926
#   define DEFINE_synctex_scanner_class(NAME)\
 
2927
        scanner->class[synctex_node_type_##NAME] = synctex_class_##NAME;\
 
2928
        (scanner->class[synctex_node_type_##NAME]).scanner = scanner
 
2929
    DEFINE_synctex_scanner_class(sheet);
 
2930
    DEFINE_synctex_scanner_class(input);
 
2931
    DEFINE_synctex_scanner_class(hbox);
 
2932
    DEFINE_synctex_scanner_class(void_hbox);
 
2933
    DEFINE_synctex_scanner_class(vbox);
 
2934
    DEFINE_synctex_scanner_class(void_vbox);
 
2935
    DEFINE_synctex_scanner_class(kern);
 
2936
    DEFINE_synctex_scanner_class(glue);
 
2937
    DEFINE_synctex_scanner_class(math);
 
2938
    DEFINE_synctex_scanner_class(boundary);
 
2939
        SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE+1); /*  one more character for null termination */
 
2940
        if (NULL == SYNCTEX_START) {
 
2941
                _synctex_error("malloc error");
 
2942
                synctex_scanner_free(scanner);
 
2943
                return NULL;
 
2944
        }
 
2945
        SYNCTEX_END = SYNCTEX_START+SYNCTEX_BUFFER_SIZE;
 
2946
        /*  SYNCTEX_END always points to a null terminating character.
 
2947
         *  Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1.
 
2948
         *  At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */
 
2949
        *SYNCTEX_END = '\0';
 
2950
        SYNCTEX_CUR = SYNCTEX_END;
6113
2951
#   if defined(SYNCTEX_USE_CHARINDEX)
6114
 
    scanner->reader->charindex_offset = -SYNCTEX_BUFFER_SIZE;
 
2952
    scanner->charindex_offset = -SYNCTEX_BUFFER_SIZE;
6115
2953
#   endif
6116
 
    status = _synctex_scan_preamble(scanner);
6117
 
    if (status<SYNCTEX_STATUS_OK) {
6118
 
        _synctex_error("Bad preamble\n");
6119
 
        bailey:
6120
 
#ifdef SYNCTEX_DEBUG
6121
 
            return scanner;
6122
 
#else
6123
 
            synctex_scanner_free(scanner);
6124
 
            return NULL;
6125
 
#endif
6126
 
    }
6127
 
    status = _synctex_scan_content(scanner);
6128
 
    if (status<SYNCTEX_STATUS_OK) {
6129
 
        _synctex_error("Bad content\n");
6130
 
        goto bailey;
6131
 
    }
6132
 
    status = _synctex_scan_postamble(scanner);
6133
 
    if (status<SYNCTEX_STATUS_OK) {
6134
 
        _synctex_error("Bad postamble. Ignored\n");
6135
 
    }
6136
 
#if SYNCTEX_DEBUG>500
6137
 
    synctex_scanner_set_display_switcher(scanner, 100);
6138
 
    synctex_node_display(scanner->sheet);
6139
 
    synctex_node_display(scanner->form);
6140
 
#endif
6141
 
    synctex_scanner_set_display_switcher(scanner, 1000);
6142
 
    /*  Everything is finished, free the buffer, close the file */
6143
 
    free((void *)SYNCTEX_START);
6144
 
    SYNCTEX_START = SYNCTEX_CUR = SYNCTEX_END = NULL;
6145
 
    gzclose(SYNCTEX_FILE);
6146
 
    SYNCTEX_FILE = NULL;
6147
 
    /*  Final tuning: set the default values for various parameters */
6148
 
    /*  1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp
6149
 
     * 1 pt = 65536 sp */
6150
 
    if (scanner->pre_unit<=0) {
6151
 
        scanner->pre_unit = 8192;
6152
 
    }
6153
 
    if (scanner->pre_magnification<=0) {
6154
 
        scanner->pre_magnification = 1000;
6155
 
    }
6156
 
    if (scanner->unit <= 0) {
6157
 
        /*  no post magnification */
6158
 
        scanner->unit = scanner->pre_unit / 65781.76;/*  65781.76 or 65536.0*/
6159
 
    } else {
6160
 
        /*  post magnification */
6161
 
        scanner->unit *= scanner->pre_unit / 65781.76;
6162
 
    }
6163
 
    scanner->unit *= scanner->pre_magnification / 1000.0;
6164
 
    if (scanner->x_offset > 6e23) {
6165
 
        /*  no post offset */
6166
 
        scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76);
6167
 
        scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76);
6168
 
    } else {
6169
 
        /*  post offset */
6170
 
        scanner->x_offset /= 65781.76f;
6171
 
        scanner->y_offset /= 65781.76f;
6172
 
    }
6173
 
    return scanner;
6174
 
#undef SYNCTEX_FILE
 
2954
        status = _synctex_scan_preamble(scanner);
 
2955
        if (status<SYNCTEX_STATUS_OK) {
 
2956
                _synctex_error("SyncTeX Error: Bad preamble\n");
 
2957
bailey:
 
2958
                synctex_scanner_free(scanner);
 
2959
                return NULL;
 
2960
        }
 
2961
        status = _synctex_scan_content(scanner);
 
2962
        if (status<SYNCTEX_STATUS_OK) {
 
2963
                _synctex_error("SyncTeX Error: Bad content\n");
 
2964
                goto bailey;
 
2965
        }
 
2966
        /*  Everything is finished, free the buffer, close the file */
 
2967
        free((void *)SYNCTEX_START);
 
2968
        SYNCTEX_START = SYNCTEX_CUR = SYNCTEX_END = NULL;
 
2969
        gzclose(SYNCTEX_FILE);
 
2970
        SYNCTEX_FILE = NULL;
 
2971
        /*  Final tuning: set the default values for various parameters */
 
2972
        /*  1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp
 
2973
         * 1 pt = 65536 sp */
 
2974
        if (scanner->pre_unit<=0) {
 
2975
                scanner->pre_unit = 8192;
 
2976
        }
 
2977
        if (scanner->pre_magnification<=0) {
 
2978
                scanner->pre_magnification = 1000;
 
2979
        }
 
2980
        if (scanner->unit <= 0) {
 
2981
                /*  no post magnification */
 
2982
                scanner->unit = scanner->pre_unit / 65781.76;/*  65781.76 or 65536.0*/
 
2983
        } else {
 
2984
                /*  post magnification */
 
2985
                scanner->unit *= scanner->pre_unit / 65781.76;
 
2986
        }
 
2987
        scanner->unit *= scanner->pre_magnification / 1000.0;
 
2988
        if (scanner->x_offset > 6e23) {
 
2989
                /*  no post offset */
 
2990
                scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76);
 
2991
                scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76);
 
2992
        } else {
 
2993
                /*  post offset */
 
2994
                scanner->x_offset /= 65781.76f;
 
2995
                scanner->y_offset /= 65781.76f;
 
2996
        }
 
2997
        return scanner;
 
2998
        #undef SYNCTEX_FILE
6175
2999
}
6176
3000
 
6177
3001
/*  Scanner accessors.
6178
3002
 */
6179
 
int synctex_scanner_pre_x_offset(synctex_scanner_p scanner){
6180
 
    return scanner?scanner->pre_x_offset:0;
6181
 
}
6182
 
int synctex_scanner_pre_y_offset(synctex_scanner_p scanner){
6183
 
    return scanner?scanner->pre_y_offset:0;
6184
 
}
6185
 
int synctex_scanner_x_offset(synctex_scanner_p scanner){
6186
 
    return scanner?scanner->x_offset:0;
6187
 
}
6188
 
int synctex_scanner_y_offset(synctex_scanner_p scanner){
6189
 
    return scanner?scanner->y_offset:0;
6190
 
}
6191
 
float synctex_scanner_magnification(synctex_scanner_p scanner){
6192
 
    return scanner?scanner->unit:1;
6193
 
}
6194
 
void synctex_scanner_display(synctex_scanner_p scanner) {
6195
 
    if (NULL == scanner) {
6196
 
        return;
6197
 
    }
6198
 
    printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n",scanner->reader->output,scanner->output_fmt,scanner->version);
6199
 
    printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n",scanner->pre_unit,scanner->pre_x_offset,scanner->pre_y_offset);
6200
 
    printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n",
6201
 
           scanner->count,scanner->unit,scanner->x_offset,scanner->y_offset);
6202
 
    printf("The input:\n");
6203
 
    synctex_node_display(scanner->input);
6204
 
    if (scanner->count<1000) {
6205
 
        printf("The sheets:\n");
6206
 
        synctex_node_display(scanner->sheet);
6207
 
        printf("The friends:\n");
6208
 
        if (scanner->lists_of_friends) {
6209
 
            int i = scanner->number_of_lists;
6210
 
            synctex_node_p node;
6211
 
            while(i--) {
6212
 
                printf("Friend index:%i\n",i);
6213
 
                node = (scanner->lists_of_friends)[i];
6214
 
                while(node) {
6215
 
                    printf("%s:%i,%i\n",
6216
 
                           synctex_node_isa(node),
6217
 
                           _synctex_data_tag(node),
6218
 
                           _synctex_data_line(node)
6219
 
                           );
6220
 
                    node = _synctex_tree_friend(node);
6221
 
                }
6222
 
            }
6223
 
        }
6224
 
    } else {
6225
 
        printf("SyncTeX Warning: Too many objects\n");
6226
 
    }
6227
 
}
6228
 
/*  Public */
6229
 
const char * synctex_scanner_get_name(synctex_scanner_p scanner,int tag) {
6230
 
    synctex_node_p input = NULL;
6231
 
    if (NULL == scanner) {
6232
 
        return NULL;
6233
 
    }
6234
 
    if ((input = scanner->input)) {;
6235
 
        do {
6236
 
            if (tag == _synctex_data_tag(input)) {
6237
 
                return (_synctex_data_name(input));
6238
 
            }
6239
 
        } while((input = __synctex_tree_sibling(input)));
6240
 
    }
6241
 
    return NULL;
6242
 
}
6243
 
const char * synctex_node_get_name(synctex_node_p node) {
6244
 
    if (node) {
6245
 
        return synctex_scanner_get_name(node->class_->scanner,_synctex_data_tag(node));
6246
 
    }
6247
 
    return NULL;
 
3003
int synctex_scanner_pre_x_offset(synctex_scanner_t scanner){
 
3004
        return scanner?scanner->pre_x_offset:0;
 
3005
}
 
3006
int synctex_scanner_pre_y_offset(synctex_scanner_t scanner){
 
3007
        return scanner?scanner->pre_y_offset:0;
 
3008
}
 
3009
int synctex_scanner_x_offset(synctex_scanner_t scanner){
 
3010
        return scanner?scanner->x_offset:0;
 
3011
}
 
3012
int synctex_scanner_y_offset(synctex_scanner_t scanner){
 
3013
        return scanner?scanner->y_offset:0;
 
3014
}
 
3015
float synctex_scanner_magnification(synctex_scanner_t scanner){
 
3016
        return scanner?scanner->unit:1;
 
3017
}
 
3018
void synctex_scanner_display(synctex_scanner_t scanner) {
 
3019
        if (NULL == scanner) {
 
3020
                return;
 
3021
        }
 
3022
        printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n",scanner->output,scanner->output_fmt,scanner->version);
 
3023
        printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n",scanner->pre_unit,scanner->pre_x_offset,scanner->pre_y_offset);
 
3024
        printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n",
 
3025
                scanner->count,scanner->unit,scanner->x_offset,scanner->y_offset);
 
3026
        printf("The input:\n");
 
3027
        SYNCTEX_DISPLAY(scanner->input);
 
3028
        if (scanner->count<1000) {
 
3029
                printf("The sheets:\n");
 
3030
                SYNCTEX_DISPLAY(scanner->sheet);
 
3031
                printf("The friends:\n");
 
3032
                if (scanner->lists_of_friends) {
 
3033
                        int i = scanner->number_of_lists;
 
3034
                        synctex_node_t node;
 
3035
                        while(i--) {
 
3036
                                printf("Friend index:%i\n",i);
 
3037
                                node = (scanner->lists_of_friends)[i];
 
3038
                                while(node) {
 
3039
                                        printf("%s:%i,%i\n",
 
3040
                                                synctex_node_isa(node),
 
3041
                                                SYNCTEX_TAG(node),
 
3042
                                                SYNCTEX_LINE(node)
 
3043
                                        );
 
3044
                                        node = SYNCTEX_FRIEND(node);
 
3045
                                }
 
3046
                        }
 
3047
                }
 
3048
        } else {
 
3049
                printf("SyncTeX Warning: Too many objects\n");
 
3050
        }
 
3051
}
 
3052
/*  Public*/
 
3053
const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag) {
 
3054
        synctex_node_t input = NULL;
 
3055
        if (NULL == scanner) {
 
3056
                return NULL;
 
3057
        }
 
3058
        input = scanner->input;
 
3059
        do {
 
3060
                if (tag == SYNCTEX_TAG(input)) {
 
3061
                        return (SYNCTEX_NAME(input));
 
3062
                }
 
3063
        } while((input = SYNCTEX_SIBLING(input)) != NULL);
 
3064
        return NULL;
6248
3065
}
6249
3066
 
6250
 
static int _synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name);
6251
 
static int _synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name) {
6252
 
    synctex_node_p input = NULL;
6253
 
    if (NULL == scanner) {
6254
 
        return 0;
6255
 
    }
6256
 
    if ((input = scanner->input)) {
6257
 
        do {
6258
 
            if (_synctex_is_equivalent_file_name(name,(_synctex_data_name(input)))) {
6259
 
                return _synctex_data_tag(input);
6260
 
            }
6261
 
        } while((input = __synctex_tree_sibling(input)));
6262
 
    }
 
3067
int _synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name);
 
3068
int _synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name) {
 
3069
        synctex_node_t input = NULL;
 
3070
        if (NULL == scanner) {
 
3071
                return 0;
 
3072
        }
 
3073
        input = scanner->input;
 
3074
        do {
 
3075
                if (_synctex_is_equivalent_file_name(name,(SYNCTEX_NAME(input)))) {
 
3076
                        return SYNCTEX_TAG(input);
 
3077
                }
 
3078
        } while((input = SYNCTEX_SIBLING(input)) != NULL);
6263
3079
    //  2011 version
6264
3080
    name = _synctex_base_name(name);
6265
 
    if ((input = scanner->input)) {
6266
 
        do {
6267
 
            if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(input)))) {
6268
 
                synctex_node_p other_input = input;
6269
 
                while((other_input = __synctex_tree_sibling(other_input))) {
6270
 
                    if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(other_input)))
6271
 
                        && (strlen(_synctex_data_name(input))!=strlen(_synctex_data_name(other_input))
6272
 
                            || strncmp(_synctex_data_name(other_input),_synctex_data_name(input),strlen(_synctex_data_name(input))))) {
6273
 
                            // There is a second possible candidate
6274
 
                            return 0;
6275
 
                        }
 
3081
        input = scanner->input;
 
3082
        do {
 
3083
                if (_synctex_is_equivalent_file_name(name,_synctex_base_name(SYNCTEX_NAME(input)))) {
 
3084
            synctex_node_t other_input = input;
 
3085
            while((other_input = SYNCTEX_SIBLING(other_input)) != NULL) {
 
3086
                if (_synctex_is_equivalent_file_name(name,_synctex_base_name(SYNCTEX_NAME(other_input)))
 
3087
                    && (strlen(SYNCTEX_NAME(input))!=strlen(SYNCTEX_NAME(other_input))
 
3088
                        || strncmp(SYNCTEX_NAME(other_input),SYNCTEX_NAME(input),strlen(SYNCTEX_NAME(input))))) {
 
3089
                    // There is a second possible candidate
 
3090
                    return 0;
6276
3091
                }
6277
 
                return _synctex_data_tag(input);
6278
3092
            }
6279
 
        } while((input = __synctex_tree_sibling(input)));
6280
 
    }
6281
 
    return 0;
 
3093
                        return SYNCTEX_TAG(input);
 
3094
                }
 
3095
        } while((input = SYNCTEX_SIBLING(input)) != NULL);
 
3096
        return 0;
6282
3097
}
6283
3098
 
6284
 
int synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name) {
6285
 
    size_t char_index = strlen(name);
6286
 
    if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) {
6287
 
        /*  the name is not void */
6288
 
        char_index -= 1;
6289
 
        if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) {
6290
 
            /*  the last character of name is not a path separator */
6291
 
            int result = _synctex_scanner_get_tag(scanner,name);
6292
 
            if (result) {
6293
 
                return result;
6294
 
            } else {
6295
 
                /*  the given name was not the one known by TeX
6296
 
                 *  try a name relative to the enclosing directory of the scanner->output file */
6297
 
                const char * relative = name;
6298
 
                const char * ptr = scanner->reader->output;
6299
 
                while((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr))
6300
 
                {
6301
 
                    relative += 1;
6302
 
                    ptr += 1;
6303
 
                }
6304
 
                /*  Find the last path separator before relative */
6305
 
                while(relative > name) {
6306
 
                    if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) {
6307
 
                        break;
6308
 
                    }
6309
 
                    relative -= 1;
6310
 
                }
6311
 
                if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) {
6312
 
                    return result;
6313
 
                }
6314
 
                if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) {
6315
 
                    /*  No tag found for the given absolute name,
6316
 
                     *  Try each relative path starting from the shortest one */
6317
 
                    while(0<char_index) {
6318
 
                        char_index -= 1;
6319
 
                        if (SYNCTEX_IS_PATH_SEPARATOR(name[char_index])
6320
 
                            && (result = _synctex_scanner_get_tag(scanner,name+char_index+1))) {
6321
 
                            return result;
6322
 
                        }
6323
 
                    }
6324
 
                }
6325
 
            }
6326
 
            return result;
6327
 
        }
6328
 
    }
6329
 
    return 0;
6330
 
}
6331
 
synctex_node_p synctex_scanner_input(synctex_scanner_p scanner) {
6332
 
    return scanner?scanner->input:NULL;
6333
 
}
6334
 
synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner, int tag) {
6335
 
    synctex_node_p input = scanner?scanner->input:NULL;
6336
 
    while (_synctex_data_tag(input)!=tag) {
6337
 
        if ((input = __synctex_tree_sibling(input))) {
6338
 
            continue;
6339
 
        }
6340
 
        break;
6341
 
    }
6342
 
    return input;
6343
 
}
6344
 
const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner) {
6345
 
    return NULL != scanner && scanner->output_fmt?scanner->output_fmt:"";
6346
 
}
6347
 
const char * synctex_scanner_get_output(synctex_scanner_p scanner) {
6348
 
    return NULL != scanner && scanner->reader->output?scanner->reader->output:"";
6349
 
}
6350
 
const char * synctex_scanner_get_synctex(synctex_scanner_p scanner) {
6351
 
    return NULL != scanner && scanner->reader->synctex?scanner->reader->synctex:"";
 
3099
int synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name) {
 
3100
        size_t char_index = strlen(name);
 
3101
        if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) {
 
3102
                /*  the name is not void */
 
3103
                char_index -= 1;
 
3104
                if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) {
 
3105
                        /*  the last character of name is not a path separator */
 
3106
                        int result = _synctex_scanner_get_tag(scanner,name);
 
3107
                        if (result) {
 
3108
                                return result;
 
3109
                        } else {
 
3110
                                /*  the given name was not the one known by TeX
 
3111
                                 *  try a name relative to the enclosing directory of the scanner->output file */
 
3112
                                const char * relative = name;
 
3113
                                const char * ptr = scanner->output;
 
3114
                                while((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr))
 
3115
                                {
 
3116
                                        relative += 1;
 
3117
                                        ptr += 1;
 
3118
                                }
 
3119
                                /*  Find the last path separator before relative */
 
3120
                                while(relative > name) {
 
3121
                                        if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) {
 
3122
                                                break;
 
3123
                                        }
 
3124
                                        relative -= 1;
 
3125
                                }
 
3126
                                if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) {
 
3127
                                        return result;
 
3128
                                }
 
3129
                                if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) {
 
3130
                                        /*  No tag found for the given absolute name,
 
3131
                                         *  Try each relative path starting from the shortest one */
 
3132
                                        while(0<char_index) {
 
3133
                                                char_index -= 1;
 
3134
                                                if (SYNCTEX_IS_PATH_SEPARATOR(name[char_index])
 
3135
                                                                && (result = _synctex_scanner_get_tag(scanner,name+char_index+1))) {
 
3136
                                                        return result;
 
3137
                                                }
 
3138
                                        }
 
3139
                                }
 
3140
                        }
 
3141
                        return result;
 
3142
                }
 
3143
        }
 
3144
        return 0;
 
3145
}
 
3146
synctex_node_t synctex_scanner_input(synctex_scanner_t scanner) {
 
3147
        return scanner?scanner->input:NULL;
 
3148
}
 
3149
const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner) {
 
3150
        return NULL != scanner && scanner->output_fmt?scanner->output_fmt:"";
 
3151
}
 
3152
const char * synctex_scanner_get_output(synctex_scanner_t scanner) {
 
3153
        return NULL != scanner && scanner->output?scanner->output:"";
 
3154
}
 
3155
const char * synctex_scanner_get_synctex(synctex_scanner_t scanner) {
 
3156
        return NULL != scanner && scanner->synctex?scanner->synctex:"";
6352
3157
}
6353
3158
#       ifdef SYNCTEX_NOTHING
6354
3159
#       pragma mark -
6355
3160
#       pragma mark Public node attributes
6356
3161
#   endif
6357
 
 
6358
 
#   define SYNCTEX_DEFINE_NODE_HVWHD(WHAT) \
6359
 
int synctex_node_##WHAT(synctex_node_p node) { \
6360
 
    return (node && node->class_->inspector->WHAT)? \
6361
 
        node->class_->inspector->WHAT(node): 0; \
6362
 
}
6363
 
#   define SYNCTEX_DEFINE_PROXY_HV(WHAT) \
6364
 
static int _synctex_proxy_##WHAT(synctex_proxy_p proxy) { \
6365
 
    synctex_node_p target = _synctex_tree_target(proxy); \
6366
 
    if (target) { \
6367
 
        return _synctex_data_##WHAT(proxy)+synctex_node_##WHAT(target); \
6368
 
    } else { \
6369
 
        return proxy? _synctex_data_##WHAT(proxy): 0; \
6370
 
    } \
6371
 
}
6372
 
#define SYNCTEX_DEFINE_PROXY_TLCWVD(WHAT) \
6373
 
static int _synctex_proxy_##WHAT(synctex_proxy_p proxy) { \
6374
 
    synctex_node_p target = _synctex_tree_target(proxy); \
6375
 
    return target? synctex_node_##WHAT(target): 0; \
6376
 
}
6377
 
 
6378
 
/**
6379
 
 *  The horizontal location of the node.
6380
 
 *  Idem for v, width, height and depth.
6381
 
 *  - parameter node: a node with geometrical information.
6382
 
 *  - returns: an integer.
6383
 
 *  - requires: every proxy node has a target.
6384
 
 *  - note: recursive call if the parameter has a proxy.
6385
 
 *  - author: JL
6386
 
 */
6387
 
SYNCTEX_DEFINE_NODE_HVWHD(h)
6388
 
SYNCTEX_DEFINE_NODE_HVWHD(v)
6389
 
SYNCTEX_DEFINE_NODE_HVWHD(width)
6390
 
SYNCTEX_DEFINE_NODE_HVWHD(height)
6391
 
SYNCTEX_DEFINE_NODE_HVWHD(depth)
6392
 
SYNCTEX_DEFINE_PROXY_TLCWVD(tag)
6393
 
SYNCTEX_DEFINE_PROXY_TLCWVD(line)
6394
 
SYNCTEX_DEFINE_PROXY_TLCWVD(column)
6395
 
SYNCTEX_DEFINE_PROXY_HV(h)
6396
 
SYNCTEX_DEFINE_PROXY_HV(v)
6397
 
SYNCTEX_DEFINE_PROXY_TLCWVD(width)
6398
 
SYNCTEX_DEFINE_PROXY_TLCWVD(height)
6399
 
SYNCTEX_DEFINE_PROXY_TLCWVD(depth)
6400
 
 
6401
 
/**
6402
 
 *  Whether the argument is a box,
6403
 
 *  either vertical or horizontal,
6404
 
 *  either void or not,
6405
 
 *  or a proxy to such a box.
6406
 
 *  - parameter NODE: of type synctex_node_p
6407
 
 *  - returns: yorn
6408
 
 */
6409
 
 
6410
 
SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_box(synctex_node_p node) {
6411
 
    return node &&
6412
 
    (node->class_->type == synctex_node_type_hbox
6413
 
     || node->class_->type == synctex_node_type_void_hbox
6414
 
     || node->class_->type == synctex_node_type_vbox
6415
 
     || node->class_->type == synctex_node_type_void_vbox
6416
 
     || _synctex_node_is_box(_synctex_tree_target(node)));
6417
 
}
6418
 
 
6419
 
/**
6420
 
 *  Whether the argument is a handle.
6421
 
 *  Handles are similar to proxies because they have a target.
6422
 
 *  They are used for query results.
6423
 
 *  - parameter NODE: of type synctex_node_p
6424
 
 *  - returns: yorn
6425
 
 */
6426
 
 
6427
 
SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_handle(synctex_node_p node) {
6428
 
    return node &&
6429
 
    (node->class_->type == synctex_node_type_handle);
6430
 
}
6431
 
 
6432
 
/**
6433
 
 *  Resolves handle indirection.
6434
 
 *  - parameter node: of type synctex_node_p
6435
 
 *  - returns: node if it is not a handle,
6436
 
 *  its target otherwise.
6437
 
 */
6438
 
 
6439
 
SYNCTEX_INLINE static synctex_node_p _synctex_node_or_handle_target(synctex_node_p node) {
6440
 
    return _synctex_node_is_handle(node)?
6441
 
    _synctex_tree_target(node):node;
6442
 
}
6443
 
 
6444
 
/**
6445
 
 *  Whether the argument is an hbox.
6446
 
 *  - parameter NODE: of type synctex_node_p
6447
 
 *  - returns: yorn
6448
 
 */
6449
 
 
6450
 
SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_hbox(synctex_node_p node) {
6451
 
    return node &&
6452
 
    (node->class_->type == synctex_node_type_hbox
6453
 
     || node->class_->type == synctex_node_type_void_hbox
6454
 
     || _synctex_node_is_hbox(_synctex_tree_target(node)));
6455
 
}
6456
 
 
6457
 
/**
6458
 
 *  The horizontal location of the first box enclosing node.
6459
 
 *  - parameter node: a node with geometrical information.
6460
 
 *  - returns: an integer.
6461
 
 *  - author: JL
6462
 
 */
6463
 
int synctex_node_box_h(synctex_node_p node) {
6464
 
    if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6465
 
        return synctex_node_h(node);
6466
 
    }
6467
 
    return 0;
6468
 
}
6469
 
/**
6470
 
 *  The vertical location of the first box enclosing node.
6471
 
 *  - parameter node: a node with geometrical information.
6472
 
 *  - returns: an integer.
6473
 
 *  - author: JL
6474
 
 */
6475
 
int synctex_node_box_v(synctex_node_p node) {
6476
 
    if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6477
 
        return synctex_node_v(node);
6478
 
    }
6479
 
    return 0;
6480
 
}
6481
 
/**
6482
 
 *  The width of the first box enclosing node.
6483
 
 *  - parameter node: a node with geometrical information.
6484
 
 *  - returns: an integer.
6485
 
 *  - author: JL
6486
 
 */
6487
 
int synctex_node_box_width(synctex_node_p node) {
6488
 
    if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6489
 
        return synctex_node_width(node);
6490
 
    }
6491
 
    return 0;
6492
 
}
6493
 
/**
6494
 
 *  The height of the first box enclosing node.
6495
 
 *  - parameter node: a node with geometrical information.
6496
 
 *  - returns: an integer.
6497
 
 *  - author: JL
6498
 
 */
6499
 
int synctex_node_box_height(synctex_node_p node) {
6500
 
    if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6501
 
        return synctex_node_height(node);
6502
 
    }
6503
 
    return 0;
6504
 
}
6505
 
/**
6506
 
 *  The depth of the first box enclosing node.
6507
 
 *  - parameter node: a node with geometrical information.
6508
 
 *  - returns: an integer.
6509
 
 *  - author: JL
6510
 
 */
6511
 
int synctex_node_box_depth(synctex_node_p node) {
6512
 
    if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) {
6513
 
        return synctex_node_depth(node);
6514
 
    }
6515
 
    return 0;
6516
 
}
6517
 
/**
6518
 
 *  The horizontal location of an hbox, corrected with contents.
6519
 
 *  - parameter node: an hbox node.
6520
 
 *  - returns: an integer, 0 if node is not an hbox or an hbox proxy.
6521
 
 *  - note: recursive call when node is an hbox proxy.
6522
 
 *  - author: JL
6523
 
 */
6524
 
int synctex_node_hbox_h(synctex_node_p node) {
6525
 
    switch(synctex_node_type(node)) {
6526
 
        case synctex_node_type_hbox:
6527
 
            return _synctex_data_h_V(node);
6528
 
        case synctex_node_type_proxy_hbox:
6529
 
            return _synctex_data_h(node)+synctex_node_hbox_h(_synctex_tree_target(node));
6530
 
        default:
6531
 
            return 0;
6532
 
    }
6533
 
}
6534
 
/**
6535
 
 *  The vertical location of an hbox, corrected with contents.
6536
 
 *  - parameter node: an hbox node.
6537
 
 *  - returns: an integer, 0 if node is not an hbox or an hbox proxy.
6538
 
 *  - note: recursive call when node is an hbox proxy.
6539
 
 *  - author: JL
6540
 
 */
6541
 
int synctex_node_hbox_v(synctex_node_p node) {
6542
 
    switch(synctex_node_type(node)) {
6543
 
        case synctex_node_type_hbox:
6544
 
            return _synctex_data_v_V(node);
6545
 
        case synctex_node_type_proxy_hbox:
6546
 
            return _synctex_data_v(node)+synctex_node_hbox_v(_synctex_tree_target(node));
6547
 
        default:
6548
 
            return 0;
6549
 
    }
6550
 
}
6551
 
/**
6552
 
 *  The width of an hbox, corrected with contents.
6553
 
 *  - parameter node: an hbox node, 0 if node is not an hbox or an hbox proxy.
6554
 
 *  - returns: an integer.
6555
 
 *  - author: JL
6556
 
 */
6557
 
int synctex_node_hbox_width(synctex_node_p node) {
6558
 
    synctex_node_p target = _synctex_tree_target(node);
6559
 
    if (target) {
6560
 
        node = target;
6561
 
    }
6562
 
    return synctex_node_type(node) == synctex_node_type_hbox?
6563
 
    _synctex_data_width_V(node): 0;
6564
 
}
6565
 
/**
6566
 
 *  The height of an hbox, corrected with contents.
6567
 
 *  - parameter node: an hbox node.
6568
 
 *  - returns: an integer, 0 if node is not an hbox or an hbox proxy.
6569
 
 *  - author: JL
6570
 
 */
6571
 
int synctex_node_hbox_height(synctex_node_p node) {
6572
 
    synctex_node_p target = _synctex_tree_target(node);
6573
 
    if (target) {
6574
 
        node = target;
6575
 
    }
6576
 
    return synctex_node_type(node) == synctex_node_type_hbox?
6577
 
    _synctex_data_height_V(node): 0;
6578
 
}
6579
 
/**
6580
 
 *  The depth of an hbox, corrected with contents.
6581
 
 *  - parameter node: an hbox node.
6582
 
 *  - returns: an integer, 0 if node is not an hbox or an hbox proxy.
6583
 
 *  - note: recursive call when node is an hbox proxy.
6584
 
 *  - author: JL
6585
 
 */
6586
 
int synctex_node_hbox_depth(synctex_node_p node) {
6587
 
    synctex_node_p target = _synctex_tree_target(node);
6588
 
    if (target) {
6589
 
        node = target;
6590
 
    }
6591
 
    return synctex_node_type(node) == synctex_node_type_hbox?
6592
 
    _synctex_data_depth_V(node): 0;
 
3162
int synctex_node_h(synctex_node_t node){
 
3163
        if (!node) {
 
3164
                return 0;
 
3165
        }
 
3166
        return SYNCTEX_HORIZ(node);
 
3167
}
 
3168
int synctex_node_v(synctex_node_t node){
 
3169
        if (!node) {
 
3170
                return 0;
 
3171
        }
 
3172
        return SYNCTEX_VERT(node);
 
3173
}
 
3174
int synctex_node_width(synctex_node_t node){
 
3175
        if (!node) {
 
3176
                return 0;
 
3177
        }
 
3178
        return SYNCTEX_WIDTH(node);
 
3179
}
 
3180
int synctex_node_box_h(synctex_node_t node){
 
3181
        if (!node) {
 
3182
                return 0;
 
3183
        }
 
3184
        if (SYNCTEX_IS_BOX(node)) {
 
3185
result:
 
3186
                return SYNCTEX_HORIZ(node);
 
3187
        }
 
3188
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3189
                goto result;
 
3190
        }
 
3191
        return 0;
 
3192
}
 
3193
int synctex_node_box_v(synctex_node_t node){
 
3194
        if (!node) {
 
3195
                return 0;
 
3196
        }
 
3197
        if (SYNCTEX_IS_BOX(node)) {
 
3198
result:
 
3199
                return SYNCTEX_VERT(node);
 
3200
        }
 
3201
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3202
                goto result;
 
3203
        }
 
3204
        return 0;
 
3205
}
 
3206
int synctex_node_box_width(synctex_node_t node){
 
3207
        if (!node) {
 
3208
                return 0;
 
3209
        }
 
3210
        if (SYNCTEX_IS_BOX(node)) {
 
3211
result:
 
3212
                return SYNCTEX_WIDTH(node);
 
3213
        }
 
3214
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3215
                goto result;
 
3216
        }
 
3217
        return 0;
 
3218
}
 
3219
int synctex_node_box_height(synctex_node_t node){
 
3220
        if (!node) {
 
3221
                return 0;
 
3222
        }
 
3223
        if (SYNCTEX_IS_BOX(node)) {
 
3224
result:
 
3225
                return SYNCTEX_HEIGHT(node);
 
3226
        }
 
3227
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3228
                goto result;
 
3229
        }
 
3230
        return 0;
 
3231
}
 
3232
int synctex_node_box_depth(synctex_node_t node){
 
3233
        if (!node) {
 
3234
                return 0;
 
3235
        }
 
3236
        if (SYNCTEX_IS_BOX(node)) {
 
3237
result:
 
3238
                return SYNCTEX_DEPTH(node);
 
3239
        }
 
3240
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3241
                goto result;
 
3242
        }
 
3243
        return 0;
6593
3244
}
6594
3245
#       ifdef SYNCTEX_NOTHING
6595
3246
#       pragma mark -
6596
3247
#       pragma mark Public node visible attributes
6597
3248
#   endif
6598
 
 
6599
 
#define SYNCTEX_VISIBLE_SIZE(node,s) \
6600
 
(s)*node->class_->scanner->unit
6601
 
#define SYNCTEX_VISIBLE_DISTANCE_h(node,d) \
6602
 
((d)*node->class_->scanner->unit+node->class_->scanner->x_offset)
6603
 
#define SYNCTEX_VISIBLE_DISTANCE_v(node,d) \
6604
 
((d)*node->class_->scanner->unit+node->class_->scanner->y_offset)
6605
 
static float __synctex_node_visible_h(synctex_node_p node) {
6606
 
    return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node));
6607
 
}
6608
 
static float __synctex_node_visible_v(synctex_node_p node) {
6609
 
    return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node));
6610
 
}
6611
 
static float __synctex_node_visible_width(synctex_node_p node) {
6612
 
    return SYNCTEX_VISIBLE_SIZE(node,synctex_node_width(node));
6613
 
}
6614
 
static float __synctex_node_visible_height(synctex_node_p node) {
6615
 
    return SYNCTEX_VISIBLE_SIZE(node,synctex_node_height(node));
6616
 
}
6617
 
static float __synctex_node_visible_depth(synctex_node_p node) {
6618
 
    return SYNCTEX_VISIBLE_SIZE(node,synctex_node_depth(node));
6619
 
}
6620
 
static float __synctex_proxy_visible_h(synctex_node_p node) {
6621
 
    return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node));
6622
 
}
6623
 
static float __synctex_proxy_visible_v(synctex_node_p node) {
6624
 
    return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node));
6625
 
}
6626
 
static float __synctex_proxy_visible_width(synctex_node_p node) {
6627
 
    synctex_node_p target = _synctex_tree_target(node);
6628
 
    return __synctex_node_visible_width(target);
6629
 
}
6630
 
static float __synctex_proxy_visible_height(synctex_node_p node) {
6631
 
    synctex_node_p target = _synctex_tree_target(node);
6632
 
    return __synctex_node_visible_height(target);
6633
 
}
6634
 
static float __synctex_proxy_visible_depth(synctex_node_p node) {
6635
 
    synctex_node_p target = _synctex_tree_target(node);
6636
 
    return __synctex_node_visible_depth(target);
6637
 
}
6638
 
static float __synctex_kern_visible_h(synctex_noxy_p noxy) {
6639
 
    int h = _synctex_data_h(noxy);
6640
 
    int width = _synctex_data_width(noxy);
6641
 
    return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width>0?h-width:h);
6642
 
}
6643
 
static float __synctex_kern_visible_width(synctex_noxy_p noxy) {
6644
 
    int width = _synctex_data_width(noxy);
6645
 
    return SYNCTEX_VISIBLE_SIZE(noxy, width>0?width:-width);
6646
 
}
6647
 
static float __synctex_rule_visible_h(synctex_noxy_p noxy) {
6648
 
    int h = _synctex_data_h(noxy);
6649
 
    int width = _synctex_data_width(noxy);
6650
 
    return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width>0?h:h-width);
6651
 
}
6652
 
static float __synctex_rule_visible_width(synctex_noxy_p noxy) {
6653
 
    int width = _synctex_data_width(noxy);
6654
 
    return SYNCTEX_VISIBLE_SIZE(noxy, width>0?width:-width);
6655
 
}
6656
 
static float __synctex_rule_visible_v(synctex_noxy_p noxy) {
6657
 
    return __synctex_node_visible_v(noxy);
6658
 
}
6659
 
static float __synctex_rule_visible_height(synctex_noxy_p noxy) {
6660
 
    return __synctex_node_visible_height(noxy);
6661
 
}
6662
 
static float __synctex_rule_visible_depth(synctex_noxy_p noxy) {
6663
 
    return __synctex_node_visible_depth(noxy);
6664
 
}
6665
 
 
6666
 
/**
6667
 
 *  The horizontal location of node, in page coordinates.
6668
 
 *  - parameter node: a node.
6669
 
 *  - returns: a float.
6670
 
 *  - author: JL
6671
 
 */
6672
 
float synctex_node_visible_h(synctex_node_p node){
6673
 
    return node? node->class_->vispector->h(node): 0;
6674
 
}
6675
 
/**
6676
 
 *  The vertical location of node, in page coordinates.
6677
 
 *  - parameter node: a node.
6678
 
 *  - returns: a float.
6679
 
 *  - author: JL
6680
 
 */
6681
 
float synctex_node_visible_v(synctex_node_p node){
6682
 
    return node? node->class_->vispector->v(node): 0;
6683
 
}
6684
 
/**
6685
 
 *  The width of node, in page coordinates.
6686
 
 *  - parameter node: a node.
6687
 
 *  - returns: a float.
6688
 
 *  - author: JL
6689
 
 */
6690
 
float synctex_node_visible_width(synctex_node_p node){
6691
 
    return node? node->class_->vispector->width(node): 0;
6692
 
}
6693
 
/**
6694
 
 *  The height of node, in page coordinates.
6695
 
 *  - parameter node: a node.
6696
 
 *  - returns: a float.
6697
 
 *  - author: JL
6698
 
 */
6699
 
float synctex_node_visible_height(synctex_node_p node){
6700
 
    return node? node->class_->vispector->height(node): 0;
6701
 
}
6702
 
/**
6703
 
 *  The depth of node, in page coordinates.
6704
 
 *  - parameter node: a node.
6705
 
 *  - returns: a float.
6706
 
 *  - author: JL
6707
 
 */
6708
 
float synctex_node_visible_depth(synctex_node_p node){
6709
 
    return node? node->class_->vispector->depth(node): 0;
6710
 
}
6711
 
 
6712
 
/**
6713
 
 *  The V variant of geometrical information.
6714
 
 *  - parameter node: a node.
6715
 
 *  - returns: an integer.
6716
 
 *  - author: JL
6717
 
 */
6718
 
#define SYNCTEX_DEFINE_V(WHAT)\
6719
 
SYNCTEX_INLINE static int _synctex_node_##WHAT##_V(synctex_node_p node) { \
6720
 
    synctex_node_p target = _synctex_tree_target(node); \
6721
 
    if (target) { \
6722
 
        return _synctex_data_##WHAT(node)+_synctex_node_##WHAT##_V(target); \
6723
 
    } else if (_synctex_data_has_##WHAT##_V(node)) { \
6724
 
        return _synctex_data_##WHAT##_V(node); \
6725
 
    } else { \
6726
 
        return _synctex_data_##WHAT(node); \
6727
 
    } \
6728
 
}
6729
 
SYNCTEX_DEFINE_V(h)
6730
 
SYNCTEX_DEFINE_V(v)
6731
 
SYNCTEX_DEFINE_V(width)
6732
 
SYNCTEX_DEFINE_V(height)
6733
 
SYNCTEX_DEFINE_V(depth)
6734
 
 
6735
 
SYNCTEX_INLINE static synctex_point_s _synctex_data_point(synctex_node_p node) {
6736
 
    return (synctex_point_s){synctex_node_h(node),synctex_node_v(node)};
6737
 
}
6738
 
SYNCTEX_INLINE static synctex_point_s _synctex_data_point_V(synctex_node_p node) {
6739
 
    return (synctex_point_s){_synctex_node_h_V(node),_synctex_node_v_V(node)};
6740
 
}
6741
 
SYNCTEX_INLINE static synctex_point_s _synctex_data_set_point(synctex_node_p node, synctex_point_s point) {
6742
 
    synctex_point_s old = _synctex_data_point(node);
6743
 
    _synctex_data_set_h(node,point.h);
6744
 
    _synctex_data_set_v(node,point.v);
6745
 
    return old;
6746
 
}
6747
 
SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node) {
6748
 
    synctex_box_s box = {{0,0},{0,0}};
6749
 
    int n;
6750
 
    n = synctex_node_width(node);
6751
 
    if (n<0) {
6752
 
        box.max.h = synctex_node_h(node);
6753
 
        box.min.h = box.max.h + n;
6754
 
    } else {
6755
 
        box.min.h = synctex_node_h(node);
6756
 
        box.max.h = box.min.h + n;
6757
 
    }
6758
 
    n = synctex_node_v(node);
6759
 
    box.min.v = n - synctex_node_height(node);
6760
 
    box.max.v = n + synctex_node_depth(node);
6761
 
    return box;
6762
 
}
6763
 
SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node) {
6764
 
    synctex_box_s box = {{0,0},{0,0}};
6765
 
    int n;
6766
 
    n = synctex_node_width(node);
6767
 
    if (n>0) {
6768
 
        box.max.h = synctex_node_h(node);
6769
 
        box.min.h = box.max.h - n;
6770
 
    } else {
6771
 
        box.min.h = synctex_node_h(node);
6772
 
        box.max.h = box.min.h - n;
6773
 
    }
6774
 
    n = synctex_node_v(node);
6775
 
    box.min.v = n - synctex_node_height(node);
6776
 
    box.max.v = n + synctex_node_depth(node);
6777
 
    return box;
6778
 
}
6779
 
SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node) {
6780
 
    synctex_box_s box = {{0,0},{0,0}};
6781
 
    int n;
6782
 
    n = _synctex_node_width_V(node);
6783
 
    if (n<0) {
6784
 
        box.max.h = _synctex_node_h_V(node);
6785
 
        box.min.h = box.max.h + n;
6786
 
    } else {
6787
 
        box.min.h = _synctex_node_h_V(node);
6788
 
        box.max.h = box.min.h + n;
6789
 
    }
6790
 
    n = _synctex_node_v_V(node);
6791
 
    box.min.v = n - _synctex_node_height_V(node);
6792
 
    box.max.v = n + _synctex_node_depth_V(node);
6793
 
    return box;
6794
 
}
6795
 
 
6796
 
/**
6797
 
 *  The higher box node in the parent hierarchy which
6798
 
 *  mean line number is the one of node ±1.
6799
 
 *  This enclosing box is computed as follows
6800
 
 *  1) get the first hbox in the parent linked list
6801
 
 *  starting at node.
6802
 
 *  If there is none, simply return the parent of node.
6803
 
 *  2) compute the mean line number
6804
 
 *  3) scans up the tree for the higher hbox with
6805
 
 *  the same mean line number, ±1 eventually
6806
 
*  - parameter node: a node.
6807
 
 *  - returns: a (proxy to a) box node.
6808
 
 *  - author: JL
6809
 
 */
6810
 
static synctex_node_p _synctex_node_box_visible(synctex_node_p node) {
6811
 
    if ((node = _synctex_node_or_handle_target(node))) {
6812
 
        int mean = 0;
6813
 
        int bound = 1500000/(node->class_->scanner->pre_magnification/1000.0);
6814
 
        synctex_node_p parent = NULL;
6815
 
        /*  get the first enclosing parent
6816
 
         *  then get the highest enclosing parent with the same mean line ±1 */
6817
 
        node = _synctex_node_or_handle_target(node);
6818
 
        if (!_synctex_node_is_box(node)) {
6819
 
            if ((parent = _synctex_tree_parent(node))) {
6820
 
                node = parent;
6821
 
            } else if ((node = _synctex_tree_target(node))) {
6822
 
                if (!_synctex_node_is_box(node)) {
6823
 
                    if ((parent = _synctex_tree_parent(node))) {
6824
 
                        node = parent;
6825
 
                    } else {
6826
 
                        return NULL;
6827
 
                    }
6828
 
                }
6829
 
            }
6830
 
        }
6831
 
        parent = node;
6832
 
        mean = synctex_node_mean_line(node);
6833
 
        while ((parent = _synctex_tree_parent(parent))) {
6834
 
            if (_synctex_node_is_hbox(parent)) {
6835
 
                if (_synctex_abs(mean-synctex_node_mean_line(parent))>1) {
6836
 
                    return node;
6837
 
                } else if (synctex_node_width(parent)>bound) {
6838
 
                    return parent;
6839
 
                } else if (synctex_node_height(parent)+synctex_node_depth(parent)>bound) {
6840
 
                    return parent;
6841
 
                }
6842
 
                node = parent;
6843
 
            }
6844
 
        }
6845
 
    }
6846
 
    return node;
6847
 
}
6848
 
/**
6849
 
 *  The horizontal location of the first box enclosing node, in page coordinates.
6850
 
 *  - parameter node: a node.
6851
 
 *  - returns: a float.
6852
 
 *  - author: JL
6853
 
 */
6854
 
float synctex_node_box_visible_h(synctex_node_p node) {
6855
 
    return SYNCTEX_VISIBLE_DISTANCE_h(node,_synctex_node_h_V(_synctex_node_box_visible(node)));
6856
 
}
6857
 
/**
6858
 
 *  The vertical location of the first box enclosing node, in page coordinates.
6859
 
 *  - parameter node: a node.
6860
 
 *  - returns: a float.
6861
 
 *  - author: JL
6862
 
 */
6863
 
float synctex_node_box_visible_v(synctex_node_p node) {
6864
 
    return SYNCTEX_VISIBLE_DISTANCE_v(node,_synctex_node_v_V(_synctex_node_box_visible(node)));
6865
 
}
6866
 
/**
6867
 
 *  The width of the first box enclosing node, in page coordinates.
6868
 
 *  - parameter node: a node.
6869
 
 *  - returns: a float.
6870
 
 *  - author: JL
6871
 
 */
6872
 
float synctex_node_box_visible_width(synctex_node_p node) {
6873
 
    return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_width_V(_synctex_node_box_visible(node)));
6874
 
}
6875
 
/**
6876
 
 *  The height of the first box enclosing node, in page coordinates.
6877
 
 *  - parameter node: a node.
6878
 
 *  - returns: a float.
6879
 
 *  - author: JL
6880
 
 */
6881
 
float synctex_node_box_visible_height(synctex_node_p node) {
6882
 
    return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_height_V(_synctex_node_box_visible(node)));
6883
 
}
6884
 
/**
6885
 
 *  The depth of the first box enclosing node, in page coordinates.
6886
 
 *  - parameter node: a node.
6887
 
 *  - returns: a float.
6888
 
 *  - author: JL
6889
 
 */
6890
 
float synctex_node_box_visible_depth(synctex_node_p node) {
6891
 
    return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_depth_V(_synctex_node_box_visible(node)));
 
3249
float synctex_node_visible_h(synctex_node_t node){
 
3250
        if (!node) {
 
3251
                return 0;
 
3252
        }
 
3253
        return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset;
 
3254
}
 
3255
float synctex_node_visible_v(synctex_node_t node){
 
3256
        if (!node) {
 
3257
                return 0;
 
3258
        }
 
3259
        return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset;
 
3260
}
 
3261
float synctex_node_visible_width(synctex_node_t node){
 
3262
        if (!node) {
 
3263
                return 0;
 
3264
        }
 
3265
        return SYNCTEX_WIDTH(node)*node->class->scanner->unit;
 
3266
}
 
3267
float synctex_node_box_visible_h(synctex_node_t node){
 
3268
        if (!node) {
 
3269
                return 0;
 
3270
        }
 
3271
        switch(node->class->type) {
 
3272
                case synctex_node_type_vbox:
 
3273
                case synctex_node_type_void_vbox:
 
3274
                case synctex_node_type_void_hbox:
 
3275
                        return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset;
 
3276
                case synctex_node_type_hbox:
 
3277
result:
 
3278
                        return SYNCTEX_HORIZ_V(node)*node->class->scanner->unit+node->class->scanner->x_offset;
 
3279
        }
 
3280
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3281
                goto result;
 
3282
        }
 
3283
        return 0;
 
3284
}
 
3285
float synctex_node_box_visible_v(synctex_node_t node){
 
3286
        if (!node) {
 
3287
                return 0;
 
3288
        }
 
3289
        switch(node->class->type) {
 
3290
                case synctex_node_type_vbox:
 
3291
                case synctex_node_type_void_vbox:
 
3292
                case synctex_node_type_void_hbox:
 
3293
                        return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset;
 
3294
                case synctex_node_type_hbox:
 
3295
result:
 
3296
                        return SYNCTEX_VERT_V(node)*node->class->scanner->unit+node->class->scanner->y_offset;
 
3297
        }
 
3298
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3299
                goto result;
 
3300
        }
 
3301
        return 0;
 
3302
}
 
3303
float synctex_node_box_visible_width(synctex_node_t node){
 
3304
        if (!node) {
 
3305
                return 0;
 
3306
        }
 
3307
        switch(node->class->type) {
 
3308
                case synctex_node_type_vbox:
 
3309
                case synctex_node_type_void_vbox:
 
3310
                case synctex_node_type_void_hbox:
 
3311
                        return SYNCTEX_WIDTH(node)*node->class->scanner->unit;
 
3312
                case synctex_node_type_hbox:
 
3313
result:
 
3314
                        return SYNCTEX_WIDTH_V(node)*node->class->scanner->unit;
 
3315
        }
 
3316
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3317
                goto result;
 
3318
        }
 
3319
        return 0;
 
3320
}
 
3321
float synctex_node_box_visible_height(synctex_node_t node){
 
3322
        if (!node) {
 
3323
                return 0;
 
3324
        }
 
3325
        switch(node->class->type) {
 
3326
                case synctex_node_type_vbox:
 
3327
                case synctex_node_type_void_vbox:
 
3328
                case synctex_node_type_void_hbox:
 
3329
                        return SYNCTEX_HEIGHT(node)*node->class->scanner->unit;
 
3330
                case synctex_node_type_hbox:
 
3331
result:
 
3332
                        return SYNCTEX_HEIGHT_V(node)*node->class->scanner->unit;
 
3333
        }
 
3334
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3335
                goto result;
 
3336
        }
 
3337
        return 0;
 
3338
}
 
3339
float synctex_node_box_visible_depth(synctex_node_t node){
 
3340
        if (!node) {
 
3341
                return 0;
 
3342
        }
 
3343
        switch(node->class->type) {
 
3344
                case synctex_node_type_vbox:
 
3345
                case synctex_node_type_void_vbox:
 
3346
                case synctex_node_type_void_hbox:
 
3347
                        return SYNCTEX_DEPTH(node)*node->class->scanner->unit;
 
3348
                case synctex_node_type_hbox:
 
3349
result:
 
3350
                        return SYNCTEX_DEPTH_V(node)*node->class->scanner->unit;
 
3351
        }
 
3352
        if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
 
3353
                goto result;
 
3354
        }
 
3355
        return 0;
6892
3356
}
6893
3357
#       ifdef SYNCTEX_NOTHING
6894
3358
#       pragma mark -
6895
3359
#       pragma mark Other public node attributes
6896
3360
#   endif
6897
3361
 
6898
 
/**
6899
 
 *  The page number of the sheet enclosing node.
6900
 
 *  - parameter node: a node.
6901
 
 *  - returns: the page number or -1 if node does not belong to a sheet tree.
6902
 
 *  - note: a proxy target does not belong to a sheet
6903
 
 *      but a form, its page number is always -1.
6904
 
 *  - note: a handles does not belong to a sheet not a form.
6905
 
 *      its page number is -1.
6906
 
 *  - author: JL
6907
 
 */
6908
 
int synctex_node_page(synctex_node_p node){
6909
 
    synctex_node_p parent = NULL;
6910
 
    while((parent = _synctex_tree_parent(node))) {
6911
 
        node = parent;
6912
 
    }
6913
 
    if (synctex_node_type(node) == synctex_node_type_sheet) {
6914
 
        return _synctex_data_page(node);
6915
 
    }
6916
 
    return -1;
6917
 
}
6918
 
/**
6919
 
 *  The page number of the target.
6920
 
 *  - author: JL
6921
 
 */
6922
 
SYNCTEX_INLINE static int _synctex_node_target_page(synctex_node_p node){
6923
 
    return synctex_node_page(_synctex_tree_target(node));
6924
 
}
6925
 
 
6926
 
#if defined (SYNCTEX_USE_CHARINDEX)
6927
 
synctex_charindex_t synctex_node_charindex(synctex_node_p node) {
6928
 
    synctex_node_p target = _synctex_tree_target(node);
6929
 
    return target? SYNCTEX_CHARINDEX(target):(node?SYNCTEX_CHARINDEX(node):0);
6930
 
}
6931
 
#endif
6932
 
 
6933
 
/**
6934
 
 *  The tag of the node.
6935
 
 *  - parameter node: a node.
6936
 
 *  - returns: the tag or -1 if node is NULL.
6937
 
 *  - author: JL
6938
 
 */
6939
 
int synctex_node_tag(synctex_node_p node) {
6940
 
    return node? node->class_->tlcpector->tag(node): -1;
6941
 
}
6942
 
/**
6943
 
 *  The line of the node.
6944
 
 *  - parameter node: a node.
6945
 
 *  - returns: the line or -1 if node is NULL.
6946
 
 *  - author: JL
6947
 
 */
6948
 
int synctex_node_line(synctex_node_p node) {
6949
 
    return node? node->class_->tlcpector->line(node): -1;
6950
 
}
6951
 
/**
6952
 
 *  The column of the node.
6953
 
 *  - parameter node: a node.
6954
 
 *  - returns: the column or -1 if node is NULL.
6955
 
 *  - author: JL
6956
 
 */
6957
 
int synctex_node_column(synctex_node_p node) {
6958
 
    return node? node->class_->tlcpector->column(node): -1;
6959
 
}
6960
 
/**
6961
 
 *  The mean line number of the node.
6962
 
 *  - parameter node: a node.
6963
 
 *  - returns: the mean line or -1 if node is NULL.
6964
 
 *  - author: JL
6965
 
 */
6966
 
int synctex_node_mean_line(synctex_node_p node) {
6967
 
    synctex_node_p other = _synctex_tree_target(node);
6968
 
    if (other) {
6969
 
        node = other;
6970
 
    }
6971
 
    if (_synctex_data_has_mean_line(node)) {
6972
 
        return _synctex_data_mean_line(node);
6973
 
    }
6974
 
    if ((other = synctex_node_parent(node))) {
6975
 
        if (_synctex_data_has_mean_line(other)) {
6976
 
            return _synctex_data_mean_line(other);
6977
 
        }
6978
 
    }
6979
 
    return synctex_node_line(node);
6980
 
}
6981
 
/**
6982
 
 *  The weight of the node.
6983
 
 *  - parameter node: a node.
6984
 
 *  - returns: the weight or -1 if node is NULL.
6985
 
 *  - author: JL
6986
 
 */
6987
 
int synctex_node_weight(synctex_node_p node) {
6988
 
    synctex_node_p target = _synctex_tree_target(node);
6989
 
    if (target) {
6990
 
        node = target;
6991
 
    }
6992
 
    return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1;
6993
 
}
6994
 
/**
6995
 
 *  The number of children of the node.
6996
 
 *  - parameter node: a node.
6997
 
 *  - returns: the count or -1 if node is NULL.
6998
 
 *  - author: JL
6999
 
 */
7000
 
int synctex_node_child_count(synctex_node_p node) {
7001
 
    synctex_node_p target = _synctex_tree_target(node);
7002
 
    if (target) {
7003
 
        node = target;
7004
 
    }
7005
 
    return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1;
7006
 
}
7007
 
#       ifdef SYNCTEX_NOTHING
7008
 
#       pragma mark -
7009
 
#       pragma mark Sheet & Form
7010
 
#   endif
7011
 
 
7012
 
/**
7013
 
 *  The sheet of the scanner with a given page number.
7014
 
 *  - parameter scanner: a scanner.
7015
 
 *  - parameter page: a 1 based page number.
7016
 
 *      If page == 0, returns the first sheet.
7017
 
 *  - returns: a sheet or NULL.
7018
 
 *  - author: JL
7019
 
 */
7020
 
synctex_node_p synctex_sheet(synctex_scanner_p scanner,int page) {
7021
 
    if (scanner) {
7022
 
        synctex_node_p sheet = scanner->sheet;
7023
 
        while(sheet) {
7024
 
            if (page == _synctex_data_page(sheet)) {
7025
 
                return sheet;
7026
 
            }
7027
 
            sheet = __synctex_tree_sibling(sheet);
7028
 
        }
7029
 
        if (page == 0) {
7030
 
            return scanner->sheet;
7031
 
        }
7032
 
    }
7033
 
    return NULL;
7034
 
}
7035
 
/**
7036
 
 *  The form of the scanner with a given tag.
7037
 
 *  - parameter scanner: a scanner.
7038
 
 *  - parameter tag: an integer identifier.
7039
 
 *      If tag == 0, returns the first form.
7040
 
 *  - returns: a form.
7041
 
 *  - author: JL
7042
 
 */
7043
 
synctex_node_p synctex_form(synctex_scanner_p scanner,int tag) {
7044
 
    if (scanner) {
7045
 
        synctex_node_p form = scanner->form;
7046
 
        while(form) {
7047
 
            if (tag == _synctex_data_tag(form)) {
7048
 
                return form;
7049
 
            }
7050
 
            form = __synctex_tree_sibling(form);
7051
 
        }
7052
 
        if (tag == 0) {
7053
 
            return scanner->form;
7054
 
        }
7055
 
    }
7056
 
    return NULL;
7057
 
}
7058
 
 
7059
 
/**
7060
 
 *  The content of the sheet with given page number.
7061
 
 *  - parameter scanner: a scanner.
7062
 
 *  - parameter page: a 1 based page number.
7063
 
 *  - returns: a (vertical) box node.
7064
 
 *  - author: JL
7065
 
 */
7066
 
synctex_node_p synctex_sheet_content(synctex_scanner_p scanner,int page) {
7067
 
    if (scanner) {
7068
 
        return _synctex_tree_child(synctex_sheet(scanner,page));
7069
 
    }
7070
 
    return NULL;
7071
 
}
7072
 
 
7073
 
/**
7074
 
 *  The content of the sheet with given page number.
7075
 
 *  - parameter scanner: a scanner.
7076
 
 *  - parameter tag: an integer identifier.
7077
 
 *  - returns: a box node.
7078
 
 *  - author: JL
7079
 
 */
7080
 
synctex_node_p synctex_form_content(synctex_scanner_p scanner,int tag) {
7081
 
    if (scanner) {
7082
 
        return _synctex_tree_child(synctex_form(scanner,tag));
7083
 
    }
7084
 
    return NULL;
7085
 
}
7086
 
 
7087
 
SYNCTEX_INLINE static synctex_node_p _synctex_scanner_friend(synctex_scanner_p scanner,int i) {
7088
 
    if (i>=0) {
7089
 
        i = _synctex_abs(i)%(scanner->number_of_lists);
7090
 
        return (scanner->lists_of_friends)[i];
7091
 
    }
7092
 
    return NULL;
7093
 
}
7094
 
SYNCTEX_INLINE static synctex_bool_t _synctex_nodes_are_friend(synctex_node_p left, synctex_node_p right) {
7095
 
    return synctex_node_tag(left) == synctex_node_tag(right) && synctex_node_line(left) == synctex_node_line(right);
7096
 
}
7097
 
/**
7098
 
 *  The sibling argument is a parent/child list of nodes of the same page.
7099
 
 */
 
3362
int synctex_node_page(synctex_node_t node){
 
3363
        synctex_node_t parent = NULL;
 
3364
        if (!node) {
 
3365
                return -1;
 
3366
        }
 
3367
        parent = SYNCTEX_PARENT(node);
 
3368
        while(parent) {
 
3369
                node = parent;
 
3370
                parent = SYNCTEX_PARENT(node);
 
3371
        }
 
3372
        if (node->class->type == synctex_node_type_sheet) {
 
3373
                return SYNCTEX_PAGE(node);
 
3374
        }
 
3375
        return -1;
 
3376
}
 
3377
synctex_charindex_t synctex_node_charindex(synctex_node_t node) {
 
3378
        return node?SYNCTEX_CHARINDEX(node):0;
 
3379
}
 
3380
int synctex_node_tag(synctex_node_t node) {
 
3381
        return node?SYNCTEX_TAG(node):-1;
 
3382
}
 
3383
int synctex_node_line(synctex_node_t node) {
 
3384
        return node?SYNCTEX_LINE(node):-1;
 
3385
}
 
3386
int synctex_node_mean_line(synctex_node_t node) {
 
3387
        return node?(node->class->type==synctex_node_type_hbox?SYNCTEX_MEAN_LINE(node):SYNCTEX_LINE(node)):-1;
 
3388
}
 
3389
int synctex_node_child_count(synctex_node_t node) {
 
3390
        return node?(node->class->type==synctex_node_type_hbox?SYNCTEX_NODE_WEIGHT(node):0):-1;
 
3391
}
 
3392
int synctex_node_column(synctex_node_t node) {
 
3393
#       ifdef __DARWIN_UNIX03
 
3394
#       pragma unused(node)
 
3395
#   endif
 
3396
        return -1;
 
3397
}
 
3398
#       ifdef SYNCTEX_NOTHING
 
3399
#       pragma mark -
 
3400
#       pragma mark Sheet
 
3401
#   endif
 
3402
 
 
3403
synctex_node_t synctex_sheet(synctex_scanner_t scanner,int page) {
 
3404
        if (scanner) {
 
3405
                synctex_node_t sheet = scanner->sheet;
 
3406
                while(sheet) {
 
3407
                        if (page == SYNCTEX_PAGE(sheet)) {
 
3408
                                return sheet;
 
3409
                        }
 
3410
                        sheet = SYNCTEX_SIBLING(sheet);
 
3411
                }
 
3412
        }
 
3413
        return NULL;
 
3414
}
 
3415
 
 
3416
synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page) {
 
3417
        if (scanner) {
 
3418
                return SYNCTEX_CHILD(synctex_sheet(scanner,page));
 
3419
        }
 
3420
        return NULL;
 
3421
}
 
3422
 
 
3423
#       ifdef SYNCTEX_NOTHING
 
3424
#       pragma mark -
 
3425
#       pragma mark Query
 
3426
#   endif
 
3427
 
 
3428
synctex_status_t synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column) {
 
3429
#       ifdef __DARWIN_UNIX03
 
3430
#       pragma unused(column)
 
3431
#   endif
 
3432
        int tag = synctex_scanner_get_tag(scanner,name);
 
3433
        size_t size = 0;
 
3434
        int friend_index = 0;
 
3435
        int max_line = 0;
 
3436
        synctex_node_t node = NULL;
 
3437
        if (tag == 0) {
 
3438
                printf("SyncTeX Warning: No tag for %s\n",name);
 
3439
                return -1;
 
3440
        }
 
3441
        free(SYNCTEX_START);
 
3442
        SYNCTEX_CUR = SYNCTEX_END = SYNCTEX_START = NULL;
 
3443
        max_line = line < INT_MAX-scanner->number_of_lists ? line+scanner->number_of_lists:INT_MAX;
 
3444
        while(line<max_line) {
 
3445
                /*  This loop will only be performed once for advanced viewers */
 
3446
                friend_index = (tag+line)%(scanner->number_of_lists);
 
3447
                if ((node = (scanner->lists_of_friends)[friend_index])) {
 
3448
                        do {
 
3449
                                if ((synctex_node_type(node)>=synctex_node_type_boundary)
 
3450
                                        && (tag == SYNCTEX_TAG(node))
 
3451
                                                && (line == SYNCTEX_LINE(node))) {
 
3452
                                        if (SYNCTEX_CUR == SYNCTEX_END) {
 
3453
                                                size += 16;
 
3454
                                                SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *));
 
3455
                                                SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START;
 
3456
                                                SYNCTEX_START = SYNCTEX_END;
 
3457
                                                SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *);
 
3458
                                        }                       
 
3459
                                        *(synctex_node_t *)SYNCTEX_CUR = node;
 
3460
                                        SYNCTEX_CUR += sizeof(synctex_node_t);
 
3461
                                }
 
3462
                        } while ((node = SYNCTEX_FRIEND(node)));
 
3463
                        if (SYNCTEX_START == NULL) {
 
3464
                                /*  We did not find any matching boundary, retry with glue or kern */
 
3465
                                node = (scanner->lists_of_friends)[friend_index];/*  no need to test it again, already done */
 
3466
                                do {
 
3467
                                        if ((synctex_node_type(node)>=synctex_node_type_kern)
 
3468
                                                && (tag == SYNCTEX_TAG(node))
 
3469
                                                        && (line == SYNCTEX_LINE(node))) {
 
3470
                                                if (SYNCTEX_CUR == SYNCTEX_END) {
 
3471
                                                        size += 16;
 
3472
                                                        SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *));
 
3473
                                                        SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START;
 
3474
                                                        SYNCTEX_START = SYNCTEX_END;
 
3475
                                                        SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *);
 
3476
                                                }                       
 
3477
                                                *(synctex_node_t *)SYNCTEX_CUR = node;
 
3478
                                                SYNCTEX_CUR += sizeof(synctex_node_t);
 
3479
                                        }
 
3480
                                } while ((node = SYNCTEX_FRIEND(node)));
 
3481
                                if (SYNCTEX_START == NULL) {
 
3482
                                        /*  We did not find any matching glue or kern, retry with boxes */
 
3483
                                        node = (scanner->lists_of_friends)[friend_index];/*  no need to test it again, already done */
 
3484
                                        do {
 
3485
                                                if ((tag == SYNCTEX_TAG(node))
 
3486
                                                                && (line == SYNCTEX_LINE(node))) {
 
3487
                                                        if (SYNCTEX_CUR == SYNCTEX_END) {
 
3488
                                                                size += 16;
 
3489
                                                                SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *));
 
3490
                                                                SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START;
 
3491
                                                                SYNCTEX_START = SYNCTEX_END;
 
3492
                                                                SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *);
 
3493
                                                        }                       
 
3494
                                                        *(synctex_node_t *)SYNCTEX_CUR = node;
 
3495
                                                        SYNCTEX_CUR += sizeof(synctex_node_t);
 
3496
                                                }
 
3497
                                        } while((node = SYNCTEX_FRIEND(node)));
 
3498
                                }
 
3499
                        }
 
3500
                        SYNCTEX_END = SYNCTEX_CUR;
 
3501
                        /*  Now reverse the order to have nodes in display order, and then keep just a few nodes.
 
3502
             *  Order first the best node. */
 
3503
                        if ((SYNCTEX_START) && (SYNCTEX_END)) {
 
3504
                unsigned int best_match = -1;
 
3505
                unsigned int next_match = -1;
 
3506
                unsigned int best_weight = 0;
 
3507
                synctex_node_t * best_ref   = NULL;
 
3508
                                synctex_node_t * start_ref = (synctex_node_t *)SYNCTEX_START;
 
3509
                                synctex_node_t * end_ref   = (synctex_node_t *)SYNCTEX_END;
 
3510
                                --end_ref;
 
3511
                                while (start_ref < end_ref) {
 
3512
                                        node = *start_ref;
 
3513
                                        *start_ref = *end_ref;
 
3514
                                        *end_ref = node;
 
3515
                                        ++start_ref;
 
3516
                                        --end_ref;
 
3517
                                }
 
3518
                /*  Now reorder the nodes to put first the one which fits best.
 
3519
                 *  The idea is to walk along the list of nodes and pick up the first one
 
3520
                 *  which line info is exactly the mean line of its parent, or at least very close.
 
3521
                 *  Then we choose among all such node the one with the maximum number of child nodes.
 
3522
                 *  Then we switch with the first node.
 
3523
                 */
 
3524
                best_ref = start_ref = (synctex_node_t *)SYNCTEX_START;
 
3525
                node = *start_ref;
 
3526
                best_match = abs(SYNCTEX_LINE(node)-SYNCTEX_MEAN_LINE(SYNCTEX_PARENT(node)));
 
3527
                end_ref = (synctex_node_t *)SYNCTEX_END;
 
3528
                                while (++start_ref<end_ref) {
 
3529
                    synctex_node_t parent = NULL;
 
3530
                                        node = *start_ref;
 
3531
                    parent = SYNCTEX_PARENT(node);
 
3532
                    next_match = abs(SYNCTEX_LINE(node)-SYNCTEX_MEAN_LINE(parent));
 
3533
                    if (next_match < best_match
 
3534
                            || (next_match == best_match && SYNCTEX_NODE_WEIGHT(parent)>best_weight)) {
 
3535
                        best_match = next_match;
 
3536
                        best_ref = start_ref;
 
3537
                        best_weight = SYNCTEX_NODE_WEIGHT(parent);
 
3538
                    }
 
3539
                                }
 
3540
                node = *best_ref;
 
3541
                *best_ref = *(synctex_node_t *)SYNCTEX_START;
 
3542
                *(synctex_node_t *)SYNCTEX_START = node;
 
3543
                                /*  Basically, we keep the first node for each parent.
 
3544
                                 *  More precisely, we keep only nodes that are not children of
 
3545
                                 *  their predecessor's parent. */
 
3546
                                start_ref = (synctex_node_t *)SYNCTEX_START;
 
3547
                                end_ref   = (synctex_node_t *)SYNCTEX_START;
 
3548
next_end:
 
3549
                                end_ref += 1; /*  we allways have start_ref<= end_ref*/
 
3550
                                if (end_ref < (synctex_node_t *)SYNCTEX_END) {
 
3551
                                        node = *end_ref;
 
3552
                                        while ((node = SYNCTEX_PARENT(node))) {
 
3553
                                                if (SYNCTEX_PARENT(*start_ref) == node) {
 
3554
                                                        goto next_end;
 
3555
                                                }
 
3556
                                        }
 
3557
                                        start_ref += 1;
 
3558
                                        *start_ref = *end_ref;
 
3559
                                        goto next_end;
 
3560
                                }
 
3561
                                start_ref += 1;
 
3562
                SYNCTEX_END = (char *)start_ref;
 
3563
                SYNCTEX_CUR = NULL;// added on behalf of Jose Alliste
 
3564
                                return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);// added on behalf Jan Sundermeyer
 
3565
            }
 
3566
                        SYNCTEX_CUR = NULL;
 
3567
                        // return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); removed on behalf Jan Sundermeyer
 
3568
                }
 
3569
#       if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__)
 
3570
                break;
 
3571
#       else
 
3572
                ++line;
 
3573
#       endif
 
3574
        }
 
3575
        return 0;
 
3576
}
 
3577
 
 
3578
synctex_node_t synctex_next_result(synctex_scanner_t scanner) {
 
3579
        if (NULL == SYNCTEX_CUR) {
 
3580
                SYNCTEX_CUR = SYNCTEX_START;
 
3581
        } else {
 
3582
                SYNCTEX_CUR+=sizeof(synctex_node_t);
 
3583
        }
 
3584
        if (SYNCTEX_CUR<SYNCTEX_END) {
 
3585
                return *(synctex_node_t*)SYNCTEX_CUR;
 
3586
        } else {
 
3587
                return NULL;
 
3588
        }
 
3589
}
 
3590
 
 
3591
/*  This struct records a point in TeX coordinates.*/
7100
3592
typedef struct {
7101
 
    int count;
7102
 
    synctex_node_p node;
7103
 
} synctex_counted_node_s;
7104
 
 
7105
 
SYNCTEX_INLINE static synctex_counted_node_s _synctex_vertically_sorted_v2(synctex_node_p sibling) {
7106
 
    /* Clean the weights of the parents */
7107
 
    synctex_counted_node_s result = {0, NULL};
7108
 
    synctex_node_p h = NULL;
7109
 
    synctex_node_p next_h = NULL;
7110
 
    synctex_node_p parent = NULL;
7111
 
    int weight = 0;
7112
 
    synctex_node_p N = NULL;
7113
 
    h = sibling;
7114
 
    do {
7115
 
        N = _synctex_tree_target(h);
7116
 
        parent = _synctex_tree_parent(N);
7117
 
        _synctex_data_set_weight(parent, 0);
7118
 
    } while((h = _synctex_tree_child(h)));
7119
 
    /* Compute the weights of the nodes */
7120
 
    h = sibling;
7121
 
    do {
7122
 
        N = _synctex_tree_target(h);
7123
 
        parent = _synctex_tree_parent(N);
7124
 
        weight = _synctex_data_weight(parent);
7125
 
        if (weight==0) {
7126
 
            N = _synctex_tree_child(parent);
7127
 
            do {
7128
 
                if (_synctex_nodes_are_friend(N,sibling)) {
7129
 
                    ++ weight;
7130
 
                }
7131
 
            } while ((N = __synctex_tree_sibling(N)));
7132
 
            _synctex_data_set_weight(h,weight);
7133
 
            _synctex_data_set_weight(parent,weight);
7134
 
        }
7135
 
    } while((h = _synctex_tree_child(h)));
7136
 
    /* Order handle nodes according to the weight */
7137
 
    h = _synctex_tree_reset_child(sibling);
7138
 
    result.node = sibling;
7139
 
    weight = 0;
7140
 
    while((h)) {
7141
 
        N = result.node;
7142
 
        if (_synctex_data_weight(h)>_synctex_data_weight(N)) {
7143
 
            next_h = _synctex_tree_set_child(h,N);
7144
 
            result.node = h;
7145
 
        } else if (_synctex_data_weight(h) == 0) {
7146
 
            ++ weight;
7147
 
            next_h = _synctex_tree_reset_child(h);
7148
 
            synctex_node_free(h);
7149
 
        } else {
7150
 
            synctex_node_p next_N = NULL;
7151
 
            while((next_N = _synctex_tree_child(N))) {
7152
 
                N = next_N;
7153
 
                if (_synctex_data_weight(h)<_synctex_data_weight(next_N)) {
7154
 
                    continue;
7155
 
                }
7156
 
                break;
7157
 
            }
7158
 
            next_h = _synctex_tree_set_child(h,_synctex_tree_set_child(N,h));
7159
 
        }
7160
 
        h = next_h;
7161
 
    };
7162
 
    h = result.node;
7163
 
    weight = 0;
7164
 
    do {
7165
 
        ++weight;
7166
 
    } while((h = _synctex_tree_child(h)));
7167
 
    result.count = 1;
7168
 
    h = result.node;
7169
 
    while((next_h = _synctex_tree_child(h))) {
7170
 
        if (_synctex_data_weight(next_h)==0) {
7171
 
            _synctex_tree_reset_child(h);
7172
 
            weight = 1;
7173
 
            h = next_h;
7174
 
            while((h = _synctex_tree_child(h))) {
7175
 
                ++weight;
7176
 
            }
7177
 
            synctex_node_free(next_h);
7178
 
            break;
7179
 
        }
7180
 
        ++result.count;
7181
 
        h = next_h;
7182
 
    }
7183
 
    return result;
7184
 
}
7185
 
 
7186
 
SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hitP, synctex_node_p node);
7187
 
 
7188
 
/*  This struct records distances, the left one is non negative and the right one is non positive.
 
3593
        int h;
 
3594
        int v;
 
3595
} synctex_point_t;
 
3596
 
 
3597
/*  This struct records distances, the left one is positive or 0 and the right one is negative or 0.
7189
3598
 *  When comparing the locations of 2 different graphical objects on the page, we will have to also record the
7190
3599
 *  horizontal distance as signed to keep track of the typesetting order.*/
7191
 
 
7192
 
typedef struct {
7193
 
    synctex_node_p node;
7194
 
    int distance;
7195
 
} synctex_nd_s;
7196
 
 
7197
 
#define SYNCTEX_ND_0 (synctex_nd_s){NULL,INT_MAX}
7198
 
 
7199
 
typedef synctex_nd_s * synctex_nd_p;
7200
 
 
7201
 
typedef struct {
7202
 
    synctex_nd_s l;
7203
 
    synctex_nd_s r;
7204
 
} synctex_nd_lr_s;
 
3600
typedef struct {
 
3601
        int left;
 
3602
        int right;
 
3603
} synctex_distances_t;
 
3604
 
 
3605
typedef struct {
 
3606
        synctex_point_t left;
 
3607
        synctex_point_t right;
 
3608
} synctex_offsets_t;
 
3609
 
 
3610
 
 
3611
typedef struct {
 
3612
        synctex_node_t left;
 
3613
        synctex_node_t right;
 
3614
} synctex_node_set_t;
 
3615
 
 
3616
/*  The smallest container between two has the smallest width or height.
 
3617
 *  This comparison is used when there are 2 overlapping boxes that contain the hit point.
 
3618
 *  For ConTeXt, the problem appears at each page.
 
3619
 *  The chosen box is the one with the smallest height, then the smallest width. */
 
3620
SYNCTEX_INLINE static synctex_node_t _synctex_smallest_container(synctex_node_t node, synctex_node_t other_node);
 
3621
 
 
3622
/*  Returns the distance between the hit point hitPoint=(H,V) and the given node. */
 
3623
synctex_bool_t _synctex_point_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible);
 
3624
int _synctex_node_distance_to_point(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible);
7205
3625
 
7206
3626
/*  The best container is the deeper box that contains the hit point (H,V).
7207
 
 *  _synctex_eq_deepest_container_v2 starts with node whereas
 
3627
 *  _synctex_eq_deepest_container starts with node whereas
7208
3628
 *  _synctex_box_child_deepest starts with node's children, if any
7209
3629
 *  if node is not a box, or a void box, NULL is returned.
7210
3630
 *  We traverse the node tree in a deep first manner and stop as soon as a result is found. */
7211
 
static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hitP, synctex_node_p node);
7212
 
 
7213
 
SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node);
7214
 
 
7215
 
/*  Closest child, recursive.  */
7216
 
static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node);
7217
 
 
7218
 
/*  The smallest container between two has the smallest width or height.
7219
 
 *  This comparison is used when there are 2 overlapping boxes that contain the hit point.
7220
 
 *  For ConTeXt, the problem appears at each page.
7221
 
 *  The chosen box is the one with the smallest height, then the smallest width. */
7222
 
SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node);
7223
 
 
7224
 
/*  Returns the distance between the hit point hit point=(H,V) and the given node. */
7225
 
 
7226
 
static int _synctex_point_node_distance_v2(synctex_point_p hitP, synctex_node_p node);
 
3631
static synctex_node_t _synctex_eq_deepest_container(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible);
 
3632
 
 
3633
/*  Once a best container is found, the closest children are the closest nodes to the left or right of the hit point.
 
3634
 *  Only horizontal and vertical offsets are used to compare the positions of the nodes. */
 
3635
SYNCTEX_INLINE static int _synctex_eq_get_closest_children_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t*  bestNodesRef,synctex_distances_t*  bestDistancesRef, synctex_bool_t visible);
7227
3636
 
7228
3637
/*  The closest container is the box that is the one closest to the given point.
7229
3638
 *  The "visible" version takes into account the visible dimensions instead of the real ones given by TeX. */
7230
 
static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node);
7231
 
 
7232
 
#       ifdef SYNCTEX_NOTHING
7233
 
#       pragma mark -
7234
 
#       pragma mark Queries
7235
 
#   endif
7236
 
 
7237
 
/**
7238
 
 *  iterator for a deep first tree traversal.
7239
 
 */
7240
 
struct synctex_iterator_t {
7241
 
    synctex_node_p seed;
7242
 
    synctex_node_p top;
7243
 
    synctex_node_p next;
7244
 
    int count0;
7245
 
    int count;
7246
 
};
7247
 
 
7248
 
SYNCTEX_INLINE static synctex_iterator_p _synctex_iterator_new(synctex_node_p result, int count) {
7249
 
    synctex_iterator_p iterator;
7250
 
    if ((iterator = _synctex_malloc(sizeof(synctex_iterator_s)))) {
7251
 
        iterator->seed = iterator->top = iterator->next = result;
7252
 
        iterator->count0 = iterator->count = count;
7253
 
    }
7254
 
    return iterator;
7255
 
};
7256
 
 
7257
 
void synctex_iterator_free(synctex_iterator_p iterator) {
7258
 
    if (iterator) {
7259
 
        synctex_node_free(iterator->seed);
7260
 
        _synctex_free(iterator);
7261
 
    }
7262
 
}
7263
 
synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator) {
7264
 
    return iterator?iterator->count>0:0;
7265
 
}
7266
 
int synctex_iterator_count(synctex_iterator_p iterator) {
7267
 
    return iterator? iterator->count: 0;
7268
 
}
7269
 
 
7270
 
/**
7271
 
 *  The next result of the iterator.
7272
 
 *  Internally, the iterator stores handles to nodes.
7273
 
 *  Externally, it returns the targets,
7274
 
 *  such that the caller only sees nodes.
7275
 
 */
7276
 
synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator) {
7277
 
    if (iterator && iterator->count>0) {
7278
 
        synctex_node_p N = iterator->next;
7279
 
        if(!(iterator->next = _synctex_tree_child(N))) {
7280
 
            iterator->next = iterator->top = __synctex_tree_sibling(iterator->top);
7281
 
        }
7282
 
        --iterator->count;
7283
 
        return _synctex_tree_target(N);
7284
 
    }
7285
 
    return NULL;
7286
 
}
7287
 
int synctex_iterator_reset(synctex_iterator_p iterator) {
7288
 
    if (iterator) {
7289
 
        iterator->next = iterator->top = iterator->seed;
7290
 
        return iterator->count = iterator->count0;
7291
 
    }
7292
 
    return 0;
7293
 
}
7294
 
 
7295
 
synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner,int page,float h,float v){
7296
 
    if (scanner) {
7297
 
        synctex_node_p sheet = NULL;
7298
 
        synctex_point_s hit;
7299
 
        synctex_node_p node = NULL;
7300
 
        synctex_nd_lr_s nds = {{NULL,0},{NULL,0}};
7301
 
        if (NULL == (scanner = synctex_scanner_parse(scanner)) || 0 >= scanner->unit) {/*  scanner->unit must be >0 */
7302
 
            return NULL;
7303
 
        }
7304
 
        /*  Find the proper sheet */
7305
 
        sheet = synctex_sheet(scanner,page);
7306
 
        if (NULL == sheet) {
7307
 
            return NULL;
7308
 
        }
7309
 
        /*  Now sheet points to the sheet node with proper page number. */
7310
 
        /*  Now that scanner has been initialized, we can convert
7311
 
         *  the given point to scanner integer coordinates */
7312
 
        hit = (synctex_point_s)
7313
 
        {(h-scanner->x_offset)/scanner->unit,
7314
 
            (v-scanner->y_offset)/scanner->unit};
7315
 
        /*  At first, we browse all the horizontal boxes of the sheet
7316
 
         *  until we find one containing the hit point. */
7317
 
        if ((node = _synctex_tree_next_hbox(sheet))) {
7318
 
            do {
7319
 
                if (_synctex_point_in_box_v2(&hit,node)) {
7320
 
                    /*  Maybe the hit point belongs to a contained vertical box.
7321
 
                     *  This is the most likely situation.
7322
 
                     */
7323
 
                    synctex_node_p next = node;
7324
 
#if defined(SYNCTEX_DEBUG)
7325
 
                    printf("--- We are lucky\n");
7326
 
#endif
7327
 
                    /*  This trick is for catching overlapping boxes */
7328
 
                    while ((next = _synctex_tree_next_hbox(next))) {
7329
 
                        if (_synctex_point_in_box_v2(&hit,next)) {
7330
 
                            node = _synctex_smallest_container_v2(next,node);
7331
 
                        }
7332
 
                    }
7333
 
                    /*  node is the smallest horizontal box that contains hit,
7334
 
                     *  unless there is no hbox at all.
7335
 
                     */
7336
 
                    node = _synctex_eq_deepest_container_v2(&hit, node);
7337
 
                    nds = _synctex_eq_get_closest_children_in_box_v2(&hit, node);
7338
 
                end:
7339
 
                    if (nds.r.node && nds.l.node) {
7340
 
                        if ((_synctex_data_tag(nds.r.node)!=_synctex_data_tag(nds.l.node))
7341
 
                            || (_synctex_data_line(nds.r.node)!=_synctex_data_line(nds.l.node))
7342
 
                            || (_synctex_data_column(nds.r.node)!=_synctex_data_column(nds.l.node))) {
7343
 
                            if (_synctex_data_line(nds.r.node)<_synctex_data_line(nds.l.node)) {
7344
 
                                node = nds.r.node;
7345
 
                                nds.r.node = nds.l.node;
7346
 
                                nds.l.node = node;
7347
 
                            } else if (_synctex_data_line(nds.r.node)==_synctex_data_line(nds.l.node)) {
7348
 
                                if (nds.l.distance>nds.r.distance) {
7349
 
                                    node = nds.r.node;
7350
 
                                    nds.r.node = nds.l.node;
7351
 
                                    nds.l.node = node;
7352
 
                                }
7353
 
                            }
7354
 
                            if((node = _synctex_new_handle_with_target(nds.l.node))) {
7355
 
                                synctex_node_p other_handle;
7356
 
                                if((other_handle = _synctex_new_handle_with_target(nds.r.node))) {
7357
 
                                    _synctex_tree_set_sibling(node,other_handle);
7358
 
                                    return _synctex_iterator_new(node,2);
7359
 
                                }
7360
 
                                return _synctex_iterator_new(node,1);
7361
 
                            }
7362
 
                            return NULL;
7363
 
                        }
7364
 
                        /*  both nodes have the same input coordinates
7365
 
                         *  We choose the one closest to the hit point  */
7366
 
                        if (nds.l.distance>nds.r.distance) {
7367
 
                            nds.l.node = nds.r.node;
7368
 
                        }
7369
 
                        nds.r.node = NULL;
7370
 
                    } else if (nds.r.node) {
7371
 
                        nds.l = nds.r;
7372
 
                    } else if (!nds.l.node) {
7373
 
                        nds.l.node = node;
7374
 
                    }
7375
 
                    if((node = _synctex_new_handle_with_target(nds.l.node))) {
7376
 
                        return _synctex_iterator_new(node,1);
7377
 
                    }
7378
 
                    return 0;
7379
 
                }
7380
 
            } while ((node = _synctex_tree_next_hbox(node)));
7381
 
            /*  All the horizontal boxes have been tested,
7382
 
             *  None of them contains the hit point.
7383
 
             */
7384
 
        }
7385
 
        /*  We are not lucky,
7386
 
         *  we test absolutely all the node
7387
 
         *  to find the closest... */
7388
 
        if ((node = _synctex_tree_child(sheet))) {
7389
 
#if defined(SYNCTEX_DEBUG)
7390
 
            printf("--- We are not lucky\n");
7391
 
#endif
7392
 
            nds.l = __synctex_closest_deep_child_v2(&hit, node);
7393
 
#if defined(SYNCTEX_DEBUG)
7394
 
            printf("Edit query best: %i\n", nds.l.distance);
7395
 
#endif
7396
 
            goto end;
7397
 
        }
7398
 
    }
7399
 
    return NULL;
7400
 
}
7401
 
 
7402
 
/**
7403
 
 *  Loop the candidate friendly list to find the ones with the proper
7404
 
 *  tag and line.
7405
 
 *  Returns a tree of results targeting the found candidates.
7406
 
 *  At the top level each sibling has its own page number.
7407
 
 *  All the results with the same page number are linked by child/parent entry.
7408
 
 *  - parameter candidate: a friendly list of candidates
7409
 
 */
7410
 
static synctex_node_p _synctex_display_query_v2(synctex_node_p target, int tag, int line, synctex_bool_t exclude_box) {
7411
 
    synctex_node_p first_handle = NULL;
7412
 
    /*  Search the first match */
7413
 
    if (target == NULL) {
7414
 
        return first_handle;
7415
 
    }
7416
 
    do {
7417
 
        int page;
7418
 
        if ((exclude_box
7419
 
             && _synctex_node_is_box(target))
7420
 
            || (tag != synctex_node_tag(target))
7421
 
            || (line != synctex_node_line(target))) {
7422
 
            continue;
7423
 
        }
7424
 
        /*  We found a first match, create
7425
 
         *  a result handle targeting that candidate. */
7426
 
        first_handle = _synctex_new_handle_with_target(target);
7427
 
        if (first_handle == NULL) {
7428
 
            return first_handle;
7429
 
        }
7430
 
        /*  target is either a node,
7431
 
         *  or a proxy to some node, in which case,
7432
 
         *  the target's target belongs to a form,
7433
 
         *  not a sheet. */
7434
 
        page = synctex_node_page(target);
7435
 
        /*  Now create all the other results  */
7436
 
        while ((target = _synctex_tree_friend(target))) {
7437
 
            synctex_node_p result = NULL;
7438
 
            if ((exclude_box
7439
 
                 && _synctex_node_is_box(target))
7440
 
                || (tag != synctex_node_tag(target))
7441
 
                || (line != synctex_node_line(target))) {
7442
 
                continue;
7443
 
            }
7444
 
            /*  Another match, same page number ? */
7445
 
            result = _synctex_new_handle_with_target(target);
7446
 
            if (NULL == result ) {
7447
 
                return first_handle;
7448
 
            }
7449
 
            /*  is it the same page number ? */
7450
 
            if (synctex_node_page(target) == page) {
7451
 
                __synctex_tree_set_child(result, first_handle);
7452
 
                first_handle = result;
7453
 
            } else {
7454
 
                /*  We have 2 page numbers involved */
7455
 
                __synctex_tree_set_sibling(first_handle, result);
7456
 
                while ((target = _synctex_tree_friend(target))) {
7457
 
                    synctex_node_p same_page_node;
7458
 
                    if ((exclude_box
7459
 
                         && _synctex_node_is_box(target))
7460
 
                        || (tag != synctex_node_tag(target))
7461
 
                        || (line != synctex_node_line(target))) {
7462
 
                        continue;
7463
 
                    }
7464
 
                    /*  New match found, which page? */
7465
 
                    result = _synctex_new_handle_with_target(target);
7466
 
                    if (NULL == result) {
7467
 
                        return first_handle;
7468
 
                    }
7469
 
                    same_page_node = first_handle;
7470
 
                    page = synctex_node_page(target);
7471
 
                    /*  Find a result with the same page number */;
7472
 
                    do {
7473
 
                        if (_synctex_node_target_page(same_page_node) == page) {
7474
 
                            /* Insert result between same_page_node and its child */
7475
 
                            _synctex_tree_set_child(result,_synctex_tree_set_child(same_page_node,result));
7476
 
                        } else if ((same_page_node = __synctex_tree_sibling(same_page_node))) {
7477
 
                            continue;
7478
 
                        } else {
7479
 
                            /*  This is a new page number */
7480
 
                            __synctex_tree_set_sibling(result,first_handle);
7481
 
                            first_handle = result;
7482
 
                        }
7483
 
                        break;
7484
 
                    } while (synctex_YES);
7485
 
                }
7486
 
                return first_handle;
7487
 
            }
7488
 
        }
7489
 
    } while ((target = _synctex_tree_friend(target)));
7490
 
    return first_handle;
7491
 
}
7492
 
synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) {
7493
 
    SYNCTEX_UNUSED(column)
7494
 
    if (scanner) {
7495
 
        int tag = synctex_scanner_get_tag(scanner,name);/* parse if necessary */
7496
 
        int max_line = 0;
7497
 
        int line_offset = 1;
7498
 
        int try_count = 100;
7499
 
        synctex_node_p node = NULL;
7500
 
        synctex_node_p result = NULL;
7501
 
        if (tag == 0) {
7502
 
            printf("SyncTeX Warning: No tag for %s\n",name);
7503
 
            return NULL;
7504
 
        }
7505
 
        node = synctex_scanner_input_with_tag(scanner, tag);
7506
 
        max_line = _synctex_data_line(node);
7507
 
        /*  node = NULL; */
7508
 
        if (line>max_line) {
7509
 
            line = max_line;
7510
 
        }
7511
 
        while(try_count--) {
7512
 
            if (line<=max_line) {
7513
 
                /*  This loop will only be performed once for advanced viewers */
7514
 
                synctex_node_p friend = _synctex_scanner_friend(scanner,tag+line);
7515
 
                if ((node = friend)) {
7516
 
                    result = _synctex_display_query_v2(node,tag,line,synctex_YES);
7517
 
                    if (!result) {
7518
 
                        /*  We did not find any matching boundary, retry including boxes */
7519
 
                        node = friend;/*  no need to test it again, already done */
7520
 
                        result = _synctex_display_query_v2(node,tag,line,synctex_NO);
7521
 
                    }
7522
 
                    /*  Now reverse the order to have nodes in display order, and then keep just a few nodes.
7523
 
                     *  Order first the best node. */
7524
 
                    /*  The result is a tree. At the root level, all nodes
7525
 
                     *  correspond to different page numbers.
7526
 
                     *  Each node has a child which corresponds to the same
7527
 
                     *  page number if relevant.
7528
 
                     *  Then reorder the nodes to put first the one which fits best.
7529
 
                     *  The idea is to count the number of nodes
7530
 
                     *  with the same tag and line number in the parents
7531
 
                     *  and choose the ones with the biggest count.
7532
 
                     */
7533
 
                    if (result) {
7534
 
                        /*  navigate through siblings, then children   */
7535
 
                        synctex_node_p next_sibling = __synctex_tree_reset_sibling(result);
7536
 
                        int best_match = abs(page_hint-_synctex_node_target_page(result));
7537
 
                        synctex_node_p sibling;
7538
 
                        int match;
7539
 
                        synctex_counted_node_s cn = _synctex_vertically_sorted_v2(result);
7540
 
                        int count = cn.count;
7541
 
                        result = cn.node;
7542
 
                        while((sibling = next_sibling)) {
7543
 
                            /* What is next? Do not miss that step! */
7544
 
                            next_sibling = __synctex_tree_reset_sibling(sibling);
7545
 
                            cn = _synctex_vertically_sorted_v2(sibling);
7546
 
                            count += cn.count;
7547
 
                            sibling = cn.node;
7548
 
                            match = abs(page_hint-_synctex_node_target_page(sibling));
7549
 
                            if (match<best_match) {
7550
 
                                /*  Order this node first */
7551
 
                                __synctex_tree_set_sibling(sibling,result);
7552
 
                                result = sibling;
7553
 
                                best_match = match;
7554
 
                            } else /*if (match>=best_match)*/ {
7555
 
                                __synctex_tree_set_sibling(sibling,__synctex_tree_sibling(result));
7556
 
                                __synctex_tree_set_sibling(result,sibling);
7557
 
                            }
7558
 
                        }
7559
 
                        return _synctex_iterator_new(result,count);
7560
 
                    }
7561
 
                }
7562
 
#       if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__)
7563
 
                break;
7564
 
#       else
7565
 
                line += line_offset;
7566
 
                line_offset=line_offset<0?-(line_offset-1):-(line_offset+1);
7567
 
                if (line <= 0) {
7568
 
                    line += line_offset;
7569
 
                    line_offset=line_offset<0?-(line_offset-1):-(line_offset+1);
7570
 
                }
7571
 
#       endif
7572
 
            }
7573
 
        }
7574
 
    }
7575
 
    return NULL;
7576
 
}
7577
 
synctex_status_t synctex_display_query(synctex_scanner_p scanner,const char *  name,int line,int column, int page_hint) {
7578
 
    if (scanner) {
7579
 
        synctex_iterator_free(scanner->iterator);
7580
 
        scanner->iterator = synctex_iterator_new_display(scanner, name,line,column, page_hint);
7581
 
        return synctex_iterator_count(scanner->iterator);
7582
 
    }
7583
 
    return SYNCTEX_STATUS_ERROR;
7584
 
}
7585
 
synctex_status_t synctex_edit_query(synctex_scanner_p scanner,int page,float h,float v) {
7586
 
    if (scanner) {
7587
 
        synctex_iterator_free(scanner->iterator);
7588
 
        scanner->iterator = synctex_iterator_new_edit(scanner, page, h, v);
7589
 
        return synctex_iterator_count(scanner->iterator);
7590
 
    }
7591
 
    return SYNCTEX_STATUS_ERROR;
7592
 
}
7593
 
/**
7594
 
 *  The next result of a query.
7595
 
 */
7596
 
synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner) {
7597
 
    return scanner? synctex_iterator_next_result(scanner->iterator): NULL;
7598
 
}
7599
 
synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner) {
7600
 
    return scanner? synctex_iterator_reset(scanner->iterator): SYNCTEX_STATUS_ERROR;
7601
 
}
7602
 
 
7603
 
synctex_node_p synctex_node_target(synctex_node_p node) {
7604
 
    return _synctex_tree_target(node);
7605
 
}
7606
 
 
7607
 
#       ifdef SYNCTEX_NOTHING
7608
 
#       pragma mark -
7609
 
#       pragma mark Geometric utilities
7610
 
#   endif
7611
 
 
7612
 
/** Rougly speaking, this is:
7613
 
 *  node's h coordinate - hit point's h coordinate.
 
3639
SYNCTEX_INLINE static synctex_node_t _synctex_eq_closest_child(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible);
 
3640
 
 
3641
#define SYNCTEX_MASK_LEFT 1
 
3642
#define SYNCTEX_MASK_RIGHT 2
 
3643
 
 
3644
synctex_status_t synctex_edit_query(synctex_scanner_t scanner,int page,float h,float v) {
 
3645
        synctex_node_t sheet = NULL;
 
3646
        synctex_node_t node = NULL; /*  placeholder */
 
3647
        synctex_node_t other_node = NULL; /*  placeholder */
 
3648
        synctex_point_t hitPoint = {0,0}; /*  placeholder */
 
3649
        synctex_node_set_t bestNodes = {NULL,NULL}; /*  holds the best node */
 
3650
        synctex_distances_t bestDistances = {INT_MAX,INT_MAX}; /*  holds the best distances for the best node */
 
3651
        synctex_node_t bestContainer = NULL; /*  placeholder */
 
3652
        if (NULL == (scanner = synctex_scanner_parse(scanner)) || 0 >= scanner->unit) {/*  scanner->unit must be >0 */
 
3653
                return 0;
 
3654
        }
 
3655
        /*  Convert the given point to scanner integer coordinates */
 
3656
        hitPoint.h = (h-scanner->x_offset)/scanner->unit;
 
3657
        hitPoint.v = (v-scanner->y_offset)/scanner->unit;
 
3658
        /*  We will store in the scanner's buffer the result of the query. */
 
3659
        free(SYNCTEX_START);
 
3660
        SYNCTEX_START = SYNCTEX_END = SYNCTEX_CUR = NULL;
 
3661
        /*  Find the proper sheet */
 
3662
        sheet = scanner->sheet;
 
3663
        while((sheet) && SYNCTEX_PAGE(sheet) != page) {
 
3664
                sheet = SYNCTEX_SIBLING(sheet);
 
3665
        }
 
3666
        if (NULL == sheet) {
 
3667
                return -1;
 
3668
        }
 
3669
        /*  Now sheet points to the sheet node with proper page number */
 
3670
        /*  Here is how we work:
 
3671
         *  At first we do not consider the visible box dimensions. This will cover the most frequent cases.
 
3672
         *  Then we try with the visible box dimensions.
 
3673
         *  We try to find a non void box containing the hit point.
 
3674
         *  We browse all the horizontal boxes until we find one containing the hit point. */
 
3675
        if ((node = SYNCTEX_NEXT_hbox(sheet))) {
 
3676
                do {
 
3677
                        if (_synctex_point_in_box(hitPoint,node,synctex_YES)) {
 
3678
                                /*  Maybe the hitPoint belongs to a contained vertical box. */
 
3679
end:
 
3680
                                /*  This trick is for catching overlapping boxes */
 
3681
                                if ((other_node = SYNCTEX_NEXT_hbox(node))) {
 
3682
                                        do {
 
3683
                                                if (_synctex_point_in_box(hitPoint,other_node,synctex_YES)) {
 
3684
                                                        node = _synctex_smallest_container(other_node,node); 
 
3685
                                                }
 
3686
                                        } while((other_node = SYNCTEX_NEXT_hbox(other_node)));
 
3687
                                }
 
3688
                /*  node is the smallest horizontal box that contains hitPoint. */
 
3689
                                if ((bestContainer = _synctex_eq_deepest_container(hitPoint,node,synctex_YES))) {
 
3690
                                        node = bestContainer;
 
3691
                                }
 
3692
                                _synctex_eq_get_closest_children_in_box(hitPoint,node,&bestNodes,&bestDistances,synctex_YES);
 
3693
                                if (bestNodes.right && bestNodes.left) {
 
3694
                                        if ((SYNCTEX_TAG(bestNodes.right)!=SYNCTEX_TAG(bestNodes.left))
 
3695
                                                        || (SYNCTEX_LINE(bestNodes.right)!=SYNCTEX_LINE(bestNodes.left))
 
3696
                                                                || (SYNCTEX_COLUMN(bestNodes.right)!=SYNCTEX_COLUMN(bestNodes.left))) {
 
3697
                                                if ((SYNCTEX_START = malloc(2*sizeof(synctex_node_t)))) {
 
3698
                                                        if (bestDistances.left>bestDistances.right) {
 
3699
                                                                ((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.right;
 
3700
                                                                ((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.left;
 
3701
                                                        } else {
 
3702
                                                                ((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.left;
 
3703
                                                                ((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.right;
 
3704
                                                        }
 
3705
                                                        SYNCTEX_END = SYNCTEX_START + 2*sizeof(synctex_node_t);
 
3706
                                                        SYNCTEX_CUR = NULL;
 
3707
                                                        return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
 
3708
                                                }
 
3709
                                                return SYNCTEX_STATUS_ERROR;
 
3710
                                        }
 
3711
                                        /*  both nodes have the same input coordinates
 
3712
                                         *  We choose the one closest to the hit point  */
 
3713
                                        if (bestDistances.left>bestDistances.right) {
 
3714
                                                bestNodes.left = bestNodes.right;
 
3715
                                        }
 
3716
                                        bestNodes.right = NULL;
 
3717
                                } else if (bestNodes.right) {
 
3718
                                        bestNodes.left = bestNodes.right;
 
3719
                                } else if (!bestNodes.left){
 
3720
                                        bestNodes.left = node;
 
3721
                                }
 
3722
                                if ((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) {
 
3723
                                        * (synctex_node_t *)SYNCTEX_START = bestNodes.left;
 
3724
                                        SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t);
 
3725
                                        SYNCTEX_CUR = NULL;
 
3726
                                        return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
 
3727
                                }
 
3728
                                return SYNCTEX_STATUS_ERROR;
 
3729
                        }
 
3730
                } while ((node = SYNCTEX_NEXT_hbox(node)));
 
3731
                /*  All the horizontal boxes have been tested,
 
3732
                 *  None of them contains the hit point.
 
3733
                 */
 
3734
        }
 
3735
        /*  We are not lucky */
 
3736
        if ((node = SYNCTEX_CHILD(sheet))) {
 
3737
                goto end;
 
3738
        }
 
3739
        return 0;
 
3740
}
 
3741
 
 
3742
#       ifdef SYNCTEX_NOTHING
 
3743
#       pragma mark -
 
3744
#       pragma mark Utilities
 
3745
#   endif
 
3746
 
 
3747
/*  Rougly speaking, this is:
 
3748
 *  node's h coordinate - hitPoint's h coordinate.
7614
3749
 *  If node is to the right of the hit point, then this distance is positive,
7615
 
 *  if node is to the left of the hit point, this distance is negative.
7616
 
 *  If the argument is a pdf form reference, then the child is used and returned instead.
7617
 
 *  Last Revision: Mon Apr 24 07:05:27 UTC 2017
7618
 
 */
7619
 
static synctex_nd_s _synctex_point_h_ordered_distance_v2
7620
 
(synctex_point_p hit, synctex_node_p node) {
7621
 
    synctex_nd_s nd = {node,INT_MAX};
7622
 
    if (node) {
7623
 
        int min,med,max,width;
7624
 
        switch(synctex_node_type(node)) {
7625
 
                /*  The distance between a point and a box is special.
7626
 
                 *  It is not the euclidian distance, nor something similar.
7627
 
                 *  We have to take into account the particular layout,
7628
 
                 *  and the box hierarchy.
7629
 
                 *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
7630
 
                 *  The origin being at the top left corner of the page,
7631
 
                 *  we also give names to the vertices of the box.
7632
 
                 *
7633
 
                 *   1 | 2 | 3
7634
 
                 *  ---A---B--->
7635
 
                 *   4 | 5 | 6
7636
 
                 *  ---C---D--->
7637
 
                 *   7 | 8 | 9
7638
 
                 *     v   v
7639
 
                 */
7640
 
            case synctex_node_type_vbox:
7641
 
            case synctex_node_type_void_vbox:
7642
 
            case synctex_node_type_void_hbox:
7643
 
                /*  getting the box bounds, taking into account negative width, height and depth. */
7644
 
                width = _synctex_data_width(node);
7645
 
                min = _synctex_data_h(node);
7646
 
                max = min + (width>0?width:-width);
7647
 
                /*  We always have min <= max */
7648
 
                if (hit->h<min) {
7649
 
                    nd.distance = min - hit->h; /*  regions 1+4+7, result is > 0 */
7650
 
                } else if (hit->h>max) {
7651
 
                    nd.distance = max - hit->h; /*  regions 3+6+9, result is < 0 */
7652
 
                } else {
7653
 
                    nd.distance = 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
7654
 
                }
7655
 
                break;
7656
 
            case synctex_node_type_proxy_vbox:
7657
 
                /*  getting the box bounds, taking into account negative width, height and depth. */
7658
 
                width = synctex_node_width(node);
7659
 
                min = synctex_node_h(node);
7660
 
                max = min + (width>0?width:-width);
7661
 
                /*  We always have min <= max */
7662
 
                if (hit->h<min) {
7663
 
                    nd.distance = min - hit->h; /*  regions 1+4+7, result is > 0 */
7664
 
                } else if (hit->h>max) {
7665
 
                    nd.distance = max - hit->h; /*  regions 3+6+9, result is < 0 */
7666
 
                } else {
7667
 
                    nd.distance = 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
7668
 
                }
7669
 
                break;
7670
 
            case synctex_node_type_hbox:
7671
 
            case synctex_node_type_proxy_hbox:
7672
 
                /*  getting the box bounds, taking into account negative width, height and depth. */
7673
 
                width = synctex_node_hbox_width(node);
7674
 
                min = synctex_node_hbox_h(node);
7675
 
                max = min + (width>0?width:-width);
7676
 
                /*  We always have min <= max */
7677
 
                if (hit->h<min) {
7678
 
                    nd.distance = min - hit->h; /*  regions 1+4+7, result is > 0 */
7679
 
                } else if (hit->h>max) {
7680
 
                    nd.distance = max - hit->h; /*  regions 3+6+9, result is < 0 */
7681
 
                } else {
7682
 
                    nd.distance = 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
7683
 
                }
7684
 
                break;
7685
 
            case synctex_node_type_kern:
7686
 
                /*  IMPORTANT NOTICE: the location of the kern is recorded AFTER the move.
7687
 
                 *  The distance to the kern is very special,
7688
 
                 *  in general, there is no text material in the kern,
7689
 
                 *  this is why we compute the offset relative to the closest edge of the kern.*/
7690
 
                max = _synctex_data_width(node);
7691
 
                if (max<0) {
7692
 
                    min = _synctex_data_h(node);
7693
 
                    max = min - max;
7694
 
                } else {
7695
 
                    min = -max;
7696
 
                    max = _synctex_data_h(node);
7697
 
                    min += max;
7698
 
                }
7699
 
                med = (min+max)/2;
7700
 
                /*  positive kern: '.' means text, '>' means kern offset
7701
 
                 *      .............
7702
 
                 *                   min>>>>med>>>>max
7703
 
                 *                                    ...............
7704
 
                 *  negative kern: '.' means text, '<' means kern offset
7705
 
                 *      ............................
7706
 
                 *                 min<<<<med<<<<max
7707
 
                 *                 .................................
7708
 
                 *  Actually, we do not take into account negative widths.
7709
 
                 *  There is a problem for such situation when there is effectively overlapping text.
7710
 
                 *  But this should be extremely rare. I guess that in that case, many different choices
7711
 
                 *  could be made, one being in contradiction with the other.
7712
 
                 *  It means that the best choice should be made according to the situation that occurs
7713
 
                 *  most frequently.
7714
 
                 */
7715
 
                if (hit->h<min) {
7716
 
                    nd.distance = min - hit->h + 1; /*  penalty to ensure other nodes are chosen first in case of overlapping ones */
7717
 
                } else if (hit->h>max) {
7718
 
                    nd.distance = max - hit->h - 1; /*  same kind of penalty */
7719
 
                } else if (hit->h>med) {
7720
 
                    /*  do things like if the node had 0 width and was placed at the max edge + 1*/
7721
 
                    nd.distance = max - hit->h + 1; /*  positive, the kern is to the right of the hit point */
7722
 
                } else {
7723
 
                    nd.distance = min - hit->h - 1; /*  negative, the kern is to the left of the hit point */
7724
 
                }
7725
 
                break;
7726
 
            case synctex_node_type_rule:/* to do: special management */
7727
 
            case synctex_node_type_glue:
7728
 
            case synctex_node_type_math:
7729
 
            case synctex_node_type_boundary:
7730
 
            case synctex_node_type_box_bdry:
7731
 
                nd.distance = _synctex_data_h(node) - hit->h;
7732
 
                break;
7733
 
            case synctex_node_type_ref:
7734
 
                nd.node = synctex_node_child(node);
7735
 
                nd = _synctex_point_h_ordered_distance_v2(hit,nd.node);
7736
 
                break;
7737
 
            case synctex_node_type_proxy:
7738
 
            case synctex_node_type_proxy_last:
7739
 
            {
7740
 
                /* shift the hit point to be relative to the proxy origin,
7741
 
                 *  then compute the distance to the target
7742
 
                 */
7743
 
                synctex_point_s otherHit = *hit;
7744
 
                otherHit.h -= _synctex_data_h(node);
7745
 
                otherHit.v -= _synctex_data_v(node);
7746
 
                nd.node = _synctex_tree_target(node);
7747
 
                nd = _synctex_point_h_ordered_distance_v2(&otherHit,nd.node);
7748
 
                nd.node = node;
7749
 
            }
7750
 
            default:
7751
 
                break;
7752
 
        }
7753
 
    }
7754
 
    return nd;
 
3750
 *  if node is to the left of the hit point, this distance is negative.*/
 
3751
int _synctex_point_h_distance(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible);
 
3752
int _synctex_point_h_distance(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) {
 
3753
        if (node) {
 
3754
                int min,med,max;
 
3755
                switch(node->class->type) {
 
3756
                        /*  The distance between a point and a box is special.
 
3757
                         *  It is not the euclidian distance, nor something similar.
 
3758
                         *  We have to take into account the particular layout,
 
3759
                         *  and the box hierarchy.
 
3760
                         *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
 
3761
                         *  The origin being at the top left corner of the page,
 
3762
                         *  we also give names to the vertices of the box.
 
3763
                         *
 
3764
                         *   1 | 2 | 3
 
3765
                         *  ---A---B--->
 
3766
                         *   4 | 5 | 6
 
3767
                         *  ---C---D--->
 
3768
                         *   7 | 8 | 9
 
3769
                         *     v   v
 
3770
                         */
 
3771
                        case synctex_node_type_hbox:
 
3772
                                /*  getting the box bounds, taking into account negative width, height and depth. */
 
3773
                                min = visible?SYNCTEX_HORIZ_V(node):SYNCTEX_HORIZ(node);
 
3774
                                max = min + (visible?SYNCTEX_ABS_WIDTH_V(node):SYNCTEX_ABS_WIDTH(node));
 
3775
                                /*  We allways have min <= max */
 
3776
                                if (hitPoint.h<min) {
 
3777
                                        return min - hitPoint.h; /*  regions 1+4+7, result is > 0 */
 
3778
                                } else if (hitPoint.h>max) {
 
3779
                                        return max - hitPoint.h; /*  regions 3+6+9, result is < 0 */
 
3780
                                } else {
 
3781
                                        return 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
 
3782
                                }
 
3783
                                break;
 
3784
                        case synctex_node_type_vbox:
 
3785
                        case synctex_node_type_void_vbox:
 
3786
                        case synctex_node_type_void_hbox:
 
3787
                                /*  getting the box bounds, taking into account negative width, height and depth.
 
3788
                                 *  For these boxes, no visible dimension available */
 
3789
                                min = SYNCTEX_HORIZ(node);
 
3790
                                max = min + SYNCTEX_ABS_WIDTH(node);
 
3791
                                /*  We allways have min <= max */
 
3792
                                if (hitPoint.h<min) {
 
3793
                                        return min - hitPoint.h; /*  regions 1+4+7, result is > 0 */
 
3794
                                } else if (hitPoint.h>max) {
 
3795
                                        return max - hitPoint.h; /*  regions 3+6+9, result is < 0 */
 
3796
                                } else {
 
3797
                                        return 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
 
3798
                                }
 
3799
                                break;
 
3800
                        case synctex_node_type_kern:
 
3801
                                /*  IMPORTANT NOTICE: the location of the kern is recorded AFTER the move.
 
3802
                                 *  The distance to the kern is very special,
 
3803
                                 *  in general, there is no text material in the kern,
 
3804
                                 *  this is why we compute the offset relative to the closest edge of the kern.*/
 
3805
                                max = SYNCTEX_WIDTH(node);
 
3806
                                if (max<0) {
 
3807
                                        min = SYNCTEX_HORIZ(node);
 
3808
                                        max = min - max;
 
3809
                                } else {
 
3810
                                        min = -max;
 
3811
                                        max = SYNCTEX_HORIZ(node);
 
3812
                                        min += max;
 
3813
                                }
 
3814
                                med = (min+max)/2;
 
3815
                                /*  positive kern: '.' means text, '>' means kern offset
 
3816
                                 *      .............
 
3817
                                 *                   min>>>>med>>>>max
 
3818
                                 *                                    ...............
 
3819
                                 *  negative kern: '.' means text, '<' means kern offset
 
3820
                                 *      ............................
 
3821
                                 *                 min<<<<med<<<<max
 
3822
                                 *                 .................................
 
3823
                                 *  Actually, we do not take into account negative widths.
 
3824
                                 *  There is a problem for such situation when there is efectively overlapping text.
 
3825
                                 *  But this should be extremely rare. I guess that in that case, many different choices
 
3826
                                 *  could be made, one being in contradiction of the other.
 
3827
                                 *  It means that the best choice should be made according to the situation that occurs
 
3828
                                 *  most frequently.
 
3829
                                 */
 
3830
                                if (hitPoint.h<min) {
 
3831
                                        return min - hitPoint.h + 1; /*  penalty to ensure other nodes are chosen first in case of overlapping ones */
 
3832
                                } else if (hitPoint.h>max) {
 
3833
                                        return max - hitPoint.h - 1; /*  same kind of penalty */
 
3834
                                } else if (hitPoint.h>med) {
 
3835
                                        /*  do things like if the node had 0 width and was placed at the max edge + 1*/
 
3836
                                        return max - hitPoint.h + 1; /*  positive, the kern is to the right of the hitPoint */
 
3837
                                } else {
 
3838
                                        return min - hitPoint.h - 1; /*  negative, the kern is to the left of the hitPoint */
 
3839
                                }
 
3840
                        case synctex_node_type_glue:
 
3841
                        case synctex_node_type_math:
 
3842
                                return SYNCTEX_HORIZ(node) - hitPoint.h;
 
3843
                }
 
3844
        }
 
3845
        return INT_MAX;/*  We always assume that the node is faraway to the right*/
7755
3846
}
7756
 
/** Rougly speaking, this is:
7757
 
 *  node's v coordinate - hit point's v coordinate.
 
3847
/*  Rougly speaking, this is:
 
3848
 *  node's v coordinate - hitPoint's v coordinate.
7758
3849
 *  If node is at the top of the hit point, then this distance is positive,
7759
 
 *  if node is at the bottom of the hit point, this distance is negative.
7760
 
 */
7761
 
static synctex_nd_s _synctex_point_v_ordered_distance_v2
7762
 
(synctex_point_p hit, synctex_node_p node) {
7763
 
    synctex_nd_s nd = {node, INT_MAX};
7764
 
    int min,max,depth,height;
7765
 
    switch(synctex_node_type(node)) {
7766
 
            /*  The distance between a point and a box is special.
7767
 
             *  It is not the euclidian distance, nor something similar.
7768
 
             *  We have to take into account the particular layout,
7769
 
             *  and the box hierarchy.
7770
 
             *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
7771
 
             *  The origin being at the top left corner of the page,
7772
 
             *  we also give names to the vertices of the box.
7773
 
             *
7774
 
             *   1 | 2 | 3
7775
 
             *  ---A---B--->
7776
 
             *   4 | 5 | 6
7777
 
             *  ---C---D--->
7778
 
             *   7 | 8 | 9
7779
 
             *     v   v
7780
 
             */
7781
 
        case synctex_node_type_vbox:
7782
 
        case synctex_node_type_void_vbox:
7783
 
        case synctex_node_type_void_hbox:
7784
 
            /*  getting the box bounds, taking into account negative width, height and depth. */
7785
 
            min = synctex_node_v(node);
7786
 
            max = min + _synctex_abs(_synctex_data_depth(node));
7787
 
            min -= _synctex_abs(_synctex_data_height(node));
7788
 
            /*  We always have min <= max */
7789
 
            if (hit->v<min) {
7790
 
                nd.distance = min - hit->v; /*  regions 1+2+3, result is > 0 */
7791
 
            } else if (hit->v>max) {
7792
 
                nd.distance = max - hit->v; /*  regions 7+8+9, result is < 0 */
7793
 
            } else {
7794
 
                nd.distance = 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
7795
 
            }
7796
 
            break;
7797
 
        case synctex_node_type_proxy_vbox:
7798
 
            /*  getting the box bounds, taking into account negative width, height and depth. */
7799
 
            min = synctex_node_v(node);
7800
 
            max = min + _synctex_abs(synctex_node_depth(node));
7801
 
            min -= _synctex_abs(synctex_node_height(node));
7802
 
            /*  We always have min <= max */
7803
 
            if (hit->v<min) {
7804
 
                nd.distance = min - hit->v; /*  regions 1+2+3, result is > 0 */
7805
 
            } else if (hit->v>max) {
7806
 
                nd.distance = max - hit->v; /*  regions 7+8+9, result is < 0 */
7807
 
            } else {
7808
 
                nd.distance = 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
7809
 
            }
7810
 
            break;
7811
 
        case synctex_node_type_hbox:
7812
 
        case synctex_node_type_proxy_hbox:
7813
 
            /*  getting the box bounds, taking into account negative height and depth. */
7814
 
            min = synctex_node_hbox_v(node);
7815
 
            depth = synctex_node_hbox_depth(node);
7816
 
            max = min + (depth>0?depth:-depth);
7817
 
            height = synctex_node_hbox_height(node);
7818
 
            min -= (height>0?height:-height);
7819
 
            /*  We always have min <= max */
7820
 
            if (hit->v<min) {
7821
 
                nd.distance = min - hit->v; /*  regions 1+2+3, result is > 0 */
7822
 
            } else if (hit->v>max) {
7823
 
                nd.distance = max - hit->v; /*  regions 7+8+9, result is < 0 */
7824
 
            } else {
7825
 
                nd.distance = 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
7826
 
            }
7827
 
            break;
7828
 
        case synctex_node_type_rule:/* to do: special management */
7829
 
        case synctex_node_type_kern:
7830
 
        case synctex_node_type_glue:
7831
 
        case synctex_node_type_math:
7832
 
            min = _synctex_data_v(node);
7833
 
            max = min + _synctex_abs(_synctex_data_depth(_synctex_tree_parent(node)));
7834
 
            min -= _synctex_abs(_synctex_data_height(_synctex_tree_parent(node)));
7835
 
            /*  We always have min <= max */
7836
 
            if (hit->v<min) {
7837
 
                nd.distance = min - hit->v; /*  regions 1+2+3, result is > 0 */
7838
 
            } else if (hit->v>max) {
7839
 
                nd.distance = max - hit->v; /*  regions 7+8+9, result is < 0 */
7840
 
            } else {
7841
 
                nd.distance = 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
7842
 
            }
7843
 
            break;
7844
 
        case synctex_node_type_ref:
7845
 
            nd.node = synctex_node_child(node);
7846
 
            nd = _synctex_point_v_ordered_distance_v2(hit,nd.node);
7847
 
            break;
7848
 
        case synctex_node_type_proxy:
7849
 
        case synctex_node_type_proxy_last:
7850
 
        {
7851
 
            synctex_point_s otherHit = *hit;
7852
 
            otherHit.h -= _synctex_data_h(node);
7853
 
            otherHit.v -= _synctex_data_v(node);
7854
 
            nd.node = _synctex_tree_target(node);
7855
 
            nd = _synctex_point_v_ordered_distance_v2(&otherHit,nd.node);
7856
 
            nd.node = node;
7857
 
        }
7858
 
        default: break;
7859
 
    }
7860
 
    return nd;
 
3850
 *  if node is at the bottom of the hit point, this distance is negative.*/
 
3851
int _synctex_point_v_distance(synctex_point_t hitPoint, synctex_node_t node,synctex_bool_t visible);
 
3852
int _synctex_point_v_distance(synctex_point_t hitPoint, synctex_node_t node,synctex_bool_t visible) {
 
3853
#       ifdef __DARWIN_UNIX03
 
3854
#       pragma unused(visible)
 
3855
#   endif
 
3856
        if (node) {
 
3857
                int min,max;
 
3858
                switch(node->class->type) {
 
3859
                        /*  The distance between a point and a box is special.
 
3860
                         *  It is not the euclidian distance, nor something similar.
 
3861
                         *  We have to take into account the particular layout,
 
3862
                         *  and the box hierarchy.
 
3863
                         *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
 
3864
                         *  The origin being at the top left corner of the page,
 
3865
                         *  we also give names to the vertices of the box.
 
3866
                         *
 
3867
                         *   1 | 2 | 3
 
3868
                         *  ---A---B--->
 
3869
                         *   4 | 5 | 6
 
3870
                         *  ---C---D--->
 
3871
                         *   7 | 8 | 9
 
3872
                         *     v   v
 
3873
                         */
 
3874
                        case synctex_node_type_hbox:
 
3875
                                /*  getting the box bounds, taking into account negative width, height and depth. */
 
3876
                                min = SYNCTEX_VERT_V(node);
 
3877
                                max = min + SYNCTEX_ABS_DEPTH_V(node);
 
3878
                                min -= SYNCTEX_ABS_HEIGHT_V(node);
 
3879
                                /*  We allways have min <= max */
 
3880
                                if (hitPoint.v<min) {
 
3881
                                        return min - hitPoint.v; /*  regions 1+2+3, result is > 0 */
 
3882
                                } else if (hitPoint.v>max) {
 
3883
                                        return max - hitPoint.v; /*  regions 7+8+9, result is < 0 */
 
3884
                                } else {
 
3885
                                        return 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
 
3886
                                }
 
3887
                                break;
 
3888
                        case synctex_node_type_vbox:
 
3889
                        case synctex_node_type_void_vbox:
 
3890
                        case synctex_node_type_void_hbox:
 
3891
                                /*  getting the box bounds, taking into account negative width, height and depth. */
 
3892
                                min = SYNCTEX_VERT(node);
 
3893
                                max = min + SYNCTEX_ABS_DEPTH(node);
 
3894
                                min -= SYNCTEX_ABS_HEIGHT(node);
 
3895
                                /*  We allways have min <= max */
 
3896
                                if (hitPoint.v<min) {
 
3897
                                        return min - hitPoint.v; /*  regions 1+2+3, result is > 0 */
 
3898
                                } else if (hitPoint.v>max) {
 
3899
                                        return max - hitPoint.v; /*  regions 7+8+9, result is < 0 */
 
3900
                                } else {
 
3901
                                        return 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
 
3902
                                }
 
3903
                                break;
 
3904
                        case synctex_node_type_kern:
 
3905
                        case synctex_node_type_glue:
 
3906
                        case synctex_node_type_math:
 
3907
                                return SYNCTEX_VERT(node) - hitPoint.v;
 
3908
                }
 
3909
        }
 
3910
        return INT_MAX;/*  We always assume that the node is faraway to the top*/
7861
3911
}
7862
 
/**
7863
 
 *  The best is the one with the smallest area.
7864
 
 *  The area is width*height where width and height may be big.
7865
 
 *  So there is a real risk of overflow if we stick with ints.
7866
 
 */
7867
 
SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node) {
7868
 
    long total_height, other_total_height;
7869
 
    unsigned long area, other_area;
7870
 
    long width = synctex_node_hbox_width(node);
7871
 
    long other_width = synctex_node_hbox_width(other_node);
7872
 
    if (width<0) {
7873
 
        width = -width;
7874
 
    }
7875
 
    if (other_width<0) {
7876
 
        other_width = -other_width;
7877
 
    }
7878
 
    total_height = _synctex_abs(synctex_node_hbox_depth(node)) + _synctex_abs(synctex_node_hbox_height(node));
7879
 
    other_total_height = _synctex_abs(synctex_node_hbox_depth(other_node)) + _synctex_abs(synctex_node_hbox_height(other_node));
7880
 
    area = total_height*width;
7881
 
    other_area = other_total_height*other_width;
7882
 
    if (area<other_area) {
7883
 
        return node;
7884
 
    }
7885
 
    if (area>other_area) {
7886
 
        return other_node;
7887
 
    }
7888
 
    if (_synctex_abs(_synctex_data_width(node))>_synctex_abs(_synctex_data_width(other_node))) {
7889
 
        return node;
7890
 
    }
7891
 
    if (_synctex_abs(_synctex_data_width(node))<_synctex_abs(_synctex_data_width(other_node))) {
7892
 
        return other_node;
7893
 
    }
7894
 
    if (total_height<other_total_height) {
7895
 
        return node;
7896
 
    }
7897
 
    if (total_height>other_total_height) {
7898
 
        return other_node;
 
3912
 
 
3913
SYNCTEX_INLINE static synctex_node_t _synctex_smallest_container(synctex_node_t node, synctex_node_t other_node) {
 
3914
        float height, other_height;
 
3915
        if (SYNCTEX_ABS_WIDTH(node)<SYNCTEX_ABS_WIDTH(other_node)) {
 
3916
                return node;
 
3917
        }
 
3918
        if (SYNCTEX_ABS_WIDTH(node)>SYNCTEX_ABS_WIDTH(other_node)) {
 
3919
                return other_node;
 
3920
        }
 
3921
        height = SYNCTEX_ABS_DEPTH(node) + SYNCTEX_ABS_HEIGHT(node);
 
3922
        other_height = SYNCTEX_ABS_DEPTH(other_node) + SYNCTEX_ABS_HEIGHT(other_node);
 
3923
        if (height<other_height) {
 
3924
                return node;
 
3925
        }
 
3926
        if (height>other_height) {
 
3927
                return other_node;
7899
3928
    }
7900
3929
    return node;
7901
3930
}
7902
3931
 
7903
 
SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hit, synctex_node_p node) {
7904
 
    if (node) {
7905
 
        if (0 == _synctex_point_h_ordered_distance_v2(hit,node).distance
7906
 
            && 0 == _synctex_point_v_ordered_distance_v2(hit,node).distance) {
7907
 
            return synctex_YES;
7908
 
        }
7909
 
    }
7910
 
    return synctex_NO;
7911
 
}
7912
 
 
7913
 
static int _synctex_distance_to_box_v2(synctex_point_p hit,synctex_box_p box) {
7914
 
    /*  The distance between a point and a box is special.
7915
 
     *  It is not the euclidian distance, nor something similar.
7916
 
     *  We have to take into account the particular layout,
7917
 
     *  and the box hierarchy.
7918
 
     *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
7919
 
     *  The origin being at the top left corner of the page,
7920
 
     *  we also give names to the vertices of the box.
7921
 
     *
7922
 
     *   1 | 2 | 3
7923
 
     *  ---A---B--->
7924
 
     *   4 | 5 | 6
7925
 
     *  ---C---D--->
7926
 
     *   7 | 8 | 9
7927
 
     *     v   v
7928
 
     *  In each region, there is a different formula.
7929
 
     *  In the end we have a continuous distance which may not be a mathematical distance but who cares. */
7930
 
    if (hit->v<box->min.v) {
7931
 
        /*  Regions 1, 2 or 3 */
7932
 
        if (hit->h<box->min.h) {
7933
 
            /*  This is region 1. The distance to the box is the L1 distance PA. */
7934
 
            return box->min.v - hit->v + box->min.h - hit->h;/*  Integer overflow? probability epsilon */
7935
 
        } else if (hit->h<=box->max.h) {
7936
 
            /*  This is region 2. The distance to the box is the geometrical distance to the top edge.  */
7937
 
            return box->min.v - hit->v;
7938
 
        } else {
7939
 
            /*  This is region 3. The distance to the box is the L1 distance PB. */
7940
 
            return box->min.v - hit->v + hit->h - box->max.h;
7941
 
        }
7942
 
    } else if (hit->v<=box->max.v) {
7943
 
        /*  Regions 4, 5 or 6 */
7944
 
        if (hit->h<box->min.h) {
7945
 
            /*  This is region 4. The distance to the box is the geometrical distance to the left edge.  */
7946
 
            return box->min.h - hit->h;
7947
 
        } else if (hit->h<=box->max.h) {
7948
 
            /*  This is region 5. We are inside the box.  */
7949
 
            return 0;
7950
 
        } else {
7951
 
            /*  This is region 6. The distance to the box is the geometrical distance to the right edge.  */
7952
 
            return hit->h - box->max.h;
7953
 
        }
7954
 
    } else {
7955
 
        /*  Regions 7, 8 or 9 */
7956
 
        if (hit->h<box->min.h) {
7957
 
            /*  This is region 7. The distance to the box is the L1 distance PC. */
7958
 
            return hit->v - box->max.v + box->min.h - hit->h;
7959
 
        } else if (hit->h<=box->max.h) {
7960
 
            /*  This is region 8. The distance to the box is the geometrical distance to the top edge.  */
7961
 
            return hit->v - box->max.v;
7962
 
        } else {
7963
 
            /*  This is region 9. The distance to the box is the L1 distance PD. */
7964
 
            return hit->v - box->max.v + hit->h - box->max.h;
7965
 
        }
7966
 
    }
7967
 
}
7968
 
 
7969
 
/**
7970
 
 *  The distance from the hit point to the node.
7971
 
 */
7972
 
static int _synctex_point_node_distance_v2(synctex_point_p hit, synctex_node_p node) {
7973
 
    int d = INT_MAX;
7974
 
    if (node) {
7975
 
        synctex_box_s box = {{0,0},{0,0}};
7976
 
        int dd = INT_MAX;
7977
 
        switch(synctex_node_type(node)) {
7978
 
            case synctex_node_type_vbox:
7979
 
                box.min.h = _synctex_data_h(node);
7980
 
                box.max.h = box.min.h + _synctex_abs(_synctex_data_width(node));
7981
 
                box.min.v = synctex_node_v(node);
7982
 
                box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node));
7983
 
                box.min.v -= _synctex_abs(_synctex_data_height(node));
7984
 
                return _synctex_distance_to_box_v2(hit,&box);
7985
 
            case synctex_node_type_proxy_vbox:
7986
 
                box.min.h = synctex_node_h(node);
7987
 
                box.max.h = box.min.h + _synctex_abs(synctex_node_width(node));
7988
 
                box.min.v = synctex_node_v(node);
7989
 
                box.max.v = box.min.v + _synctex_abs(synctex_node_depth(node));
7990
 
                box.min.v -= _synctex_abs(synctex_node_height(node));
7991
 
                return _synctex_distance_to_box_v2(hit,&box);
7992
 
            case synctex_node_type_hbox:
7993
 
            case synctex_node_type_proxy_hbox:
7994
 
                box.min.h = synctex_node_hbox_h(node);
7995
 
                box.max.h = box.min.h + _synctex_abs(synctex_node_hbox_width(node));
7996
 
                box.min.v = synctex_node_hbox_v(node);
7997
 
                box.max.v = box.min.v + _synctex_abs(synctex_node_hbox_depth(node));
7998
 
                box.min.v -= _synctex_abs(synctex_node_hbox_height(node));
7999
 
                return _synctex_distance_to_box_v2(hit,&box);
8000
 
            case synctex_node_type_void_vbox:
8001
 
            case synctex_node_type_void_hbox:
8002
 
                /*  best of distances from the left edge and right edge*/
8003
 
                box.min.h = _synctex_data_h(node);
8004
 
                box.max.h = box.min.h;
8005
 
                box.min.v = _synctex_data_v(node);
8006
 
                box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node));
8007
 
                box.min.v -= _synctex_abs(_synctex_data_height(node));
8008
 
                d = _synctex_distance_to_box_v2(hit,&box);
8009
 
                box.min.h = box.min.h + _synctex_abs(_synctex_data_width(node));
8010
 
                box.max.h = box.min.h;
8011
 
                dd = _synctex_distance_to_box_v2(hit,&box);
8012
 
                return d<dd ? d:dd;
8013
 
            case synctex_node_type_kern:
8014
 
                box.min.h = _synctex_data_h(node);
8015
 
                box.max.h = box.min.h;
8016
 
                box.max.v = _synctex_data_v(node);
8017
 
                box.min.v = box.max.v - _synctex_abs(_synctex_data_height(_synctex_tree_parent(node)));
8018
 
                d = _synctex_distance_to_box_v2(hit,&box);
8019
 
                box.min.h -= _synctex_data_width(node);
8020
 
                box.max.h = box.min.h;
8021
 
                dd = _synctex_distance_to_box_v2(hit,&box);
8022
 
                return d<dd ? d:dd;
8023
 
            case synctex_node_type_glue:
8024
 
            case synctex_node_type_math:
8025
 
            case synctex_node_type_boundary:
8026
 
            case synctex_node_type_box_bdry:
8027
 
                box.min.h = _synctex_data_h(node);
8028
 
                box.max.h = box.min.h;
8029
 
                box.max.v = _synctex_data_v(node);
8030
 
                box.min.v = box.max.v - _synctex_abs(_synctex_data_height(_synctex_tree_parent(node)));
8031
 
                return _synctex_distance_to_box_v2(hit,&box);
8032
 
            case synctex_node_type_proxy:
8033
 
            case synctex_node_type_proxy_last:
8034
 
            {
8035
 
                synctex_point_s otherHit = *hit;
8036
 
                otherHit.h -= _synctex_data_h(node);
8037
 
                otherHit.v -= _synctex_data_v(node);
8038
 
                return _synctex_point_node_distance_v2(&otherHit, _synctex_tree_target(node));
8039
 
            }
8040
 
            default: break;
8041
 
        }
8042
 
    }
8043
 
    return d;
8044
 
}
8045
 
static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hit, synctex_node_p node) {
8046
 
    if (node) {
8047
 
        /**/
8048
 
        synctex_node_p child;
8049
 
        if ((child = synctex_node_child(node))) {
8050
 
            /*  Non void hbox or vbox, form ref or proxy */
8051
 
            /*  We go deep first because some boxes have 0 dimensions
8052
 
             *  despite they do contain some black material.
8053
 
             */
8054
 
            do {
8055
 
                if ((_synctex_point_in_box_v2(hit,child))) {
8056
 
                    synctex_node_p deep = _synctex_eq_deepest_container_v2(hit,child);
8057
 
                    if (deep) {
8058
 
                        /*  One of the children contains the hit. */
8059
 
                        return deep;
8060
 
                    }
8061
 
                }
8062
 
            } while((child = synctex_node_sibling(child)));
8063
 
            /*  is the hit point inside the box? */
8064
 
            if (synctex_node_type(node) == synctex_node_type_vbox
8065
 
                || synctex_node_type(node) == synctex_node_type_proxy_vbox) {
8066
 
                /*  For vboxes we try to use some node inside.
8067
 
                 *  Walk through the list of siblings until we find the closest one.
8068
 
                 *  Only consider siblings with children inside. */
8069
 
                if ((child = _synctex_tree_child(node))) {
8070
 
                    synctex_nd_s best = SYNCTEX_ND_0;
8071
 
                    do {
8072
 
                        if (_synctex_tree_child(child)) {
8073
 
                            int d = _synctex_point_node_distance_v2(hit,child);
8074
 
                            if (d <= best.distance) {
8075
 
                                best = (synctex_nd_s){child, d};
8076
 
                            }
8077
 
                        }
8078
 
                    } while((child = __synctex_tree_sibling(child)));
8079
 
                    if (best.node) {
8080
 
                        return best.node;
8081
 
                    }
8082
 
                }
8083
 
            }
8084
 
            if (_synctex_point_in_box_v2(hit,node)) {
8085
 
                return node;
8086
 
            }
8087
 
        }
8088
 
    }
8089
 
    return NULL;
8090
 
}
8091
 
static synctex_nd_s _synctex_eq_deepest_container_v3(synctex_point_p hit, synctex_node_p node) {
8092
 
    if (node) {
8093
 
        synctex_node_p child = NULL;
8094
 
        if ((child = synctex_node_child(node))) {
8095
 
            /*  Non void hbox, vbox, box proxy or form ref */
8096
 
            /*  We go deep first because some boxes have 0 dimensions
8097
 
             *  despite they do contain some black material.
8098
 
             */
8099
 
            do {
8100
 
                synctex_nd_s deep = _synctex_eq_deepest_container_v3(hit, child);
8101
 
                if (deep.node) {
8102
 
                    /*  One of the children contains the hit-> */
8103
 
                    return deep;
8104
 
                }
8105
 
            } while((child = synctex_node_sibling(child)));
8106
 
            /*  For vboxes we try to use some node inside.
8107
 
             *  Walk through the list of siblings until we find the closest one.
8108
 
             *  Only consider siblings with children inside. */
8109
 
            if (synctex_node_type(node) == synctex_node_type_vbox
8110
 
                || synctex_node_type(node) == synctex_node_type_proxy_vbox) {
8111
 
                if ((child = synctex_node_child(node))) {
8112
 
                    synctex_nd_s best = SYNCTEX_ND_0;
8113
 
                    do {
8114
 
                        if (synctex_node_child(child)) {
8115
 
                            int d = _synctex_point_node_distance_v2(hit,child);
8116
 
                            if (d < best.distance) {
8117
 
                                best = (synctex_nd_s){child,d};
8118
 
                            }
8119
 
                        }
8120
 
                    } while((child = synctex_node_sibling(child)));
8121
 
                    if (best.node) {
8122
 
                        return best;
8123
 
                    }
8124
 
                }
8125
 
            }
8126
 
            /*  is the hit point inside the box? */
8127
 
            if (_synctex_point_in_box_v2(hit,node)) {
8128
 
                return (synctex_nd_s){node, 0};
8129
 
            }
8130
 
        }
8131
 
    }
8132
 
    return SYNCTEX_ND_0;
8133
 
}
8134
 
 
8135
 
/*  Compares the locations of the hit point with the locations of
8136
 
 *  the various nodes contained in the box.
8137
 
 *  As it is an horizontal box, we only compare horizontal coordinates.
8138
 
 */
8139
 
SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v2(synctex_point_p hitP, synctex_node_p node) {
8140
 
    synctex_nd_s childd = SYNCTEX_ND_0;
8141
 
    synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0};
8142
 
    if ((childd.node = synctex_node_child(node))) {
8143
 
        synctex_nd_s nd = SYNCTEX_ND_0;
8144
 
        do {
8145
 
            childd = _synctex_point_h_ordered_distance_v2(hitP,childd.node);
8146
 
            if (childd.distance > 0) {
8147
 
                /*  node is to the right of the hit point.
8148
 
                 *  We compare node and the previously recorded one, through the recorded distance.
8149
 
                 *  If the nodes have the same tag, prefer the one with the smallest line number,
8150
 
                 *  if the nodes also have the same line number, prefer the one with the smallest column. */
8151
 
                if (nds.r.distance > childd.distance) {
8152
 
                    nds.r = childd;
8153
 
                } else if (nds.r.distance == childd.distance && nds.r.node) {
8154
 
                    if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(childd.node)
8155
 
                        && (_synctex_data_line(nds.r.node) > _synctex_data_line(childd.node)
8156
 
                            || (_synctex_data_line(nds.r.node) == _synctex_data_line(childd.node)
8157
 
                                && _synctex_data_column(nds.r.node) > _synctex_data_column(childd.node)))) {
8158
 
                                nds.r = childd;
8159
 
                            }
8160
 
                }
8161
 
            } else if (childd.distance == 0) {
8162
 
                /*  hit point is inside node. */
8163
 
                if (_synctex_tree_child(childd.node)) {
8164
 
                    return _synctex_eq_get_closest_children_in_box_v2(hitP, childd.node);
8165
 
                }
8166
 
                nds.l = childd;
8167
 
            } else { /*  here childd.distance < 0, the hit point is to the right of node */
8168
 
                childd.distance = -childd.distance;
8169
 
                if (nds.l.distance > childd.distance) {
8170
 
                    nds.l = childd;
8171
 
                } else if (nds.l.distance == childd.distance && nds.l.node) {
8172
 
                    if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(childd.node)
8173
 
                        && (_synctex_data_line(nds.l.node) > _synctex_data_line(childd.node)
8174
 
                            || (_synctex_data_line(nds.l.node) == _synctex_data_line(childd.node)
8175
 
                                && _synctex_data_column(nds.l.node) > _synctex_data_column(childd.node)))) {
8176
 
                                nds.l = childd;
8177
 
                            }
8178
 
                }
8179
 
            }
8180
 
        } while((childd.node = synctex_node_sibling(childd.node)));
8181
 
        if (nds.l.node) {
8182
 
            /*  the left node is new, try to narrow the result */
8183
 
            if ((nd = _synctex_eq_deepest_container_v3(hitP,nds.l.node)).node) {
8184
 
                nds.l = nd;
8185
 
            }
8186
 
            if((nd = __synctex_closest_deep_child_v2(hitP,nds.l.node)).node) {
8187
 
                nds.l.node = nd.node;
8188
 
            }
8189
 
        }
8190
 
        if (nds.r.node) {
8191
 
            /*  the right node is new, try to narrow the result */
8192
 
            if ((nd = _synctex_eq_deepest_container_v3(hitP,nds.r.node)).node) {
8193
 
                nds.r = nd;
8194
 
            }
8195
 
            if((nd = __synctex_closest_deep_child_v2(hitP,nds.r.node)).node) {
8196
 
                nds.r.node = nd.node;
8197
 
            }
8198
 
        }
8199
 
    }
8200
 
    return nds;
8201
 
}
8202
 
 
8203
 
#if 0
8204
 
SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v3(synctex_point_p hitP, synctex_node_p nodeP) {
8205
 
    synctex_nd_s nd = SYNCTEX_ND_0;
8206
 
    synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0};
8207
 
    if ((nd.node = _synctex_tree_child(nodeP))) {
8208
 
        do {
8209
 
            nd = _synctex_point_h_ordered_distance_v2(hitP,nd.node);
8210
 
            if (nd.distance > 0) {
8211
 
                /*  node is to the right of the hit point.
8212
 
                 *  We compare node and the previously recorded one, through the recorded distance.
8213
 
                 *  If the nodes have the same tag, prefer the one with the smallest line number,
8214
 
                 *  if the nodes also have the same line number, prefer the one with the smallest column. */
8215
 
                if (nds.r.distance > nd.distance) {
8216
 
                    nds.r = nd;
8217
 
                } else if (nds.r.distance == nd.distance && nds.r.node) {
8218
 
                    if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node)
8219
 
                        && (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node)
8220
 
                            || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node)
8221
 
                                && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) {
8222
 
                                nds.r = nd;
8223
 
                            }
8224
 
                }
8225
 
            } else if (nd.distance == 0) {
8226
 
                /*  hit point is inside node. */
8227
 
                nds.l = nd;
8228
 
            } else { /*  here nd.d < 0, the hit point is to the right of node */
8229
 
                nd.distance = -nd.distance;
8230
 
                if (nds.l.distance > nd.distance) {
8231
 
                    nds.l = nd;
8232
 
                } else if (nds.l.distance == nd.distance && nds.l.node) {
8233
 
                    if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node)
8234
 
                        && (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node)
8235
 
                            || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node)
8236
 
                                && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) {
8237
 
                                nds.l = nd;
8238
 
                            }
8239
 
                }
8240
 
            }
8241
 
        } while((nd.node = __synctex_tree_sibling(nd.node)));
8242
 
        if (nds.l.node) {
8243
 
            /*  the left node is new, try to narrow the result */
8244
 
            if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) {
8245
 
                nds.l.node = nd.node;
8246
 
            }
8247
 
            if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) {
8248
 
                nds.l.node = nd.node;
8249
 
            }
8250
 
        }
8251
 
        if (nds.r.node) {
8252
 
            /*  the right node is new, try to narrow the result */
8253
 
            if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) {
8254
 
                nds.r.node = nd.node;
8255
 
            }
8256
 
            if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) {
8257
 
                nds.r.node = nd.node;
8258
 
            }
8259
 
        }
8260
 
    }
8261
 
    return nds;
8262
 
}
8263
 
#endif
8264
 
SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_vbox_v2(synctex_point_p hitP, synctex_node_p nodeP) {
8265
 
    SYNCTEX_UNUSED(nodeP)
8266
 
    synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0};
8267
 
    synctex_nd_s nd = SYNCTEX_ND_0;
8268
 
    if ((nd.node = synctex_node_child(nd.node))) {
8269
 
        do {
8270
 
            nd = _synctex_point_v_ordered_distance_v2(hitP,nd.node);
8271
 
            /*  this is what makes the difference with the h version above */
8272
 
            if (nd.distance > 0) {
8273
 
                /*  node is to the top of the hit point (below because TeX is oriented from top to bottom.
8274
 
                 *  We compare node and the previously recorded one, through the recorded distance.
8275
 
                 *  If the nodes have the same tag, prefer the one with the smallest line number,
8276
 
                 *  if the nodes also have the same line number, prefer the one with the smallest column. */
8277
 
                if (nds.r.distance > nd.distance) {
8278
 
                    nds.r = nd;
8279
 
                } else if (nds.r.distance == nd.distance && nds.r.node) {
8280
 
                    if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node)
8281
 
                        && (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node)
8282
 
                            || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node)
8283
 
                                && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) {
8284
 
                                nds.r = nd;
8285
 
                            }
8286
 
                }
8287
 
            } else if (nd.distance == 0) {
8288
 
                nds.l = nd;
8289
 
            } else { /*  here nd < 0 */
8290
 
                nd.distance = -nd.distance;
8291
 
                if (nds.l.distance > nd.distance) {
8292
 
                    nds.l = nd;
8293
 
                } else if (nds.l.distance == nd.distance && nds.l.node) {
8294
 
                    if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node)
8295
 
                        && (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node)
8296
 
                            || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node)
8297
 
                                && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) {
8298
 
                                nds.l = nd;
8299
 
                            }
8300
 
                }
8301
 
            }
8302
 
        } while((nd.node = synctex_node_sibling(nd.node)));
8303
 
        if (nds.l.node) {
8304
 
            if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) {
8305
 
                nds.l.node = nd.node;
8306
 
            }
8307
 
            if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) {
8308
 
                nds.l.node = nd.node;
8309
 
            }
8310
 
        }
8311
 
        if (nds.r.node) {
8312
 
            if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) {
8313
 
                nds.r.node = nd.node;
8314
 
            }
8315
 
            if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) {
8316
 
                nds.r.node = nd.node;
8317
 
            }
8318
 
        }
8319
 
    }
8320
 
    return nds;
8321
 
}
8322
 
 
8323
 
/**
8324
 
 *  Get the child closest to the hit point.
8325
 
 *  - parameter: hit point
8326
 
 *  - parameter: containing node
8327
 
 *  - returns: the child and the distance to the hit point.
8328
 
 *      SYNCTEX_ND_0 if the parameter node has no children.
8329
 
 *  - note: recursive call.
8330
 
 */
8331
 
static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node) {
8332
 
    synctex_nd_s best = SYNCTEX_ND_0;
8333
 
    synctex_node_p child = NULL;
8334
 
    if ((child = synctex_node_child(node))) {
8335
 
#if defined(SYNCTEX_DEBUG)
8336
 
        printf("Closest deep child on box at line %i\n",
8337
 
               SYNCTEX_LINEINDEX(node));
8338
 
#endif
8339
 
        do {
8340
 
#if SYNCTEX_DEBUG>500
8341
 
            synctex_node_display(child);
8342
 
#endif
8343
 
            synctex_nd_s nd = SYNCTEX_ND_0;
8344
 
            if (_synctex_node_is_box(child)) {
8345
 
                nd = __synctex_closest_deep_child_v2(hitP,child);
8346
 
            } else {
8347
 
                nd = (synctex_nd_s) {child, _synctex_point_node_distance_v2(hitP,child)};
8348
 
            }
8349
 
            if (nd.distance < best.distance ||(nd.distance == best.distance
8350
 
                                               && synctex_node_type(nd.node) != synctex_node_type_kern)) {
8351
 
#if defined(SYNCTEX_DEBUG)
8352
 
                if(nd.node) {
8353
 
                    printf("New best %i<=%i line %i\n",nd.distance,
8354
 
                           best.distance,SYNCTEX_LINEINDEX(nd.node));
8355
 
                }
8356
 
#endif
8357
 
                best = nd;
8358
 
            }
8359
 
        } while((child = synctex_node_sibling(child)));
8360
 
#if defined(SYNCTEX_DEBUG)
8361
 
        if(best.node) {
8362
 
            printf("Found new best %i line %i\n",best.distance,SYNCTEX_LINEINDEX(best.node));
8363
 
        }
8364
 
#endif
8365
 
    }
8366
 
    return best;
8367
 
}
8368
 
 
8369
 
/**
8370
 
 *  Return the closest child.
8371
 
 *  - parameter: a pointer to the hit point,
8372
 
 *  - parameter: the container
8373
 
 *  - return: SYNCTEX_ND_0 if node has no child,
8374
 
 *      the __synctex_closest_deep_child_v2 otherwise.
8375
 
 */
8376
 
static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node) {
8377
 
    synctex_nd_s nd = SYNCTEX_ND_0;
8378
 
    if (_synctex_node_is_box(node)) {
8379
 
        nd = __synctex_closest_deep_child_v2(hitP, node);
8380
 
        if (_synctex_node_is_box(nd.node)) {
8381
 
            synctex_node_p child = NULL;
8382
 
            if ((child = synctex_node_child(nd.node))) {
8383
 
                synctex_nd_s best = {child,_synctex_point_node_distance_v2(hitP,child)};
8384
 
                while((child = synctex_node_sibling(child))) {
8385
 
                    int d = _synctex_point_node_distance_v2(hitP,child);
8386
 
                    if (d < best.distance) {
8387
 
                        best = (synctex_nd_s){child,d};
8388
 
                    } else if (d == best.distance && synctex_node_type(child) != synctex_node_type_kern) {
8389
 
                        best.node = child;
8390
 
                    }
8391
 
                }
8392
 
                return best;
8393
 
            }
8394
 
        }
8395
 
        return nd;
8396
 
    }
8397
 
    return SYNCTEX_ND_0;
8398
 
}
8399
 
SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node) {
8400
 
    synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0};
8401
 
    if(_synctex_tree_has_child(node)) { /* node != NULL */
8402
 
        if (node->class_->type==synctex_node_type_hbox ||
8403
 
            node->class_->type==synctex_node_type_proxy_hbox) {
8404
 
            return __synctex_eq_get_closest_children_in_hbox_v2(hitP,node);
8405
 
        } else {
8406
 
            return __synctex_eq_get_closest_children_in_vbox_v2(hitP,node);
8407
 
        }
8408
 
    }
8409
 
    return nds;
8410
 
}
8411
 
 
8412
 
#ifndef SYNCTEX_NO_UPDATER
 
3932
synctex_bool_t _synctex_point_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) {
 
3933
        if (node) {
 
3934
                if (0 == _synctex_point_h_distance(hitPoint,node,visible)
 
3935
                                && 0 == _synctex_point_v_distance(hitPoint,node,visible)) {
 
3936
                        return synctex_YES;
 
3937
                }
 
3938
        }
 
3939
        return synctex_NO;      
 
3940
}
 
3941
 
 
3942
int _synctex_node_distance_to_point(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) {
 
3943
#       ifdef __DARWIN_UNIX03
 
3944
#       pragma unused(visible)
 
3945
#   endif
 
3946
        int result = INT_MAX; /*  when the distance is meaning less (sheet, input...)  */
 
3947
        if (node) {
 
3948
                int minH,maxH,minV,maxV;
 
3949
                switch(node->class->type) {
 
3950
                        /*  The distance between a point and a box is special.
 
3951
                         *  It is not the euclidian distance, nor something similar.
 
3952
                         *  We have to take into account the particular layout,
 
3953
                         *  and the box hierarchy.
 
3954
                         *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
 
3955
                         *  The origin being at the top left corner of the page,
 
3956
                         *  we also give names to the vertices of the box.
 
3957
                         *
 
3958
                         *   1 | 2 | 3
 
3959
                         *  ---A---B--->
 
3960
                         *   4 | 5 | 6
 
3961
                         *  ---C---D--->
 
3962
                         *   7 | 8 | 9
 
3963
                         *     v   v
 
3964
                         *  In each region, there is a different formula.
 
3965
                         *  In the end we have a continuous distance which may not be a mathematical distance but who cares. */
 
3966
                        case synctex_node_type_vbox:
 
3967
                        case synctex_node_type_void_vbox:
 
3968
                        case synctex_node_type_hbox:
 
3969
                        case synctex_node_type_void_hbox:
 
3970
                                /*  getting the box bounds, taking into account negative widths. */
 
3971
                                minH = SYNCTEX_HORIZ(node);
 
3972
                                maxH = minH + SYNCTEX_ABS_WIDTH(node);
 
3973
                                minV = SYNCTEX_VERT(node);
 
3974
                                maxV = minV + SYNCTEX_ABS_DEPTH(node);
 
3975
                                minV -= SYNCTEX_ABS_HEIGHT(node);
 
3976
                                /*  In what region is the point hitPoint=(H,V) ? */
 
3977
                                if (hitPoint.v<minV) {
 
3978
                                        if (hitPoint.h<minH) {
 
3979
                                                /*  This is region 1. The distance to the box is the L1 distance PA. */
 
3980
                                                result = minV - hitPoint.v + minH - hitPoint.h;/*  Integer overflow? probability epsilon */
 
3981
                                        } else if (hitPoint.h<=maxH) {
 
3982
                                                /*  This is region 2. The distance to the box is the geometrical distance to the top edge.  */
 
3983
                                                result = minV - hitPoint.v;
 
3984
                                        } else {
 
3985
                                                /*  This is region 3. The distance to the box is the L1 distance PB. */
 
3986
                                                result = minV - hitPoint.v + hitPoint.h - maxH;
 
3987
                                        }
 
3988
                                } else if (hitPoint.v<=maxV) {
 
3989
                                        if (hitPoint.h<minH) {
 
3990
                                                /*  This is region 4. The distance to the box is the geometrical distance to the left edge.  */
 
3991
                                                result = minH - hitPoint.h;
 
3992
                                        } else if (hitPoint.h<=maxH) {
 
3993
                                                /*  This is region 4. We are inside the box.  */
 
3994
                                                result = 0;
 
3995
                                        } else {
 
3996
                                                /*  This is region 6. The distance to the box is the geometrical distance to the right edge.  */
 
3997
                                                result = hitPoint.h - maxH;
 
3998
                                        }
 
3999
                                } else {
 
4000
                                        if (hitPoint.h<minH) {
 
4001
                                                /*  This is region 7. The distance to the box is the L1 distance PC. */
 
4002
                                                result = hitPoint.v - maxV + minH - hitPoint.h;
 
4003
                                        } else if (hitPoint.h<=maxH) {
 
4004
                                                /*  This is region 8. The distance to the box is the geometrical distance to the top edge.  */
 
4005
                                                result = hitPoint.v - maxV;
 
4006
                                        } else {
 
4007
                                                /*  This is region 9. The distance to the box is the L1 distance PD. */
 
4008
                                                result = hitPoint.v - maxV + hitPoint.h - maxH;
 
4009
                                        }
 
4010
                                }
 
4011
                                break;
 
4012
                        case synctex_node_type_kern:
 
4013
                                maxH = SYNCTEX_WIDTH(node);
 
4014
                                if (maxH<0) {
 
4015
                                        minH = SYNCTEX_HORIZ(node);
 
4016
                                        maxH = minH - maxH;
 
4017
                                } else {
 
4018
                                        minH = -maxH;
 
4019
                                        maxH = SYNCTEX_HORIZ(node);
 
4020
                                        minH += maxH;
 
4021
                                }
 
4022
                                minV = SYNCTEX_VERT(node);
 
4023
                                if (hitPoint.h<minH) {
 
4024
                                        if (hitPoint.v>minV) {
 
4025
                                                result = hitPoint.v - minV + minH - hitPoint.h;
 
4026
                                        } else {
 
4027
                                                result = minV - hitPoint.v + minH - hitPoint.h;
 
4028
                                        }
 
4029
                                } else if (hitPoint.h>maxH) {
 
4030
                                        if (hitPoint.v>minV) {
 
4031
                                                result = hitPoint.v - minV + hitPoint.h - maxH;
 
4032
                                        } else {
 
4033
                                                result = minV - hitPoint.v + hitPoint.h - maxH;
 
4034
                                        }
 
4035
                                } else if (hitPoint.v>minV) {
 
4036
                                        result = hitPoint.v - minV;
 
4037
                                } else {
 
4038
                                        result = minV - hitPoint.v;
 
4039
                                }
 
4040
                                break;
 
4041
                        case synctex_node_type_glue:
 
4042
                        case synctex_node_type_math:
 
4043
                                minH = SYNCTEX_HORIZ(node);
 
4044
                                minV = SYNCTEX_VERT(node);
 
4045
                                if (hitPoint.h<minH) {
 
4046
                                        if (hitPoint.v>minV) {
 
4047
                                                result = hitPoint.v - minV + minH - hitPoint.h;
 
4048
                                        } else {
 
4049
                                                result = minV - hitPoint.v + minH - hitPoint.h;
 
4050
                                        }
 
4051
                                } else if (hitPoint.v>minV) {
 
4052
                                        result = hitPoint.v - minV + hitPoint.h - minH;
 
4053
                                } else {
 
4054
                                        result = minV - hitPoint.v + hitPoint.h - minH;
 
4055
                                }
 
4056
                                break;
 
4057
                }
 
4058
        }
 
4059
        return result;
 
4060
}
 
4061
 
 
4062
static synctex_node_t _synctex_eq_deepest_container(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) {
 
4063
        if (node) {
 
4064
                synctex_node_t result = NULL;
 
4065
                synctex_node_t child = NULL;
 
4066
                switch(node->class->type) {
 
4067
                        case synctex_node_type_vbox:
 
4068
                        case synctex_node_type_hbox:
 
4069
                                /*  test the deep nodes first */
 
4070
                                if ((child = SYNCTEX_CHILD(node))) {
 
4071
                                        do {
 
4072
                                                if ((result = _synctex_eq_deepest_container(hitPoint,child,visible))) {
 
4073
                                                        return result;
 
4074
                                                }
 
4075
                                        } while((child = SYNCTEX_SIBLING(child)));
 
4076
                                }
 
4077
                                /*  is the hit point inside the box? */
 
4078
                                if (_synctex_point_in_box(hitPoint,node,visible)) {
 
4079
                                        /*  for vboxes we try to use some node inside.
 
4080
                                         *  Walk through the list of siblings until we find the closest one.
 
4081
                                         *  Only consider siblings with children. */
 
4082
                                        if ((node->class->type == synctex_node_type_vbox) && (child = SYNCTEX_CHILD(node))) {
 
4083
                                                int bestDistance = INT_MAX;
 
4084
                                                do {
 
4085
                                                        if (SYNCTEX_CHILD(child)) {
 
4086
                                                                int distance = _synctex_node_distance_to_point(hitPoint,child,visible);
 
4087
                                                                if (distance < bestDistance) {
 
4088
                                                                        bestDistance = distance;
 
4089
                                                                        node = child;
 
4090
                                                                }
 
4091
                                                        }
 
4092
                                                } while((child = SYNCTEX_SIBLING(child)));
 
4093
                                        }
 
4094
                                        return node;
 
4095
                                }
 
4096
                }
 
4097
        }
 
4098
        return NULL;
 
4099
}
 
4100
 
 
4101
/*  Compares the locations of the hitPoint with the locations of the various nodes contained in the box.
 
4102
 *  As it is an horizontal box, we only compare horizontal coordinates. */
 
4103
SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_hbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t*  bestNodesRef,synctex_distances_t*  bestDistancesRef, synctex_bool_t visible);
 
4104
SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_hbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t*  bestNodesRef,synctex_distances_t*  bestDistancesRef, synctex_bool_t visible) {
 
4105
        int result = 0;
 
4106
        if ((node = SYNCTEX_CHILD(node))) {
 
4107
                do {
 
4108
                        int off7 = _synctex_point_h_distance(hitPoint,node,visible);
 
4109
                        if (off7 > 0) {
 
4110
                                /*  node is to the right of the hit point.
 
4111
                                 *  We compare node and the previously recorded one, through the recorded distance.
 
4112
                                 *  If the nodes have the same tag, prefer the one with the smallest line number,
 
4113
                                 *  if the nodes also have the same line number, prefer the one with the smallest column. */
 
4114
                                if (bestDistancesRef->right > off7) {
 
4115
                                        bestDistancesRef->right = off7;
 
4116
                                        bestNodesRef->right = node;
 
4117
                                        result |= SYNCTEX_MASK_RIGHT;
 
4118
                                } else if (bestDistancesRef->right == off7 && bestNodesRef->right) {
 
4119
                                        if (SYNCTEX_TAG(bestNodesRef->right) == SYNCTEX_TAG(node)
 
4120
                                                && (SYNCTEX_LINE(bestNodesRef->right) > SYNCTEX_LINE(node)
 
4121
                                                        || (SYNCTEX_LINE(bestNodesRef->right) == SYNCTEX_LINE(node)
 
4122
                                                                && SYNCTEX_COLUMN(bestNodesRef->right) > SYNCTEX_COLUMN(node)))) {
 
4123
                                                bestNodesRef->right = node;
 
4124
                                                result |= SYNCTEX_MASK_RIGHT;
 
4125
                                        }
 
4126
                                }
 
4127
                        } else if (off7 == 0) {
 
4128
                                /*  hitPoint is inside node. */ 
 
4129
                                bestDistancesRef->left = bestDistancesRef->right = 0;
 
4130
                                bestNodesRef->left = node;
 
4131
                                bestNodesRef->right = NULL;
 
4132
                                result |= SYNCTEX_MASK_LEFT;
 
4133
                        } else { /*  here off7 < 0, hitPoint is to the right of node */
 
4134
                                off7 = -off7;
 
4135
                                if (bestDistancesRef->left > off7) {
 
4136
                                        bestDistancesRef->left = off7;
 
4137
                                        bestNodesRef->left = node;
 
4138
                                        result |= SYNCTEX_MASK_LEFT;
 
4139
                                } else if (bestDistancesRef->left == off7 && bestNodesRef->left) {
 
4140
                                        if (SYNCTEX_TAG(bestNodesRef->left) == SYNCTEX_TAG(node)
 
4141
                                                && (SYNCTEX_LINE(bestNodesRef->left) > SYNCTEX_LINE(node)
 
4142
                                                        || (SYNCTEX_LINE(bestNodesRef->left) == SYNCTEX_LINE(node)
 
4143
                                                                && SYNCTEX_COLUMN(bestNodesRef->left) > SYNCTEX_COLUMN(node)))) {
 
4144
                                                bestNodesRef->left = node;
 
4145
                                                result |= SYNCTEX_MASK_LEFT;
 
4146
                                        }
 
4147
                                }
 
4148
                        }
 
4149
                } while((node = SYNCTEX_SIBLING(node)));
 
4150
                if (result & SYNCTEX_MASK_LEFT) {
 
4151
                        /*  the left node is new, try to narrow the result */
 
4152
                        if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->left,visible))) {
 
4153
                                bestNodesRef->left = node;
 
4154
                        } 
 
4155
                        if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) {
 
4156
                                bestNodesRef->left = node;
 
4157
                        } 
 
4158
                }
 
4159
                if (result & SYNCTEX_MASK_RIGHT) {
 
4160
                        /*  the right node is new, try to narrow the result */
 
4161
                        if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->right,visible))) {
 
4162
                                bestNodesRef->right = node;
 
4163
                        } 
 
4164
                        if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) {
 
4165
                                bestNodesRef->right = node;
 
4166
                        } 
 
4167
                }
 
4168
        }
 
4169
        return result;
 
4170
}
 
4171
SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_vbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t*  bestNodesRef,synctex_distances_t*  bestDistancesRef,synctex_bool_t visible);
 
4172
SYNCTEX_INLINE static int __synctex_eq_get_closest_children_in_vbox(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t*  bestNodesRef,synctex_distances_t*  bestDistancesRef,synctex_bool_t visible) {
 
4173
        int result = 0;
 
4174
        if ((node = SYNCTEX_CHILD(node))) {
 
4175
                do {
 
4176
                        int off7 = _synctex_point_v_distance(hitPoint,node,visible);/*  this is what makes the difference with the h version above */
 
4177
                        if (off7 > 0) {
 
4178
                                /*  node is to the top of the hit point (below because TeX is oriented from top to bottom.
 
4179
                                 *  We compare node and the previously recorded one, through the recorded distance.
 
4180
                                 *  If the nodes have the same tag, prefer the one with the smallest line number,
 
4181
                                 *  if the nodes also have the same line number, prefer the one with the smallest column. */
 
4182
                                if (bestDistancesRef->right > off7) {
 
4183
                                        bestDistancesRef->right = off7;
 
4184
                                        bestNodesRef->right = node;
 
4185
                                        result |= SYNCTEX_MASK_RIGHT;
 
4186
                                } else if (bestDistancesRef->right == off7 && bestNodesRef->right) {
 
4187
                                        if (SYNCTEX_TAG(bestNodesRef->right) == SYNCTEX_TAG(node)
 
4188
                                                && (SYNCTEX_LINE(bestNodesRef->right) > SYNCTEX_LINE(node)
 
4189
                                                        || (SYNCTEX_LINE(bestNodesRef->right) == SYNCTEX_LINE(node)
 
4190
                                                                && SYNCTEX_COLUMN(bestNodesRef->right) > SYNCTEX_COLUMN(node)))) {
 
4191
                                                bestNodesRef->right = node;
 
4192
                                                result |= SYNCTEX_MASK_RIGHT;
 
4193
                                        }
 
4194
                                }
 
4195
                        } else if (off7 == 0) {
 
4196
                                bestDistancesRef->left = bestDistancesRef->right = 0;
 
4197
                                bestNodesRef->left = node;
 
4198
                                bestNodesRef->right = NULL;
 
4199
                                result |= SYNCTEX_MASK_LEFT;
 
4200
                        } else { /*  here off7 < 0 */
 
4201
                                off7 = -off7;
 
4202
                                if (bestDistancesRef->left > off7) {
 
4203
                                        bestDistancesRef->left = off7;
 
4204
                                        bestNodesRef->left = node;
 
4205
                                        result |= SYNCTEX_MASK_LEFT;
 
4206
                                } else if (bestDistancesRef->left == off7 && bestNodesRef->left) {
 
4207
                                        if (SYNCTEX_TAG(bestNodesRef->left) == SYNCTEX_TAG(node)
 
4208
                                                && (SYNCTEX_LINE(bestNodesRef->left) > SYNCTEX_LINE(node)
 
4209
                                                        || (SYNCTEX_LINE(bestNodesRef->left) == SYNCTEX_LINE(node)
 
4210
                                                                && SYNCTEX_COLUMN(bestNodesRef->left) > SYNCTEX_COLUMN(node)))) {
 
4211
                                                bestNodesRef->left = node;
 
4212
                                                result |= SYNCTEX_MASK_LEFT;
 
4213
                                        }
 
4214
                                }
 
4215
                        }
 
4216
                } while((node = SYNCTEX_SIBLING(node)));
 
4217
                if (result & SYNCTEX_MASK_LEFT) {
 
4218
                        /*  the left node is new, try to narrow the result */
 
4219
                        if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->left,visible))) {
 
4220
                                bestNodesRef->left = node;
 
4221
                        } 
 
4222
                        if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) {
 
4223
                                bestNodesRef->left = node;
 
4224
                        } 
 
4225
                }
 
4226
                if (result & SYNCTEX_MASK_RIGHT) {
 
4227
                        /*  the right node is new, try to narrow the result */
 
4228
                        if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->right,visible))) {
 
4229
                                bestNodesRef->right = node;
 
4230
                        } 
 
4231
                        if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) {
 
4232
                                bestNodesRef->right = node;
 
4233
                        } 
 
4234
                }
 
4235
        }
 
4236
        return result;
 
4237
}
 
4238
SYNCTEX_INLINE static int _synctex_eq_get_closest_children_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_node_set_t*  bestNodesRef,synctex_distances_t*  bestDistancesRef,synctex_bool_t visible) {
 
4239
        if (node) {
 
4240
                switch(node->class->type) {
 
4241
                        case synctex_node_type_hbox:
 
4242
                                return __synctex_eq_get_closest_children_in_hbox(hitPoint, node, bestNodesRef, bestDistancesRef,visible);
 
4243
                        case synctex_node_type_vbox:
 
4244
                                return __synctex_eq_get_closest_children_in_vbox(hitPoint, node, bestNodesRef, bestDistancesRef,visible);
 
4245
                }
 
4246
        }
 
4247
        return 0;
 
4248
}
 
4249
 
 
4250
SYNCTEX_INLINE static synctex_node_t __synctex_eq_closest_child(synctex_point_t hitPoint, synctex_node_t node,int*  distanceRef, synctex_bool_t visible);
 
4251
SYNCTEX_INLINE static synctex_node_t __synctex_eq_closest_child(synctex_point_t hitPoint, synctex_node_t node,int*  distanceRef, synctex_bool_t visible) {
 
4252
        synctex_node_t best_node = NULL;
 
4253
        if ((node = SYNCTEX_CHILD(node))) {
 
4254
                do {
 
4255
                        int distance = _synctex_node_distance_to_point(hitPoint,node,visible);
 
4256
                        synctex_node_t candidate = NULL;
 
4257
                        if (distance<=*distanceRef) {
 
4258
                                *distanceRef = distance;
 
4259
                                best_node = node;
 
4260
                        }
 
4261
                        switch(node->class->type) {
 
4262
                                case synctex_node_type_vbox:
 
4263
                                case synctex_node_type_hbox:
 
4264
                                        if ((candidate = __synctex_eq_closest_child(hitPoint,node,distanceRef,visible))) {
 
4265
                                                best_node = candidate;
 
4266
                                        }
 
4267
                        }
 
4268
                } while((node = SYNCTEX_SIBLING(node)));
 
4269
        }
 
4270
        return best_node;
 
4271
}
 
4272
SYNCTEX_INLINE static synctex_node_t _synctex_eq_closest_child(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) {
 
4273
        if (node) {
 
4274
                switch(node->class->type) {
 
4275
                        case synctex_node_type_hbox:
 
4276
                        case synctex_node_type_vbox:
 
4277
                        {
 
4278
                                int best_distance = INT_MAX;
 
4279
                                synctex_node_t best_node = __synctex_eq_closest_child(hitPoint,node,&best_distance,visible);
 
4280
                                if ((best_node)) {
 
4281
                                        synctex_node_t child = NULL;
 
4282
                                        switch(best_node->class->type) {
 
4283
                                                case synctex_node_type_vbox:
 
4284
                                                case synctex_node_type_hbox:
 
4285
                                                        if ((child = SYNCTEX_CHILD(best_node))) {
 
4286
                                                                best_distance = _synctex_node_distance_to_point(hitPoint,child,visible);
 
4287
                                                                while((child = SYNCTEX_SIBLING(child))) {
 
4288
                                                                        int distance = _synctex_node_distance_to_point(hitPoint,child,visible);
 
4289
                                                                        if (distance<=best_distance) {
 
4290
                                                                                best_distance = distance;
 
4291
                                                                                best_node = child;
 
4292
                                                                        }
 
4293
                                                                }
 
4294
                                                        }
 
4295
                                        }
 
4296
                                }
 
4297
                                return best_node;
 
4298
                        }
 
4299
                }
 
4300
        }
 
4301
        return NULL;
 
4302
}
8413
4303
 
8414
4304
#       ifdef SYNCTEX_NOTHING
8415
4305
#       pragma mark -
8416
4306
#       pragma mark Updater
8417
4307
#   endif
8418
4308
 
8419
 
typedef int (*synctex_print_f)(synctex_updater_p, const char * , ...); /*  print formatted to either FILE *  or gzFile */
8420
 
typedef void (*synctex_close_f)(synctex_updater_p); /*  close FILE *  or gzFile */
 
4309
typedef int (*synctex_fprintf_t)(void *, const char * , ...); /*  print formatted to either FILE *  or gzFile */
8421
4310
 
8422
4311
#   define SYNCTEX_BITS_PER_BYTE 8
8423
4312
 
8424
 
typedef union {
8425
 
    gzFile as_gzFile;
8426
 
    FILE * as_FILE_p;
8427
 
    void * as_ptr;
8428
 
} synctex_file_u;
8429
 
 
8430
 
struct synctex_updater_t {
8431
 
    synctex_file_u file;
8432
 
    synctex_print_f print;
8433
 
    synctex_close_f close;
8434
 
    int length;             /*  the number of chars appended */
 
4313
struct __synctex_updater_t {
 
4314
    gzFile file;                /*  the foo.synctex or foo.synctex.gz I/O identifier  */
 
4315
    synctex_fprintf_t fprintf;  /*  either fprintf or gzprintf */
 
4316
    int length;                 /*  the number of chars appended */
 
4317
    struct _flags {
 
4318
        unsigned int no_gz:1;   /*  Whether zlib is used or not */
 
4319
        unsigned int reserved:SYNCTEX_BITS_PER_BYTE*sizeof(int)-1; /*  Align */
 
4320
        } flags;
8435
4321
};
8436
 
 
8437
 
__attribute__((__format__ (__printf__, 2, 3)))
8438
 
static int _synctex_updater_print(synctex_updater_p updater, const char * format, ...) {
8439
 
    int result = 0;
8440
 
    if (updater) {
8441
 
        va_list va;
8442
 
        va_start(va, format);
8443
 
        result = vfprintf(updater->file.as_FILE_p,
8444
 
                           format,
8445
 
                           va);
8446
 
        va_end(va);
8447
 
    }
8448
 
    return result;
8449
 
}
8450
 
#if defined(_MSC_VER)
8451
 
#include <stdio.h>
8452
 
#include <stdlib.h>
8453
 
#include <stdarg.h>
8454
 
 
8455
 
static int vasprintf(char **ret,
8456
 
                     const char *format,
8457
 
                     va_list ap)
8458
 
{
8459
 
    int len;
8460
 
    len = _vsnprintf(NULL, 0, format, ap);
8461
 
    if (len < 0) return -1;
8462
 
    *ret = malloc(len + 1);
8463
 
    if (!*ret) return -1;
8464
 
    _vsnprintf(*ret, len+1, format, ap);
8465
 
    (*ret)[len] = '\0';
8466
 
    return len;
8467
 
}
8468
 
 
8469
 
#endif
8470
 
 
8471
 
/**
8472
 
 *  gzvprintf is not available until OSX 10.10
8473
 
 */
8474
 
__attribute__((__format__ (__printf__, 2, 3)))
8475
 
static int _synctex_updater_print_gz(synctex_updater_p updater, const char * format, ...) {
8476
 
    int result = 0;
8477
 
    if (updater) {
8478
 
        char * buffer;
8479
 
        va_list va;
8480
 
        va_start(va, format);
8481
 
        if (vasprintf(&buffer, format, va) < 0) {
8482
 
            _synctex_error("Out of memory...");
8483
 
        } else if ((result = (int)strlen(buffer))) {
8484
 
            result = gzwrite(updater->file.as_gzFile, buffer, (unsigned)result);
8485
 
        }
8486
 
        va_end(va);
8487
 
        free(buffer);
8488
 
    }
8489
 
    return result;
8490
 
}
8491
 
 
8492
 
static void _synctex_updater_close(synctex_updater_p updater) {
8493
 
    if (updater) {
8494
 
        fclose(updater->file.as_FILE_p);
8495
 
    }
8496
 
}
8497
 
 
8498
 
static void _synctex_updater_close_gz(synctex_updater_p updater) {
8499
 
    if (updater) {
8500
 
        gzclose(updater->file.as_gzFile);
8501
 
    }
8502
 
}
8503
 
 
8504
 
synctex_updater_p synctex_updater_new_with_output_file(const char * output, const char * build_directory) {
8505
 
    synctex_updater_p updater = NULL;
8506
 
    const char * mode = NULL;
8507
 
    synctex_open_s open;
8508
 
    /*  prepare the updater, the memory is the only one dynamically allocated */
8509
 
    updater = (synctex_updater_p)_synctex_malloc(sizeof(synctex_updater_s));
8510
 
    if (NULL == updater) {
8511
 
        _synctex_error("!  synctex_updater_new_with_file: malloc problem");
8512
 
        return NULL;
8513
 
    }
8514
 
    open = _synctex_open_v2(output,build_directory,0,synctex_ADD_QUOTES);
8515
 
    if (open.status < SYNCTEX_STATUS_OK) {
8516
 
        open = _synctex_open_v2(output,build_directory,0,synctex_DONT_ADD_QUOTES);
8517
 
        if (open.status < SYNCTEX_STATUS_OK) {
8518
 
        return_on_error:
8519
 
            _synctex_free(updater);
8520
 
            return updater = NULL;
8521
 
        }
8522
 
    }
8523
 
    /*  OK, the file exists, we close it and reopen it with the correct mode.
 
4322
#   define SYNCTEX_FILE updater->file
 
4323
#   define SYNCTEX_NO_GZ ((updater->flags).no_gz)
 
4324
#   define SYNCTEX_fprintf (*(updater->fprintf))
 
4325
 
 
4326
synctex_updater_t synctex_updater_new_with_output_file(const char * output, const char * build_directory) {
 
4327
        synctex_updater_t updater = NULL;
 
4328
        char * synctex = NULL;
 
4329
        synctex_io_mode_t io_mode = 0;
 
4330
        const char * mode = NULL;
 
4331
        /*  prepare the updater, the memory is the only one dynamically allocated */
 
4332
        updater = (synctex_updater_t)_synctex_malloc(sizeof(synctex_updater_t));
 
4333
        if (NULL == updater) {
 
4334
                _synctex_error("!  synctex_updater_new_with_file: malloc problem");
 
4335
                return NULL;
 
4336
        }
 
4337
        if (_synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_ADD_QUOTES,&io_mode)
 
4338
                && _synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_DONT_ADD_QUOTES,&io_mode)) {
 
4339
return_on_error:
 
4340
                free(updater);
 
4341
        updater = NULL;
 
4342
                return NULL;
 
4343
        }
 
4344
        /*  OK, the file exists, we close it and reopen it with the correct mode.
8524
4345
     *  The receiver is now the owner of the "synctex" variable. */
8525
 
    gzclose(open.file);
8526
 
    updater->file.as_ptr = NULL;
8527
 
    mode = _synctex_get_io_mode_name(open.io_mode|synctex_io_append_mask);/* either "a" or "ab", depending on the file extension */
8528
 
    if (open.io_mode&synctex_io_gz_mask) {
8529
 
        if (NULL == (updater->file.as_FILE_p = fopen(open.synctex,mode))) {
8530
 
        no_write_error:
8531
 
            _synctex_error("!  synctex_updater_new_with_file: Can't append to %s",open.synctex);
8532
 
            free(open.synctex);
8533
 
            goto return_on_error;
8534
 
        }
8535
 
        updater->print = &_synctex_updater_print;
8536
 
        updater->close = &_synctex_updater_close;
8537
 
    } else {
8538
 
        if (NULL == (updater->file.as_gzFile = gzopen(open.synctex,mode))) {
8539
 
            goto no_write_error;
8540
 
        }
8541
 
        updater->print = &_synctex_updater_print_gz;
8542
 
        updater->close = &_synctex_updater_close_gz;
8543
 
    }
8544
 
    printf("SyncTeX: updating %s...",open.synctex);
8545
 
    _synctex_free(open.synctex);
8546
 
    return updater;
8547
 
}
8548
 
 
8549
 
void synctex_updater_append_magnification(synctex_updater_p updater, char * magnification){
8550
 
    if (NULL==updater) {
8551
 
        return;
8552
 
    }
8553
 
    if (magnification && strlen(magnification)) {
8554
 
        updater->length +=
8555
 
        updater->print(updater,"Magnification:%s\n",magnification);
8556
 
    }
8557
 
}
8558
 
 
8559
 
void synctex_updater_append_x_offset(synctex_updater_p updater, char * x_offset){
8560
 
    if (NULL==updater) {
8561
 
        return;
8562
 
    }
8563
 
    if (x_offset && strlen(x_offset)) {
8564
 
        updater->length += updater->print(updater,"X Offset:%s\n",x_offset);
8565
 
    }
8566
 
}
8567
 
 
8568
 
void synctex_updater_append_y_offset(synctex_updater_p updater, char * y_offset){
8569
 
    if (NULL==updater) {
8570
 
        return;
8571
 
    }
8572
 
    if (y_offset && strlen(y_offset)) {
8573
 
        updater->length += updater->print(updater,"Y Offset:%s\n",y_offset);
8574
 
    }
8575
 
}
8576
 
 
8577
 
void synctex_updater_free(synctex_updater_p updater){
8578
 
    if (NULL==updater) {
8579
 
        return;
8580
 
    }
8581
 
    if (updater->length>0) {
8582
 
        updater->print(updater,"!%i\n",updater->length);
8583
 
    }
8584
 
    updater->close(updater);
8585
 
    _synctex_free(updater);
8586
 
    printf("... done.\n");
8587
 
    return;
8588
 
}
8589
 
#endif
8590
 
 
8591
 
#if defined(SYNCTEX_TESTING)
8592
 
#       ifdef SYNCTEX_NOTHING
8593
 
#       pragma mark -
8594
 
#       pragma mark Testers
8595
 
#   endif
8596
 
/**
8597
 
 *  The next nodes corresponds to a deep first tree traversal.
8598
 
 *  Does not create child proxies as side effect contrary to
8599
 
 *  the synctex_node_next method above.
8600
 
 *  May loop infinitely many times if the tree
8601
 
 *  is not properly built (contains loops).
8602
 
 */
8603
 
static synctex_node_p _synctex_node_next(synctex_node_p node) {
8604
 
    synctex_node_p N = _synctex_tree_child(node);
8605
 
    if (N) {
8606
 
        return N;
8607
 
    }
8608
 
    return _synctex_node_sibling_or_parents(node);
8609
 
}
8610
 
static int _synctex_input_copy_name(synctex_node_p input, char * name) {
8611
 
    char * copy = _synctex_malloc(strlen(name)+1);
8612
 
    memcpy(copy,name,strlen(name)+1);
8613
 
    _synctex_data_set_name(input,copy);
8614
 
    return 0;
8615
 
}
8616
 
int synctex_test_setup_scanner_sheets_421(synctex_scanner_p scanner) {
8617
 
    int TC = 0;
8618
 
    synctex_node_p sheet = synctex_node_new(scanner,synctex_node_type_sheet);
8619
 
    _synctex_data_set_page(sheet,4);
8620
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==4,"");
8621
 
    synctex_node_free(scanner->sheet);
8622
 
    scanner->sheet = sheet;
8623
 
    sheet = synctex_node_new(scanner,synctex_node_type_sheet);
8624
 
    _synctex_data_set_page(sheet,2);
8625
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==2,"");
8626
 
    __synctex_tree_set_sibling(sheet, scanner->sheet);
8627
 
    scanner->sheet = sheet;
8628
 
    sheet = synctex_node_new(scanner,synctex_node_type_sheet);
8629
 
    _synctex_data_set_page(sheet,1);
8630
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==1,"");
8631
 
    __synctex_tree_set_sibling(sheet, scanner->sheet);
8632
 
    scanner->sheet = sheet;
8633
 
    return TC;
8634
 
}
8635
 
int synctex_test_input(synctex_scanner_p scanner) {
8636
 
    int TC = 0;
8637
 
    synctex_node_p input = synctex_node_new(scanner,synctex_node_type_input);
8638
 
    _synctex_data_set_tag(input,421);
8639
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==421,"");
8640
 
    _synctex_data_set_tag(input,124);
8641
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==124,"");
8642
 
    _synctex_data_set_line(input,421);
8643
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==421,"");
8644
 
    _synctex_data_set_line(input,214);
8645
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==214,"");
8646
 
    _synctex_data_set_line(input,214);
8647
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==214,"");
8648
 
    _synctex_input_copy_name(input,"214");
8649
 
    SYNCTEX_TEST_BODY(TC, 0==memcmp(_synctex_data_name(input),"214",4),"");
8650
 
    _synctex_input_copy_name(input,"421421");
8651
 
 
8652
 
    SYNCTEX_TEST_BODY(TC,
8653
 
                      0==memcmp(_synctex_data_name(input),
8654
 
                                "421421",
8655
 
                                4),
8656
 
                      "");
8657
 
    synctex_node_free(input);
8658
 
    return TC;
8659
 
}
8660
 
int synctex_test_proxy(synctex_scanner_p scanner) {
8661
 
    int TC = 0;
8662
 
    synctex_node_p proxy = synctex_node_new(scanner,synctex_node_type_proxy);
8663
 
    synctex_node_p target = synctex_node_new(scanner,synctex_node_type_rule);
8664
 
    _synctex_tree_set_target(proxy,target);
8665
 
    _synctex_data_set_tag(target,421);
8666
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==421,"");
8667
 
    SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==421,"");
8668
 
    SYNCTEX_TEST_BODY(TC, synctex_node_tag(proxy)==421,"");
8669
 
    synctex_node_free(proxy);
8670
 
    synctex_node_free(target);
8671
 
    return TC;
8672
 
}
8673
 
int synctex_test_handle(synctex_scanner_p scanner) {
8674
 
    int TC = 0;
8675
 
    synctex_node_p handle = synctex_node_new(scanner,synctex_node_type_handle);
8676
 
    synctex_node_p proxy = synctex_node_new(scanner, synctex_node_type_proxy);
8677
 
    synctex_node_p target = synctex_node_new(scanner,synctex_node_type_rule);
8678
 
    _synctex_tree_set_target(handle,target);
8679
 
    _synctex_data_set_tag(target,421);
8680
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==421,"");
8681
 
    SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==421,"");
8682
 
    SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle)==421,"");
8683
 
    _synctex_data_set_line(target,214);
8684
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_line(target)==214,"");
8685
 
    SYNCTEX_TEST_BODY(TC, synctex_node_line(target)==214,"");
8686
 
    SYNCTEX_TEST_BODY(TC, synctex_node_line(handle)==214,"");
8687
 
    _synctex_data_set_column(target,142);
8688
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_column(target)==142,"");
8689
 
    SYNCTEX_TEST_BODY(TC, synctex_node_column(target)==142,"");
8690
 
    SYNCTEX_TEST_BODY(TC, synctex_node_column(handle)==142,"");
8691
 
    _synctex_tree_set_target(proxy,target);
8692
 
    _synctex_tree_set_target(handle,proxy);
8693
 
    _synctex_data_set_tag(target,412);
8694
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==412,"");
8695
 
    SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==412,"");
8696
 
    SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle)==412,"");
8697
 
    _synctex_data_set_line(target,124);
8698
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_line(target)==124,"");
8699
 
    SYNCTEX_TEST_BODY(TC, synctex_node_line(target)==124,"");
8700
 
    SYNCTEX_TEST_BODY(TC, synctex_node_line(handle)==124,"");
8701
 
    _synctex_data_set_column(target,241);
8702
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_column(target)==241,"");
8703
 
    SYNCTEX_TEST_BODY(TC, synctex_node_column(target)==241,"");
8704
 
    SYNCTEX_TEST_BODY(TC, synctex_node_column(handle)==241,"");
8705
 
    synctex_node_free(handle);
8706
 
    synctex_node_free(proxy);
8707
 
    synctex_node_free(target);
8708
 
    return TC;
8709
 
}
8710
 
int synctex_test_setup_scanner_input(synctex_scanner_p scanner) {
8711
 
    int TC = 0;
8712
 
    synctex_node_p input = synctex_node_new(scanner,synctex_node_type_input);
8713
 
    _synctex_data_set_tag(input,4);
8714
 
    _synctex_input_copy_name(input,"21");
8715
 
    _synctex_data_set_line(input,421);
8716
 
    synctex_node_free(scanner->input);
8717
 
    scanner->input = input;
8718
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==4,"");
8719
 
    SYNCTEX_TEST_BODY(TC, strcmp(_synctex_data_name(input),"21")==0,"");
8720
 
    SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==421,"");
8721
 
    return TC;
8722
 
}
8723
 
int synctex_test_setup_nodes(synctex_scanner_p scanner, synctex_node_r nodes) {
8724
 
    int TC = 0;
8725
 
    int n;
8726
 
    for (n=0;n<synctex_node_number_of_types;++n) {
8727
 
        nodes[n] = synctex_node_new(scanner,n);
8728
 
        SYNCTEX_TEST_BODY(TC, nodes[n]!=NULL,"");
8729
 
    }
8730
 
    return TC;
8731
 
}
8732
 
int synctex_test_teardown_nodes(synctex_scanner_p scanner, synctex_node_r nodes) {
8733
 
    int n;
8734
 
    for (n=0;n<synctex_node_number_of_types;++n) {
8735
 
        synctex_node_free(nodes[n]);
8736
 
        nodes[n]=NULL;
8737
 
    }
8738
 
    return 1;
8739
 
}
8740
 
int synctex_test_tree(synctex_scanner_p scanner) {
8741
 
    int TC = 0;
8742
 
    synctex_node_p nodes1[synctex_node_number_of_types];
8743
 
    synctex_node_p nodes2[synctex_node_number_of_types];
8744
 
    synctex_node_p nodes3[synctex_node_number_of_types];
8745
 
    int i,j;
8746
 
    TC += synctex_test_setup_nodes(scanner,nodes1);
8747
 
    TC += synctex_test_setup_nodes(scanner,nodes2);
8748
 
    TC += synctex_test_setup_nodes(scanner,nodes3);
8749
 
    /*  Every node has a sibling */
8750
 
    for (i=0;i<synctex_node_number_of_types;++i) {
8751
 
        for (j=0;j<synctex_node_number_of_types;++j) {
8752
 
            _synctex_tree_set_sibling(nodes1[i],nodes2[i]);
8753
 
            SYNCTEX_TEST_BODY(TC, nodes2[i]==synctex_node_sibling(nodes1[i]),"");
8754
 
        }
8755
 
    }
8756
 
    synctex_test_teardown_nodes(scanner,nodes3);
8757
 
    synctex_test_teardown_nodes(scanner,nodes2);
8758
 
    synctex_test_teardown_nodes(scanner,nodes1);
8759
 
    return TC;
8760
 
}
8761
 
int synctex_test_page(synctex_scanner_p scanner) {
8762
 
    int TC = synctex_test_setup_scanner_sheets_421(scanner);
8763
 
    synctex_node_p sheet = scanner->sheet;
8764
 
    synctex_node_p node = synctex_node_new(scanner,synctex_node_type_rule);
8765
 
    _synctex_data_set_tag(node,4);
8766
 
    _synctex_data_set_line(node,21);
8767
 
    synctex_node_free(_synctex_node_set_child(sheet,node));
8768
 
    SYNCTEX_TEST_BODY(TC, synctex_node_page(node)==synctex_node_page(sheet),"");
8769
 
    return TC;
8770
 
}
8771
 
int synctex_test_display_query(synctex_scanner_p scanner) {
8772
 
    int TC = synctex_test_setup_scanner_sheets_421(scanner);
8773
 
    synctex_node_p sheet = scanner->sheet;
8774
 
    synctex_node_p node = synctex_node_new(scanner,synctex_node_type_rule);
8775
 
    _synctex_data_set_tag(node,4);
8776
 
    _synctex_data_set_line(node,21);
8777
 
    synctex_node_free(_synctex_node_set_child(sheet,node));
8778
 
    SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),"");
8779
 
    __synctex_node_make_friend_tlc(node);
8780
 
    SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25)==node,"");
8781
 
    sheet = __synctex_tree_sibling(sheet);
8782
 
    node = synctex_node_new(scanner,synctex_node_type_rule);
8783
 
    _synctex_data_set_tag(node,4);
8784
 
    _synctex_data_set_line(node,21);
8785
 
    synctex_node_free(_synctex_node_set_child(sheet,node));
8786
 
    SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),"");
8787
 
    __synctex_node_make_friend_tlc(node);
8788
 
    SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25)==node,"");
8789
 
    sheet = __synctex_tree_sibling(sheet);
8790
 
    node = synctex_node_new(scanner,synctex_node_type_rule);
8791
 
    _synctex_data_set_tag(node,4);
8792
 
    _synctex_data_set_line(node,21);
8793
 
    synctex_node_free(_synctex_node_set_child(sheet,node));
8794
 
    SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),"");
8795
 
    __synctex_node_make_friend_tlc(node);
8796
 
    SYNCTEX_TEST_BODY(TC, (_synctex_scanner_friend(scanner, 25)==node),"");
8797
 
    synctex_test_setup_scanner_input(scanner);
8798
 
    scanner->flags.has_parsed = synctex_YES;
8799
 
#if 1
8800
 
    SYNCTEX_TEST_BODY(TC, (synctex_display_query(scanner,"21",21,4,-1)==3),"");
8801
 
#endif
8802
 
    return TC;
8803
 
}
8804
 
typedef struct {
8805
 
    int s;      /* status */
8806
 
    char n[25]; /* name */
8807
 
} synctex_test_sn_s;
8808
 
 
8809
 
synctex_test_sn_s synctex_test_tmp_sn(char * content) {
8810
 
    synctex_test_sn_s sn = {0, "/tmp/test.XXXXXX.synctex"};
8811
 
    FILE *sfp;
8812
 
    int fd = mkstemps(sn.n,8);
8813
 
    if (fd < 0) {
8814
 
        fprintf(stderr, "%s: %s\n", sn.n, strerror(errno));
8815
 
        sn.s = -1;
8816
 
        return sn;
8817
 
    }
8818
 
    if ((sfp = fdopen(fd, "w+")) == NULL) {
8819
 
        unlink(sn.n);
8820
 
        close(fd);
8821
 
        fprintf(stderr, "%s: %s\n", sn.n, strerror(errno));
8822
 
        sn.s = -2;
8823
 
        return sn;
8824
 
    }
8825
 
    sn.s = fputs(content,sfp);
8826
 
    printf("temp:%s\n%i\n",sn.n,sn.s);
8827
 
    fclose(sfp);
8828
 
    if (sn.s==0) {
8829
 
        sn.s = -2;
8830
 
        unlink(sn.n);
8831
 
    }
8832
 
    return sn;
8833
 
}
8834
 
int synctex_test_sheet_1() {
8835
 
    int TC = 0;
8836
 
    char * content =
8837
 
    "SyncTeX Version:1  \n" /*00-19*/
8838
 
    "Input:1:./1.tex    \n" /*20-39*/
8839
 
    "Output:pdf         \n" /*40-59*/
8840
 
    "Magnification:100000000      \n" /*60-89*/
8841
 
    "Unit:1   \n"           /*90-99*/
8842
 
    "X Offset:0         \n" /*00-19*/
8843
 
    "Y Offset:0         \n" /*20-39*/
8844
 
    "Content: \n"           /*40-49*/
8845
 
    "{1       \n"           /*50-59*/
8846
 
    "[1,10:20,350:330,330,0       \n" /*60-89*/
8847
 
    "]        \n"           /*90-99*/
8848
 
    "}        \n"           /*00-09*/
8849
 
    "Postamble:\n";
8850
 
    synctex_test_sn_s sn = synctex_test_tmp_sn(content);
8851
 
    if (sn.s>0) {
8852
 
        synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES);
8853
 
        synctex_node_p node = synctex_scanner_handle(scanner);
8854
 
        printf("Created nodes:\n");
8855
 
        while (node) {
8856
 
            printf("%s\n",_synctex_node_abstract(node));
8857
 
            node = synctex_node_next(node);
8858
 
        }
8859
 
        synctex_scanner_free(scanner);
8860
 
        unlink(sn.n);
8861
 
    } else {
8862
 
        ++TC;
8863
 
    }
8864
 
    return TC;
8865
 
}
8866
 
int synctex_test_sheet_2() {
8867
 
    int TC = 0;
8868
 
    char * content =
8869
 
    "SyncTeX Version:1  \n" /*00-19*/
8870
 
    "Input:1:./1.tex    \n" /*20-39*/
8871
 
    "Output:pdf         \n" /*40-59*/
8872
 
    "Magnification:100000000      \n" /*60-89*/
8873
 
    "Unit:1   \n"           /*90-99*/
8874
 
    "X Offset:0         \n" /*00-19*/
8875
 
    "Y Offset:0         \n" /*20-39*/
8876
 
    "Content: \n"           /*40-49*/
8877
 
    "{1       \n"           /*50-59*/
8878
 
    "(1,10:20,350:330,330,0       \n" /*60-89*/
8879
 
    ")        \n"           /*90-99*/
8880
 
    "}        \n"           /*00-09*/
8881
 
    "Postamble:\n";
8882
 
    synctex_test_sn_s sn = synctex_test_tmp_sn(content);
8883
 
    if (sn.s>0) {
8884
 
        synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES);
8885
 
        synctex_node_p node = synctex_scanner_handle(scanner);
8886
 
        printf("Created nodes:\n");
8887
 
        while (node) {
8888
 
            printf("%s\n",_synctex_node_abstract(node));
8889
 
            node = _synctex_node_next(node);
8890
 
        }
8891
 
        TC += synctex_scanner_free(scanner);
8892
 
        unlink(sn.n);
8893
 
    } else {
8894
 
        ++TC;
8895
 
    }
8896
 
    return TC;
8897
 
}
8898
 
int synctex_test_charindex() {
8899
 
    int TC = 0;
8900
 
    char * content =
8901
 
    "SyncTeX Version:1  \n" /*00-19*/
8902
 
    "Input:1:./1.tex    \n" /*20-39*/
8903
 
    "Output:pdf         \n" /*40-59*/
8904
 
    "Magnification:100000000      \n" /*60-89*/
8905
 
    "Unit:1   \n"           /*90-99*/
8906
 
    "X Offset:0         \n" /*00-19*/
8907
 
    "Y Offset:0         \n" /*20-39*/
8908
 
    "Content: \n"           /*40-49*/
8909
 
    "{1       \n"           /*50-59*/
8910
 
    "[1,10:20,350:330,330,0       \n" /*60-89*/
8911
 
    "(1,58:20,100:250,10,5        \n" /*90-119*/
8912
 
    "f1000:50,100       \n" /*20-39*/
8913
 
    ")        \n"           /*40-49*/
8914
 
    "]        \n"           /*50-59*/
8915
 
    "}        \n"           /*60-69*/
8916
 
    "Postamble:\n";
8917
 
    synctex_test_sn_s sn = synctex_test_tmp_sn(content);
8918
 
    if (sn.s>0) {
8919
 
        synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES);
8920
 
        synctex_node_p node = synctex_scanner_handle(scanner);
8921
 
        printf("Created nodes:\n");
8922
 
        while (node) {
8923
 
            printf("%s\n",_synctex_node_abstract(node));
8924
 
            node = synctex_node_next(node);
8925
 
        }
8926
 
        TC += synctex_scanner_free(scanner);
8927
 
        unlink(sn.n);
8928
 
    } else {
8929
 
        ++TC;
8930
 
    }
8931
 
    return TC;
8932
 
}
8933
 
int synctex_test_form() {
8934
 
    int TC = 0;
8935
 
    char * content =
8936
 
    "SyncTeX Version:1  \n" /*00-19*/
8937
 
    "Input:1:./1.tex    \n" /*20-39*/
8938
 
    "Output:pdf         \n" /*40-59*/
8939
 
    "Magnification:100000000      \n" /*60-89*/
8940
 
    "Unit:1   \n"           /*90-99*/
8941
 
    "X Offset:0         \n" /*00-19*/
8942
 
    "Y Offset:0         \n" /*20-39*/
8943
 
    "Content: \n"           /*40-49*/
8944
 
    "{1       \n"           /*50-59*/
8945
 
    "[1,10:20,350:330,330,0       \n" /*60-89*/
8946
 
    "(1,58:20,100:250,10,5        \n" /*90-119*/
8947
 
    "f1000:50,100       \n" /*20-39*/
8948
 
    ")        \n"           /*40-49*/
8949
 
    "]        \n"           /*50-59*/
8950
 
    "}        \n"           /*60-69*/
8951
 
    "<1000    \n"           /*70-79*/
8952
 
    "(1,63:0,0:100,8,3  \n" /*80-99*/
8953
 
    ")        \n"           /*00-09*/
8954
 
    ">        \n"           /*10-19*/
8955
 
    "Postamble:\n";
8956
 
    synctex_test_sn_s sn = synctex_test_tmp_sn(content);
8957
 
    if (sn.s>0) {
8958
 
        synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES);
8959
 
        synctex_node_p node = synctex_scanner_handle(scanner);
8960
 
        while (node) {
8961
 
            printf("%s\n",_synctex_node_abstract(node));
8962
 
            node = _synctex_node_next(node);
8963
 
        }
8964
 
        TC += synctex_scanner_free(scanner);
8965
 
        unlink(sn.n);
8966
 
    } else {
8967
 
        ++TC;
8968
 
    }
8969
 
    return TC;
8970
 
}
8971
 
#endif
 
4346
        gzclose(SYNCTEX_FILE);
 
4347
        SYNCTEX_FILE = NULL;
 
4348
        SYNCTEX_NO_GZ = (io_mode&synctex_io_gz_mask)?synctex_NO:synctex_YES;
 
4349
    mode = _synctex_get_io_mode_name(io_mode|synctex_io_append_mask);/* either "a" or "ab", depending on the file extension */
 
4350
        if (SYNCTEX_NO_GZ) {
 
4351
                if (NULL == (SYNCTEX_FILE = (void *)fopen(synctex,mode))) {
 
4352
no_write_error:
 
4353
                        _synctex_error("!  synctex_updater_new_with_file: Can't append to %s",synctex);
 
4354
                        free(synctex);
 
4355
                        goto return_on_error;
 
4356
                }
 
4357
                updater->fprintf = (synctex_fprintf_t)(&fprintf);
 
4358
        } else {
 
4359
                if (NULL == (SYNCTEX_FILE = (void *)gzopen(synctex,mode))) {
 
4360
                        goto no_write_error;
 
4361
                }
 
4362
                updater->fprintf = (synctex_fprintf_t)(&gzprintf);
 
4363
        }
 
4364
        printf("SyncTeX: updating %s...",synctex);
 
4365
        free(synctex);
 
4366
        return updater;
 
4367
}
 
4368
 
 
4369
 
 
4370
void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification){
 
4371
        if (NULL==updater) {
 
4372
                return;
 
4373
        }
 
4374
        if (magnification && strlen(magnification)) {
 
4375
                updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Magnification:%s\n",magnification);
 
4376
        }
 
4377
}
 
4378
 
 
4379
void synctex_updater_append_x_offset(synctex_updater_t updater, char * x_offset){
 
4380
        if (NULL==updater) {
 
4381
                return;
 
4382
        }
 
4383
        if (x_offset && strlen(x_offset)) {
 
4384
                updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"X Offset:%s\n",x_offset);
 
4385
        }
 
4386
}
 
4387
 
 
4388
void synctex_updater_append_y_offset(synctex_updater_t updater, char * y_offset){
 
4389
        if (NULL==updater) {
 
4390
                return;
 
4391
        }
 
4392
        if (y_offset && strlen(y_offset)) {
 
4393
                updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Y Offset:%s\n",y_offset);
 
4394
        }
 
4395
}
 
4396
 
 
4397
void synctex_updater_free(synctex_updater_t updater){
 
4398
        if (NULL==updater) {
 
4399
                return;
 
4400
        }
 
4401
        if (updater->length>0) {
 
4402
                SYNCTEX_fprintf(SYNCTEX_FILE,"!%i\n",updater->length);
 
4403
        }
 
4404
        if (SYNCTEX_NO_GZ) {
 
4405
                fclose((FILE *)SYNCTEX_FILE);
 
4406
        } else {
 
4407
                gzclose((gzFile)SYNCTEX_FILE);
 
4408
        }
 
4409
        free(updater);
 
4410
        printf("... done.\n");
 
4411
        return;
 
4412
}