111
81
#include <locale.h>
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 )
119
# define SYNCTEX_UNUSED(x) (void)(x);
122
#include "synctex_parser_advanced.h"
124
SYNCTEX_INLINE static int _synctex_abs(int x) {
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.
94
#include "synctex_parser.h"
95
#include "synctex_parser_utils.h"
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";
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);
137
* - author: J. Laurens
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.
149
/* 8 fields + size: spcflnat */
150
typedef struct synctex_tree_model_t {
160
} synctex_tree_model_s;
161
typedef const synctex_tree_model_s * synctex_tree_model_p;
163
typedef struct synctex_data_model_t {
182
} synctex_data_model_s;
184
typedef const synctex_data_model_s * synctex_data_model_p;
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) {
197
static const synctex_tlcpector_s synctex_tlcpector_none = {
198
&_synctex_int_none, /* tag */
199
&_synctex_int_none, /* line */
200
&_synctex_int_none, /* column */
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 */
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) {
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 */
238
typedef const synctex_vispector_s * synctex_vispector_p;
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;
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...
262
typedef synctex_node_p synctex_proxy_p;
263
typedef synctex_node_p synctex_noxy_p;
265
# ifdef SYNCTEX_NOTHING
267
# pragma mark Abstract OBJECTS and METHODS
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
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__);\
284
* Free the given node by sending the free message.
285
* - parameter NODE: of type synctex_node_p
287
static void synctex_node_free(synctex_node_p node) {
288
SYNCTEX_MSG_SEND(node,free);
290
# if defined(SYNCTEX_TESTING)
291
# if !defined(SYNCTEX_USE_HANDLE)
292
# define SYNCTEX_USE_HANDLE 1
294
# if !defined(SYNCTEX_USE_CHARINDEX)
295
# define SYNCTEX_USE_CHARINDEX 1
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)
307
# define SYNCTEX_SCANNER_FREE_HANDLE(SCANR)
308
# define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT)
309
# define SYNCTEX_REGISTER_HANDLE_TO(NODE)
101
/* each synctex node has a class */
102
typedef struct __synctex_class_t _synctex_class_t;
103
typedef _synctex_class_t * synctex_class_t;
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.
116
typedef union _synctex_info_t {
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));
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)
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;
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.
155
typedef synctex_node_t *(*_synctex_node_getter_t)(synctex_node_t);
156
typedef synctex_info_t *(*_synctex_info_getter_t)(synctex_node_t);
158
struct __synctex_class_t {
159
synctex_scanner_t scanner;
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;
353
173
# ifdef SYNCTEX_NOTHING
355
# pragma mark Tree SETGET
175
# pragma mark Abstract OBJECTS and METHODS
358
#if SYNCTEX_DEBUG > 1000
359
#define SYNCTEX_PARAMETER_ASSERT(WHAT) \
362
printf("! Parameter failure: %s\n",#WHAT); \
365
#define DEFINE_SYNCTEX_TREE_HAS(WHAT)\
366
static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node) {\
368
if (node->class_->navigator->WHAT>=0) {\
369
return synctex_YES; \
371
printf("WARNING: NO tree %s for %s\n", #WHAT, synctex_node_isa(node));\
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));\
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;\
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);\
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;\
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; \
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;\
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;\
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)
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)
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)
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)
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.
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)
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);
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);
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)
476
#if SYNCTEX_DEBUG>1000
477
# undef SYNCTEX_USE_NODE_COUNT
478
# define SYNCTEX_USE_NODE_COUNT 1
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)
485
# define SYNCTEX_DECLARE_NODE_COUNT
486
# define SYNCTEX_INIT_NODE_COUNT
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)
493
# define SYNCTEX_DID_NEW(N)
494
# define SYNCTEX_WILL_FREE(N)
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.
181
# define SYNCTEX_CAN_PERFORM(NODE,SELECTOR)\
182
(NULL!=((((NODE)->class))->SELECTOR))
184
/* This macro is some kind of objc_msg_send.
185
* It takes care of sending the proper message if possible.
187
# define SYNCTEX_MSG_SEND(NODE,SELECTOR) if (NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR)) {\
188
(*((((NODE)->class))->SELECTOR))(NODE);\
191
/* read only safe getter
193
# define SYNCTEX_GET(NODE,SELECTOR)((NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR))?SYNCTEX_GETTER(NODE,SELECTOR)[0]:(NULL))
197
# define SYNCTEX_GETTER(NODE,SELECTOR)\
198
((synctex_node_t *)((*((((NODE)->class))->SELECTOR))(NODE)))
200
# define SYNCTEX_FREE(NODE) SYNCTEX_MSG_SEND(NODE,free);
202
/* Parent getter and setter
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;\
209
/* Child getter and setter
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;\
217
/* Sibling getter and setter
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];\
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.
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;\
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.
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;\
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.
247
static void _synctex_free_node(synctex_node_t node) {
249
(*((node->class)->sibling))(node);
250
SYNCTEX_FREE(SYNCTEX_SIBLING(node));
251
SYNCTEX_FREE(SYNCTEX_CHILD(node));
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.
262
static void _synctex_free_leaf(synctex_node_t node) {
264
SYNCTEX_FREE(SYNCTEX_SIBLING(node));
498
269
# ifdef __SYNCTEX_WORK__
499
# include "/usr/local/include/node/zlib.h"
270
# include "/usr/include/zlib.h"
501
272
# include <zlib.h>
504
# ifdef SYNCTEX_NOTHING
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)
516
# define SYNCTEX_STATUS_ERROR (SYNCTEX_STATUS_EOF-1)
517
/* Parameter error: */
518
# define SYNCTEX_STATUS_BAD_ARGUMENT (SYNCTEX_STATUS_ERROR-1)
520
# ifdef SYNCTEX_NOTHING
522
# pragma mark File reader
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.
529
# define SYNCTEX_BUFFER_MIN_SIZE 32
530
# define SYNCTEX_BUFFER_SIZE 32768
532
#if SYNCTEX_BUFFER_SIZE >= UINT_MAX
533
# error BAD BUFFER SIZE(1)
535
#if SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE
536
# error BAD BUFFER SIZE(2)
539
typedef struct synctex_reader_t {
540
gzFile file; /* The (possibly compressed) file */
543
char * current; /* current location in the buffer */
544
char * start; /* start of the buffer */
545
char * end; /* end of the buffer */
550
SYNCTEX_DECLARE_CHAR_OFFSET
553
typedef synctex_reader_s * synctex_reader_p;
556
synctex_status_t status;
559
synctex_io_mode_t io_mode;
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.
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");
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");
589
free(quoteless_synctex_name);/* We MUST have quoteless_synctex_name<>synctex_name */
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;
597
/* now insert quotes. */
599
char * quoted = NULL;
600
if (_synctex_copy_with_quoting_last_path_component(open.synctex,"ed,size) || quoted == NULL) {
601
/* There was an error or quoting does not make sense: */
602
goto return_on_error;
604
quoteless_synctex_name = open.synctex;
605
open.synctex = quoted;
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;
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;
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;
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;
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;
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);
642
goto return_on_error;
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) {
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);
659
goto return_on_error;
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);
669
goto return_on_error;
671
/* The quote free file name should replace the old one:*/
673
open.synctex = quoteless_synctex_name;
674
quoteless_synctex_name = NULL;
677
/* The operation is successful, return the arguments by value. */
678
open.status = SYNCTEX_STATUS_OK;
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.
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) {
694
if (build_directory && strlen(build_directory)) {
698
synctex_bool_t is_absolute;
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);
704
size += strlen(output);
706
if ((build_output = (char *)_synctex_malloc(size))) {
708
build_output[0] = '\0';
710
if (build_output != strcpy(build_output,output)) {
711
_synctex_free(build_output);
714
build_output[lpc-output]='\0';
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);
724
/* Append the last path component of the output. */
725
if (build_output != strcat(build_output,lpc)) {
726
_synctex_free(build_output);
729
open = __synctex_open_v2(build_output,io_mode,add_quotes);
731
_synctex_free(build_output);
732
} /* if ((build_output... */
733
} /* if (build_directory...) */
736
static void synctex_reader_free(synctex_reader_p reader) {
738
_synctex_free(reader->output);
739
_synctex_free(reader->synctex);
740
_synctex_free(reader->start);
741
gzclose(reader->file);
742
_synctex_free(reader);
746
* Return reader on success.
747
* Deallocate reader and return NULL on failure.
749
static synctex_reader_p synctex_reader_init_with_output_file(synctex_reader_p reader, const char * output, const char * build_directory) {
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) {
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.");
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.");
780
synctex_reader_free(reader);
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;
795
# if defined(SYNCTEX_USE_HANDLE)
796
# define SYNCTEX_DECLARE_HANDLE synctex_node_p handle;
798
# define SYNCTEX_DECLARE_HANDLE
801
# ifdef SYNCTEX_NOTHING
803
# pragma mark SCANNER
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.
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 */
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 */
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 */
290
unsigned has_parsed:1; /* Whether the scanner has parsed its underlying synctex file. */
291
unsigned reserved:sizeof(unsigned)-1; /* alignment */
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 */
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.
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;
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);
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;
859
synctex_node_p sibling;
860
if (node == _synctex_tree_target(handle)) {
861
sibling = __synctex_tree_reset_sibling(handle);
863
__synctex_tree_set_sibling(arg_sibling, sibling);
865
node->class_->scanner->handle = sibling;
867
synctex_node_free(handle);
870
sibling = __synctex_tree_sibling(handle);
872
arg_sibling = handle;
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;
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),
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),
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.
904
static void _synctex_free_node(synctex_node_p 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));
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.
921
static void _synctex_free_handle_old(synctex_node_p handle) {
923
_synctex_free_handle_old(__synctex_tree_sibling(handle));
924
_synctex_free_handle_old(_synctex_tree_child(handle));
925
_synctex_free(handle);
929
static void _synctex_free_handle(synctex_node_p handle) {
931
synctex_node_p n = handle;
933
__synctex_tree_set_parent(n, NULL);
935
while ((nn = _synctex_tree_child(n))) {
936
__synctex_tree_set_parent(nn, n);
940
nn = __synctex_tree_sibling(n);
946
nn = __synctex_tree_parent(n);
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.
963
static void _synctex_free_leaf(synctex_node_p node) {
965
SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node);
966
SYNCTEX_WILL_FREE(node);
967
synctex_node_free(__synctex_tree_sibling(node));
974
SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts
976
# define SYNCTEX_CUR (scanner->reader->current)
977
# define SYNCTEX_START (scanner->reader->start)
978
# define SYNCTEX_END (scanner->reader->end)
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
991
#if defined(SYNCTEX_USE_CHARINDEX)
992
synctex_node_p synctex_scanner_handle(synctex_scanner_p scanner) {
993
return scanner? scanner->handle:NULL;
997
# ifdef SYNCTEX_NOTHING
999
# pragma mark Decoding prototypes
1004
synctex_status_t status;
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);
1013
synctex_status_t status;
1016
static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner);
1018
# ifdef SYNCTEX_NOTHING
1020
# pragma mark Data SETGET
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
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));\
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));\
1038
return __synctex_data_has_##WHAT(node);\
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));\
1045
SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node) {\
1046
return __synctex_data_has_##WHAT(node);\
1050
SYNCTEX_INLINE static synctex_data_p __synctex_data(synctex_node_p node) {
1051
return node->data+node->class_->navigator->size;
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;\
1061
static int _synctex_data_set_##WHAT(synctex_node_p node, int new_value) {\
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;\
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);\
1078
return SYNCTEX_STATUS_BAD_ARGUMENT;\
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);\
1089
return SYNCTEX_STATUS_BAD_ARGUMENT;\
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;\
1099
static char * _synctex_data_set_##WHAT(synctex_node_p node, char * new_value) {\
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;\
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);\
1116
return SYNCTEX_STATUS_BAD_ARGUMENT;\
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
310
# define SYNCTEX_CUR (scanner->buffer_cur)
311
# define SYNCTEX_START (scanner->buffer_start)
312
# define SYNCTEX_END (scanner->buffer_end)
1128
314
# ifdef SYNCTEX_NOTHING
1130
316
# pragma mark OBJECTS, their creators and destructors.
1133
# ifdef SYNCTEX_NOTHING
1134
# pragma mark input.
1137
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(tag)
1138
DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(line)
1139
DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(name)
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. */
1145
# define SYNCTEX_INPUT_MARK "Input:"
1147
static const synctex_tree_model_s synctex_tree_model_input = {
1148
synctex_tree_sibling_idx, /* sibling */
1154
-1, /* arg_sibling */
1156
synctex_tree_s_input_max
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 */
1174
synctex_data_input_name_idx, /* name */
1176
synctex_data_input_tln_max
1179
#define SYNCTEX_INSPECTOR_GETTER_F(WHAT)\
1180
&_synctex_data_##WHAT, &_synctex_data_set_##WHAT
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);
1188
static const synctex_tlcpector_s synctex_tlcpector_input = {
1189
&_synctex_data_tag, /* tag */
1190
&_synctex_int_none, /* line */
1191
&_synctex_int_none, /* column */
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 */
1210
SYNCTEX_DECLARE_CHARINDEX
1211
synctex_class_p class_;
1212
synctex_data_u data[synctex_tree_s_input_max+synctex_data_input_tln_max];
1215
static synctex_node_p _synctex_new_input(synctex_scanner_p scanner) {
1217
synctex_node_p node = _synctex_malloc(sizeof(synctex_input_s));
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);
1229
static void _synctex_free_input(synctex_node_p 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);
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
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.
1247
# ifdef SYNCTEX_NOTHING
1248
# pragma mark sheet.
1251
* Every node has the same structure, but not the same size.
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]
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
341
/* This macro defines implementation offsets
342
* It is only used for pointer values
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;\
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)
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;
1262
362
/* sheet node creator */
1264
#define DEFINE_synctex_new_scanned_NODE(NAME)\
1265
static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner) {\
1268
synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));\
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); \
364
#define DEFINE_synctex_new_NODE(NAME)\
365
static synctex_node_t _synctex_new_##NAME(synctex_scanner_t scanner) {\
367
synctex_node_t node = _synctex_malloc(sizeof(synctex_node_##NAME##_t));\
369
SYNCTEX_IMPLEMENT_CHARINDEX(node,0);\
371
node->class = scanner->class+synctex_node_type_##NAME;\
1279
/* NB: -1 in SYNCTEX_IMPLEMENT_CHARINDEX above because
1280
* the first char of the line has been scanned
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);
1287
static const synctex_tree_model_s synctex_tree_model_sheet = {
1288
synctex_tree_sibling_idx, /* sibling */
1290
synctex_tree_s_child_idx, /* child */
1293
synctex_tree_sc_next_hbox_idx, /* next_hbox */
1294
-1, /* arg_sibling */
1296
synctex_tree_scn_sheet_max
1298
static const synctex_data_model_s synctex_data_model_sheet = {
1315
synctex_data_sheet_page_idx, /* page */
1316
synctex_data_p_sheet_max
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 */
1333
# ifdef SYNCTEX_NOTHING
1337
* Every node has the same structure, but not the same size.
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;
1345
DEFINE_synctex_new_scanned_NODE(form)
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);
1351
static const synctex_tree_model_s synctex_tree_model_form = {
1352
synctex_tree_sibling_idx, /* sibling */
1354
synctex_tree_s_child_idx, /* child */
1358
-1, /* arg_sibling */
1359
synctex_tree_sc_target_idx, /* target */
1360
synctex_tree_sct_form_max
1362
static const synctex_data_model_s synctex_data_model_form = {
1363
synctex_data_form_tag_idx, /* tag */
1380
synctex_data_t_form_max
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 */
1397
# ifdef SYNCTEX_NOTHING
377
DEFINE_synctex_new_NODE(sheet)
379
static void _synctex_display_sheet(synctex_node_t node);
380
static void _synctex_log_sheet(synctex_node_t node);
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 */
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.
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)))
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;
1411
430
/* vertical box node creator */
1412
DEFINE_synctex_new_scanned_NODE(vbox)
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);
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 */
1425
-1, /* arg_sibling */
1427
synctex_tree_spcfl_vbox_max
1430
#define SYNCTEX_DFLT_COLUMN -1
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);
1442
return SYNCTEX_STATUS_BAD_ARGUMENT;
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)
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));
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));
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 */
1479
synctex_data_box_max
1481
static const synctex_tlcpector_s synctex_tlcpector_default = {
1482
&_synctex_data_tag, /* tag */
1483
&_synctex_data_line, /* line */
1484
&_synctex_data_column, /* column */
1486
static const synctex_inspector_s synctex_inspector_box = {
1489
&_synctex_data_width,
1490
&_synctex_data_height,
1491
&_synctex_data_depth,
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,
431
DEFINE_synctex_new_NODE(vbox)
433
static void _synctex_log_vbox(synctex_node_t node);
434
static void _synctex_display_vbox(synctex_node_t node);
1505
436
/* These are static class objects, each scanner will make a copy of them and setup the scanner field.
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
1522
# ifdef SYNCTEX_NOTHING
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. */
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 */
1538
synctex_tree_spcfln_hbox_max
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)
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.
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 */
1578
synctex_data_hbox_max
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)))
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;
1587
484
/* horizontal box node creator */
1588
DEFINE_synctex_new_scanned_NODE(hbox)
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);
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)
487
static void _synctex_display_hbox(synctex_node_t node);
488
static void _synctex_log_hbox(synctex_node_t node);
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
1609
# ifdef SYNCTEX_NOTHING
1610
# pragma mark void vbox.
1613
506
/* This void box node implementation is either horizontal or vertical
1614
507
* It does not contain a child field.
1616
static const synctex_tree_model_s synctex_tree_model_spf = {
1617
synctex_tree_sibling_idx, /* sibling */
1618
synctex_tree_s_parent_idx, /* parent */
1620
synctex_tree_sp_friend_idx, /* friend */
1623
-1, /* arg_sibling */
1625
synctex_tree_spf_max
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;
1633
517
/* vertical void box node creator */
1634
DEFINE_synctex_new_scanned_NODE(void_vbox)
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);
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)
520
static void _synctex_log_void_box(synctex_node_t node);
521
static void _synctex_display_void_vbox(synctex_node_t node);
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 */
532
&_synctex_implementation_1, /* sibling */
533
&_synctex_implementation_2, /* friend */
534
NULL, /* No next hbox */
535
(_synctex_info_getter_t)&_synctex_implementation_3
1655
# ifdef SYNCTEX_NOTHING
1656
# pragma mark void hbox.
1659
typedef synctex_node_void_vbox_s synctex_node_void_hbox_s;
538
typedef synctex_node_void_vbox_t synctex_node_void_hbox_t;
1661
540
/* horizontal void box node creator */
1662
DEFINE_synctex_new_scanned_NODE(void_hbox)
1664
static char * _synctex_abstract_void_hbox(synctex_node_p node);
1665
static void _synctex_display_void_hbox(synctex_node_p node);
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 */
1682
# ifdef SYNCTEX_NOTHING
1683
# pragma mark form ref.
1686
/* The form ref node. */
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;
1693
/* form ref node creator */
1694
DEFINE_synctex_new_scanned_NODE(ref)
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);
1700
static const synctex_tree_model_s synctex_tree_model_spfa = {
1701
synctex_tree_sibling_idx, /* sibling */
1702
synctex_tree_s_parent_idx, /* parent */
1704
synctex_tree_sp_friend_idx, /* friend */
1707
synctex_tree_spf_arg_sibling_idx, /* arg_sibling */
1709
synctex_tree_spfa_max
1711
static const synctex_data_model_s synctex_data_model_ref = {
1712
synctex_data_tag_idx, /* tag */
1715
synctex_data_ref_h_idx, /* h */
1716
synctex_data_ref_v_idx, /* v */
1729
synctex_data_ref_thv_max /* size */
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 */
1745
# ifdef SYNCTEX_NOTHING
1746
# pragma mark small node.
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 */
1768
synctex_data_tlchv_max
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;
1777
static void _synctex_log_tlchv_node(synctex_node_p node);
1779
# ifdef SYNCTEX_NOTHING
1783
typedef synctex_node_tlchv_s synctex_node_math_s;
541
DEFINE_synctex_new_NODE(void_hbox)
543
static void _synctex_display_void_hbox(synctex_node_t node);
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 */
554
&_synctex_implementation_1, /* sibling */
555
&_synctex_implementation_2, /* friend */
556
NULL, /* No next hbox */
557
(_synctex_info_getter_t)&_synctex_implementation_3
560
/* The medium nodes correspond to kern, glue, penalty and math nodes.
561
* In LuaTeX, the size of the nodes may have changed. */
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;
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))
576
#define SYNCTEX_HAS_CHILDREN(NODE) (NODE && SYNCTEX_CHILD(NODE))
578
static void _synctex_log_medium_node(synctex_node_t node);
580
typedef synctex_node_medium_t synctex_node_math_t;
1785
582
/* math node creator */
1786
DEFINE_synctex_new_scanned_NODE(math)
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 = {
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,
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 */
1820
# ifdef SYNCTEX_NOTHING
1821
# pragma mark kern node.
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 */
1842
synctex_data_tlchvw_max
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)
585
static void _synctex_display_math(synctex_node_t node);
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 */
596
&_synctex_implementation_1, /* sibling */
597
&_synctex_implementation_2, /* friend */
598
NULL, /* No next hbox */
599
(_synctex_info_getter_t)&_synctex_implementation_3
602
typedef synctex_node_medium_t synctex_node_kern_t;
1850
604
/* kern node creator */
1851
DEFINE_synctex_new_scanned_NODE(kern)
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);
1857
static synctex_inspector_s synctex_inspector_kern = {
1860
&_synctex_data_width,
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,
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 */
1889
# ifdef SYNCTEX_NOTHING
605
DEFINE_synctex_new_NODE(kern)
607
static void _synctex_display_kern(synctex_node_t node);
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 */
618
&_synctex_implementation_1, /* sibling */
619
&_synctex_implementation_2, /* friend */
620
NULL, /* No next hbox */
621
(_synctex_info_getter_t)&_synctex_implementation_3
624
/* The small nodes correspond to glue and boundary nodes. */
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;
633
static void _synctex_log_small_node(synctex_node_t node);
1893
635
/* glue node creator */
1894
typedef synctex_node_tlchv_s synctex_node_glue_s;
1895
DEFINE_synctex_new_scanned_NODE(glue)
1897
static char * _synctex_abstract_glue(synctex_node_p node);
1898
static void _synctex_display_glue(synctex_node_p node);
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 */
1915
/* The small nodes correspond to glue and boundary nodes. */
1917
# ifdef SYNCTEX_NOTHING
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;
1927
DEFINE_synctex_new_scanned_NODE(rule)
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);
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,
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 */
1961
# ifdef SYNCTEX_NOTHING
1962
# pragma mark boundary.
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);
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 */
649
&_synctex_implementation_1, /* sibling */
650
&_synctex_implementation_2, /* friend */
651
NULL, /* No next hbox */
652
(_synctex_info_getter_t)&_synctex_implementation_3
1965
655
/* boundary node creator */
1966
typedef synctex_node_tlchv_s synctex_node_boundary_s;
1967
DEFINE_synctex_new_scanned_NODE(boundary)
1969
static char * _synctex_abstract_boundary(synctex_node_p node);
1970
static void _synctex_display_boundary(synctex_node_p node);
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 */
1987
# ifdef SYNCTEX_NOTHING
1988
# pragma mark box boundary.
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;
1997
#define DEFINE_synctex_new_unscanned_NODE(NAME)\
1998
SYNCTEX_INLINE static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner) {\
2000
synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));\
2002
node->class_ = scanner->class_+synctex_node_type_##NAME;\
2003
SYNCTEX_DID_NEW(node); \
2009
DEFINE_synctex_new_unscanned_NODE(box_bdry)
2011
static char * _synctex_abstract_box_bdry(synctex_node_p node);
2012
static void _synctex_display_box_bdry(synctex_node_p node);
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 */
2029
# ifdef SYNCTEX_NOTHING
2030
# pragma mark hbox proxy.
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
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
2072
* At parse time, the arrow means "owns":
2075
* target1 -> ref_to2
2077
* target2 -> child22
2079
* After replacing the refs:
2080
* sheet0 -> proxy00 -> proxy01 -> proxy02
2082
* target1 -> proxy11 -> proxy12
2084
* target2 -> proxy22
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.
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.
2101
/* A proxy to a hbox.
2102
* A proxy do have a target, which can be a proxy
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
2116
static const synctex_data_model_s synctex_data_model_proxy = {
2120
synctex_data_proxy_h_idx, /* h */
2121
synctex_data_proxy_v_idx, /* v */
2134
synctex_data_proxy_hv_max
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;
2142
/* box proxy node creator */
2143
DEFINE_synctex_new_unscanned_NODE(proxy_hbox)
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);
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);
2153
static synctex_tlcpector_s synctex_tlcpector_proxy = {
2154
&_synctex_proxy_tag,
2155
&_synctex_proxy_line,
2156
&_synctex_proxy_column,
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 = {
2166
&_synctex_proxy_width,
2167
&_synctex_proxy_height,
2168
&_synctex_proxy_depth,
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);
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,
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 */
2200
# ifdef SYNCTEX_NOTHING
2201
# pragma mark vbox proxy.
2204
/* A proxy to a vbox. */
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 */
2213
-1, /* arg_sibling */
2214
synctex_tree_spcfl_target_idx, /* target */
2215
synctex_tree_spcflt_proxy_vbox_max
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;
2224
/* box proxy node creator */
2225
DEFINE_synctex_new_unscanned_NODE(proxy_vbox)
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);
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 */
2246
# ifdef SYNCTEX_NOTHING
2247
# pragma mark proxy.
2251
* A proxy to a node but a box.
2254
static const synctex_tree_model_s synctex_tree_model_proxy = {
2255
synctex_tree_sibling_idx, /* sibling */
2256
synctex_tree_s_parent_idx, /* parent */
2258
synctex_tree_sp_friend_idx, /* friend */
2261
-1, /* arg_sibling */
2262
synctex_tree_spf_target_idx,/* target */
2263
synctex_tree_spft_proxy_max
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;
2272
/* proxy node creator */
2273
DEFINE_synctex_new_unscanned_NODE(proxy)
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);
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,
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 */
2302
# ifdef SYNCTEX_NOTHING
2303
# pragma mark last proxy.
2307
* A proxy to the last proxy/box boundary.
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 */
2314
synctex_tree_sp_friend_idx, /* friend */
2317
synctex_tree_spf_arg_sibling_idx, /* arg_sibling */
2318
synctex_tree_spfa_target_idx, /* target */
2319
synctex_tree_spfat_proxy_last_max
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;
2328
/* proxy node creator */
2329
DEFINE_synctex_new_unscanned_NODE(proxy_last)
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);
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 */
2350
# ifdef SYNCTEX_NOTHING
2351
# pragma mark handle.
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.
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 */
2370
-1, /* arg_sibling */
2371
synctex_tree_spc_target_idx,/* target */
2372
synctex_tree_spct_handle_max
2375
static const synctex_data_model_s synctex_data_model_handle = {
2385
synctex_data_handle_w_idx, /* weight */
2393
synctex_data_handle_w_max
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;
2402
/* handle node creator */
2403
DEFINE_synctex_new_unscanned_NODE(handle)
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);
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 */
2424
SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target) {
2426
synctex_node_p result = _synctex_new_handle(target->class_->scanner);
2428
_synctex_tree_set_target(result,target);
2434
SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_child(synctex_node_p child) {
2436
synctex_node_p result = _synctex_new_handle(child->class_->scanner);
2438
_synctex_tree_set_child(result,child);
656
typedef synctex_node_small_t synctex_node_boundary_t;
657
DEFINE_synctex_new_NODE(boundary)
659
static void _synctex_display_boundary(synctex_node_t node);
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 */
670
&_synctex_implementation_1, /* sibling */
671
&_synctex_implementation_2, /* friend */
672
NULL, /* No next hbox */
673
(_synctex_info_getter_t)&_synctex_implementation_3
676
# define SYNCTEX_NAME_IDX (SYNCTEX_TAG_IDX+1)
677
# define SYNCTEX_NAME(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_NAME_IDX].PTR
679
/* Input nodes only know about their sibling, which is another input node.
680
* The synctex information is the SYNCTEX_TAG and SYNCTEX_NAME*/
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 */
688
# define SYNCTEX_INPUT_MARK "Input:"
689
static synctex_node_t _synctex_new_input(synctex_scanner_t scanner) {
691
synctex_node_t node = _synctex_malloc(sizeof(synctex_input_t));
693
SYNCTEX_IMPLEMENT_CHARINDEX(node,strlen(SYNCTEX_INPUT_MARK));
694
node->class = scanner->class+synctex_node_type_input;
701
static void _synctex_free_input(synctex_node_t node){
703
SYNCTEX_FREE(SYNCTEX_SIBLING(node));
704
free(SYNCTEX_NAME(node));
709
static void _synctex_display_input(synctex_node_t node);
710
static void _synctex_log_input(synctex_node_t node);
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 */
721
&_synctex_implementation_0, /* sibling */
722
NULL, /* No friend */
723
NULL, /* No next hbox */
724
(_synctex_info_getter_t)&_synctex_implementation_1
2445
727
# ifdef SYNCTEX_NOTHING
2447
729
# pragma mark Navigation
2449
synctex_node_p synctex_node_parent(synctex_node_p node)
2451
return _synctex_tree_parent(node);
2453
synctex_node_p synctex_node_parent_sheet(synctex_node_p node)
2455
while(node && synctex_node_type(node) != synctex_node_type_sheet) {
2456
node = _synctex_tree_parent(node);
2458
/* exit the while loop either when node is NULL or node is a sheet */
2461
synctex_node_p synctex_node_parent_form(synctex_node_p node)
2463
while(node && synctex_node_type(node) != synctex_node_type_form) {
2464
node = _synctex_tree_parent(node);
2466
/* exit the while loop either when node is NULL or node is a form */
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.
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) {
2481
switch(synctex_node_type(to_node)) {
2482
case synctex_node_type_vbox:
2483
proxy = _synctex_new_proxy_vbox(ref->class_->scanner);
2485
case synctex_node_type_hbox:
2486
proxy = _synctex_new_proxy_hbox(ref->class_->scanner);
2489
_synctex_error("! __synctex_new_proxy_from_ref_to. Unexpected form child (%s). Please report.", synctex_node_isa(to_node));
2493
_synctex_error("! __synctex_new_proxy_from_ref_to. Internal error. Please report.");
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;
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.
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;
2520
switch(synctex_node_type(target)) {
2521
case synctex_node_type_vbox:
2522
if ((proxy = _synctex_new_proxy_vbox(owner->class_->scanner))) {
2524
_synctex_data_set_h(proxy, _synctex_data_h(owner));
2525
_synctex_data_set_v(proxy, _synctex_data_v(owner));
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;
2535
case synctex_node_type_proxy_vbox:
2536
if ((proxy = _synctex_new_proxy_vbox(owner->class_->scanner))) {
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));
2544
case synctex_node_type_hbox:
2545
if ((proxy = _synctex_new_proxy_hbox(owner->class_->scanner))) {
2549
case synctex_node_type_proxy_hbox:
2550
if ((proxy = _synctex_new_proxy_hbox(owner->class_->scanner))) {
2554
case synctex_node_type_proxy:
2555
case synctex_node_type_proxy_last:
2556
if ((proxy = _synctex_new_proxy(owner->class_->scanner))) {
2561
if ((proxy = _synctex_new_proxy(owner->class_->scanner))) {
2566
_synctex_error("! __synctex_new_child_proxy_to. "
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;
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
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);
2598
_synctex_error("! _synctex_new_child_proxy_to. "
2599
"Internal error (1). "
2601
nns.status = SYNCTEX_STATUS_ERROR;
2603
} else if((sibling = _synctex_new_proxy_last(owner->class_->scanner))) {
2604
_synctex_tree_set_sibling(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;
2614
_synctex_error("! _synctex_new_child_proxy_to. "
2615
"Internal error (2). "
2617
nns.status = SYNCTEX_STATUS_ERROR;
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) {
2627
synctex_node_p F = new_friend;
2630
printf("THIS IS AN ERROR\n");
2633
printf("%s\n",_synctex_node_abstract(F));
2637
F = _synctex_tree_friend(F);
2641
F = _synctex_tree_friend(F);
2644
return new_friend?_synctex_tree_set_friend(node,new_friend):_synctex_tree_reset_friend(node);
2649
SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend(synctex_node_p node, int i) {
2650
synctex_node_p old = NULL;
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");
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
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);
2674
int i = _synctex_data_tag(target)+_synctex_data_line(target);
2675
old = __synctex_node_make_friend(node,i);
2677
old = __synctex_tree_reset_friend(node);
2679
if (synctex_node_type(node) == synctex_node_type_proxy_hbox) {
2680
synctex_node_p sheet = synctex_node_parent_sheet(node);
2682
_synctex_tree_set_next_hbox(node,_synctex_tree_next_hbox(sheet));
2683
_synctex_tree_set_next_hbox(sheet,node);
2689
* Register a node which have tag, line and column.
2690
* - argument node: the node
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);
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
2702
SYNCTEX_INLINE static void _synctex_node_make_friend_tlc(synctex_node_p node) {
2704
__synctex_node_make_friend_tlc(node);
2707
static synctex_node_p _synctex_node_set_child(synctex_node_p node, synctex_node_p new_child);
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.
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))) {
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);
2733
_synctex_node_set_child(node,nns.first);
2736
_synctex_error("! synctex_node_child. Internal inconsistency. Please report.");
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.
2747
static synctex_node_p _synctex_node_set_child(synctex_node_p parent, synctex_node_p new_child) {
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)) {
2754
_synctex_tree_reset_parent(child);
2755
} while ((child = __synctex_tree_sibling(child)));
2757
if ((child = new_child)) {
2759
_synctex_tree_set_parent(child,parent);
2761
} while ((child = __synctex_tree_sibling(child)));
2763
_synctex_tree_set_last(parent,last_child);
2769
/* The last child of the given node, or NULL.
2771
synctex_node_p synctex_node_last_child(synctex_node_p node) {
2772
return _synctex_tree_last(node);
2775
* All nodes siblings are properly set up at parse time
2776
* except for non root proxies.
2778
synctex_node_p synctex_node_sibling(synctex_node_p node) {
2779
return node? __synctex_tree_sibling(node): NULL;
2782
* All the _synctex_tree_... methods refer to the tree model.
2783
* __synctex_tree_... methods are low level.
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.
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) {
2796
synctex_node_p old = node? __synctex_tree_set_sibling(node,new_sibling): NULL;
2797
_synctex_tree_set_arg_sibling(new_sibling,node);
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.
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);
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);
2823
_synctex_error("! synctex_node_sibling. "
2824
"Internal inconsistency. "
2836
* The last sibling of the given node, or NULL with node.
2838
synctex_node_p synctex_node_last_sibling(synctex_node_p node) {
2839
synctex_node_p sibling;
2842
} while((node = synctex_node_sibling(node)));
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).
2852
SYNCTEX_INLINE static synctex_node_p _synctex_node_sibling_or_parents(synctex_node_p node) {
2855
if ((N = __synctex_tree_sibling(node))) {
2857
} else if ((node = _synctex_tree_parent(node))) {
2858
if (synctex_node_type(node) == synctex_node_type_sheet) {/* EXC_BAD_ACCESS? */
2860
} else if (synctex_node_type(node) == synctex_node_type_form) {
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).
2875
synctex_node_p synctex_node_next(synctex_node_p node) {
2876
synctex_node_p N = synctex_node_child(node);
2880
return _synctex_node_sibling_or_parents(node);
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
2888
synctex_node_p synctex_node_arg_sibling(synctex_node_p node) {
2890
return _synctex_tree_arg_sibling(node);
2892
synctex_node_p N = _synctex_tree_parent(node);
2893
if ((N = _synctex_tree_child(N))) {
2895
synctex_node_p NN = __synctex_tree_sibling(N);
731
synctex_node_t synctex_node_parent(synctex_node_t node)
733
return SYNCTEX_PARENT(node);
735
synctex_node_t synctex_node_sheet(synctex_node_t node)
737
while(node && node->class->type != synctex_node_type_sheet) {
738
node = SYNCTEX_PARENT(node);
740
/* exit the while loop either when node is NULL or node is a sheet */
743
synctex_node_t synctex_node_child(synctex_node_t node)
745
return SYNCTEX_CHILD(node);
747
synctex_node_t synctex_node_sibling(synctex_node_t node)
749
return SYNCTEX_SIBLING(node);
751
synctex_node_t synctex_node_next(synctex_node_t node) {
752
if (SYNCTEX_CHILD(node)) {
753
return SYNCTEX_CHILD(node);
756
if (SYNCTEX_SIBLING(node)) {
757
return SYNCTEX_SIBLING(node);
759
if ((node = SYNCTEX_PARENT(node))) {
760
if (node->class->type == synctex_node_type_sheet) {/* EXC_BAD_ACCESS? */
2905
767
# ifdef SYNCTEX_NOTHING
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;
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);
2919
return (((target)->class_))->type;
2921
return (((node)->class_))->type;
2923
return synctex_node_type_none;
773
synctex_node_type_t synctex_node_type(synctex_node_t node) {
775
return (((node)->class))->type;
777
return synctex_node_type_error;
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] =
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)];
2952
787
# ifdef SYNCTEX_NOTHING
789
# pragma mark SYNCTEX_LOG
792
# define SYNCTEX_LOG(NODE) SYNCTEX_MSG_SEND(NODE,log)
2957
794
/* Public node logger */
2958
void synctex_node_log(synctex_node_p node) {
2959
SYNCTEX_MSG_SEND(node,log);
2962
static void _synctex_log_input(synctex_node_p 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));
2974
static void _synctex_log_sheet(synctex_node_p 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));
2987
static void _synctex_log_form(synctex_node_p 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));
2999
static void _synctex_log_ref(synctex_node_p 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));
3013
static void _synctex_log_tlchv_node(synctex_node_p 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));
3031
static void _synctex_log_kern_node(synctex_node_p 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));
3050
static void _synctex_log_rule(synctex_node_p 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));
3070
static void _synctex_log_void_box(synctex_node_p 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));
3090
static void _synctex_log_vbox(synctex_node_p 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));
3111
static void _synctex_log_hbox(synctex_node_p 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));
3136
static void _synctex_log_proxy(synctex_node_p 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));
3149
static void _synctex_log_handle(synctex_node_p 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));
3160
# ifdef SYNCTEX_NOTHING
3162
# pragma mark SYNCTEX_DISPLAY
3165
int synctex_scanner_display_switcher(synctex_scanner_p scanR) {
3166
return scanR->display_switcher;
3168
void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher) {
3169
scanR->display_switcher = switcher;
3171
static const char * const _synctex_display_prompt = "................................";
3173
static char * _synctex_scanner_display_prompt_down(synctex_scanner_p scanR) {
3174
if (scanR->display_prompt>_synctex_display_prompt) {
3175
--scanR->display_prompt;
3177
return scanR->display_prompt;
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;
3183
return scanR->display_prompt;
3186
void synctex_node_display(synctex_node_p node) {
3188
synctex_scanner_p scanR = node->class_->scanner;
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);
3198
SYNCTEX_MSG_SEND(node, display);
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";
3207
SYNCTEX_INLINE static void _synctex_display_child(synctex_node_p node) {
3208
synctex_node_p N = _synctex_tree_child(node);
3210
_synctex_scanner_display_prompt_down(N->class_->scanner);
3211
synctex_node_display(N);
3212
_synctex_scanner_display_prompt_up(N->class_->scanner);
3216
SYNCTEX_INLINE static void _synctex_display_sibling(synctex_node_p node) {
3217
synctex_node_display(__synctex_tree_sibling(node));
3219
#define SYNCTEX_ABSTRACT_MAX 128
3220
static char * _synctex_abstract_input(synctex_node_p node) {
3221
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3232
static void _synctex_display_input(synctex_node_p node) {
3234
printf("Input:%i:%s(%i)"
3235
SYNCTEX_PRINT_CHARINDEX_FMT
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));
3245
static char * _synctex_abstract_sheet(synctex_node_p node) {
3246
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3248
snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"{%i...}" SYNCTEX_PRINT_CHARINDEX_FMT,
3249
_synctex_data_page(node)
3250
SYNCTEX_PRINT_CHARINDEX_WHAT);
3255
static void _synctex_display_sheet(synctex_node_p node) {
3258
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3269
static char * _synctex_abstract_form(synctex_node_p node) {
3270
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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;
3280
static void _synctex_display_form(synctex_node_p node) {
3283
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3294
static char * _synctex_abstract_vbox(synctex_node_p node) {
3295
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3311
static void _synctex_display_vbox(synctex_node_p node) {
3313
printf("%s[%i,%i:%i,%i:%i,%i,%i"
3314
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3334
static char * _synctex_abstract_hbox(synctex_node_p node) {
3335
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3353
static void _synctex_display_hbox(synctex_node_p node) {
3355
printf("%s(%i,%i~%i*%i:%i,%i:%i,%i,%i"
3356
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3378
static char * _synctex_abstract_void_vbox(synctex_node_p node) {
3379
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3381
snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"v%i,%i;%i,%i:%i,%i,%i"
3382
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3396
static void _synctex_display_void_vbox(synctex_node_p node) {
3398
printf("%sv%i,%i;%i,%i:%i,%i,%i"
3399
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3414
static char * _synctex_abstract_void_hbox(synctex_node_p node) {
3415
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3431
static void _synctex_display_void_hbox(synctex_node_p node) {
3433
printf("%sh%i,%i:%i,%i:%i,%i,%i"
3434
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3449
static char * _synctex_abstract_glue(synctex_node_p node) {
3450
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3463
static void _synctex_display_glue(synctex_node_p node) {
3465
printf("%sglue:%i,%i:%i,%i"
3466
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3478
static char * _synctex_abstract_rule(synctex_node_p node) {
3479
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3495
static void _synctex_display_rule(synctex_node_p node) {
3497
printf("%srule:%i,%i:%i,%i:%i,%i,%i"
3498
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3513
static char * _synctex_abstract_math(synctex_node_p node) {
3514
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3527
static void _synctex_display_math(synctex_node_p node) {
3529
printf("%smath:%i,%i:%i,%i"
3530
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3542
static char * _synctex_abstract_kern(synctex_node_p node) {
3543
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3557
static void _synctex_display_kern(synctex_node_p node) {
3559
printf("%skern:%i,%i:%i,%i:%i"
3560
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3573
static char * _synctex_abstract_boundary(synctex_node_p node) {
3574
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3587
static void _synctex_display_boundary(synctex_node_p node) {
3589
printf("%sboundary:%i,%i:%i,%i"
3590
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3602
static char * _synctex_abstract_box_bdry(synctex_node_p node) {
3603
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3615
static void _synctex_display_box_bdry(synctex_node_p 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);
3628
static char * _synctex_abstract_ref(synctex_node_p node) {
3629
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3640
static void _synctex_display_ref(synctex_node_p 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);
3651
static char * _synctex_abstract_proxy(synctex_node_p node) {
3652
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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),
3662
_synctex_node_abstract(N));
3666
static void _synctex_display_proxy(synctex_node_p 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));
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));
3686
_synctex_display_child(node);
3687
_synctex_display_sibling(node);
3690
static char * _synctex_abstract_proxy_vbox(synctex_node_p node) {
3691
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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);
3708
static void _synctex_display_proxy_vbox(synctex_node_p node) {
3710
printf("%s[*%i,%i:%i,%i:%i,%i,%i"
3711
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3731
static char * _synctex_abstract_proxy_hbox(synctex_node_p node) {
3732
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
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),
3746
SYNCTEX_PRINT_CHARINDEX_WHAT);
3751
static void _synctex_display_proxy_hbox(synctex_node_p node) {
3753
printf("%s(*%i,%i~%i*%i:%i,%i:%i,%i,%i"
3754
SYNCTEX_PRINT_CHARINDEX_FMT
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);
3776
static char * _synctex_abstract_handle(synctex_node_p node) {
3777
static char abstract[SYNCTEX_ABSTRACT_MAX] = "none";
3779
synctex_node_p N = _synctex_tree_target(node);
3780
if (N && !N->class_) {
3783
snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%s",
3784
synctex_node_isa(node),
3785
(N?_synctex_node_abstract(N):""));
3789
static void _synctex_display_handle(synctex_node_p 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);
3801
# ifdef SYNCTEX_NOTHING
3803
# pragma mark STATUS
795
void synctex_node_log(synctex_node_t node) {
799
static void _synctex_log_input(synctex_node_t 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));
806
static void _synctex_log_sheet(synctex_node_t 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));
819
static void _synctex_log_small_node(synctex_node_t node) {
821
printf("%s:%i,%i:%i,%i",
822
synctex_node_isa(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));
836
static void _synctex_log_medium_node(synctex_node_t node) {
838
printf("%s:%i,%i:%i,%i:%i",
839
synctex_node_isa(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));
854
static void _synctex_log_void_box(synctex_node_t node) {
856
printf("%s",synctex_node_isa(node));
857
printf(":%i",SYNCTEX_TAG(node));
858
printf(",%i",SYNCTEX_LINE(node));
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));
874
static void _synctex_log_vbox(synctex_node_t node) {
876
printf("%s",synctex_node_isa(node));
877
printf(":%i",SYNCTEX_TAG(node));
878
printf(",%i",SYNCTEX_LINE(node));
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));
895
static void _synctex_log_hbox(synctex_node_t 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));
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));
921
# define SYNCTEX_DISPLAY(NODE) SYNCTEX_MSG_SEND(NODE,display)
923
void synctex_node_display(synctex_node_t node) {
924
SYNCTEX_DISPLAY(node);
927
static void _synctex_display_input(synctex_node_t node) {
929
printf("....Input:%i:%s",
932
SYNCTEX_PRINT_CHARINDEX;
933
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
937
static void _synctex_display_sheet(synctex_node_t node) {
939
printf("....{%i",SYNCTEX_PAGE(node));
940
SYNCTEX_PRINT_CHARINDEX;
941
SYNCTEX_DISPLAY(SYNCTEX_CHILD(node));
943
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
947
static void _synctex_display_vbox(synctex_node_t node) {
949
printf("....[%i,%i:%i,%i:%i,%i,%i",
955
SYNCTEX_HEIGHT(node),
956
SYNCTEX_DEPTH(node));
957
SYNCTEX_PRINT_CHARINDEX;
958
SYNCTEX_DISPLAY(SYNCTEX_CHILD(node));
960
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
964
static void _synctex_display_hbox(synctex_node_t node) {
966
printf("....(%i,%i~%i*%i:%i,%i:%i,%i,%i",
969
SYNCTEX_MEAN_LINE(node),
970
SYNCTEX_NODE_WEIGHT(node),
974
SYNCTEX_HEIGHT(node),
975
SYNCTEX_DEPTH(node));
976
SYNCTEX_PRINT_CHARINDEX;
977
SYNCTEX_DISPLAY(SYNCTEX_CHILD(node));
979
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
983
static void _synctex_display_void_vbox(synctex_node_t node) {
985
printf("....v%i,%i;%i,%i:%i,%i,%i",
991
SYNCTEX_HEIGHT(node),
992
SYNCTEX_DEPTH(node));
993
SYNCTEX_PRINT_CHARINDEX;
994
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
998
static void _synctex_display_void_hbox(synctex_node_t node) {
1000
printf("....h%i,%i:%i,%i:%i,%i,%i",
1003
SYNCTEX_HORIZ(node),
1005
SYNCTEX_WIDTH(node),
1006
SYNCTEX_HEIGHT(node),
1007
SYNCTEX_DEPTH(node));
1008
SYNCTEX_PRINT_CHARINDEX;
1009
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
1013
static void _synctex_display_glue(synctex_node_t node) {
1015
printf("....glue:%i,%i:%i,%i",
1018
SYNCTEX_HORIZ(node),
1019
SYNCTEX_VERT(node));
1020
SYNCTEX_PRINT_CHARINDEX;
1021
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
1025
static void _synctex_display_math(synctex_node_t node) {
1027
printf("....math:%i,%i:%i,%i",
1030
SYNCTEX_HORIZ(node),
1031
SYNCTEX_VERT(node));
1032
SYNCTEX_PRINT_CHARINDEX;
1033
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
1037
static void _synctex_display_kern(synctex_node_t node) {
1039
printf("....kern:%i,%i:%i,%i:%i",
1042
SYNCTEX_HORIZ(node),
1044
SYNCTEX_WIDTH(node));
1045
SYNCTEX_PRINT_CHARINDEX;
1046
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
1050
static void _synctex_display_boundary(synctex_node_t node) {
1052
printf("....boundary:%i,%i:%i,%i",
1055
SYNCTEX_HORIZ(node),
1056
SYNCTEX_VERT(node));
1057
SYNCTEX_PRINT_CHARINDEX;
1058
SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
1062
# ifdef SYNCTEX_NOTHING
1064
# pragma mark SCANNER
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
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
1090
# define SYNCTEX_FILE (scanner->file)
1092
/* Actually, the minimum buffer size is driven by integer and float parsing.
1095
# define SYNCTEX_BUFFER_MIN_SIZE 16
1096
# define SYNCTEX_BUFFER_SIZE 32768
3806
1098
# ifdef SYNCTEX_NOTHING
3807
1099
# pragma mark -
3808
1100
# pragma mark Prototypes
3812
synctex_status_t status;
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);
3818
typedef struct synctex_ns_t {
3819
synctex_node_p node;
3820
synctex_status_t status;
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);
3826
synctex_status_t status;
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);
3837
# ifdef SYNCTEX_NOTHING
3839
# pragma mark SCANNER UTILITIES
3842
# define SYNCTEX_FILE (scanner->reader->file)
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);
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.
3857
static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t expected) {
3859
if (NULL == scanner) {
3860
return (synctex_zs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT};
3862
if (expected>scanner->reader->size){
3863
expected = scanner->reader->size;
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};
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;
1137
# define size (* size_ptr)
1138
if (size>SYNCTEX_BUFFER_SIZE){
1139
size = SYNCTEX_BUFFER_SIZE;
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 */
1145
return SYNCTEX_STATUS_OK;
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;
3878
memmove(SYNCTEX_START, SYNCTEX_CUR, size);
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 */
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};
1155
memmove(SYNCTEX_START, SYNCTEX_CUR, available);
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 */
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;
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 */
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. */
1195
return SYNCTEX_STATUS_EOF;
3920
1199
/* Used when parsing the synctex file.
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 '%'
4730
# ifdef SYNCTEX_NOTHING
4732
# pragma mark SCANNERS & PARSERS
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)
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))) {
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.");
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;
4757
/* sheets have no parent */
4758
__synctex_tree_set_sibling(last_sheet,node);
4760
scanner->sheet = node;
4762
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4764
_synctex_free_node(node);
4766
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4769
* - requirement: scanner != NULL
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))) {
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.");
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;
4787
__synctex_tree_set_sibling(last_form,node);
4789
scanner->form = node;
4791
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4793
_synctex_free_node(node);
4795
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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))
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);
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);
4819
_synctex_free_node(node);
4820
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4822
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4823
_synctex_error("Missing end of vbox.");
4826
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4828
_synctex_next_line(scanner);
4829
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4839
_synctex_free_node(node);
4840
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4842
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4843
_synctex_error("Missing end of hbox.");
4846
if (_synctex_setup_visible_hbox(node)<SYNCTEX_STATUS_OK) {
4847
_synctex_error("Unexpected error (_synctex_parse_new_hbox).");
4850
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4852
_synctex_next_line(scanner);
4853
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4862
_synctex_free_node(node);
4863
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4865
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4866
_synctex_error("Missing end of container.");
4869
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4871
_synctex_next_line(scanner);
4872
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4881
_synctex_free_node(node);
4882
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4884
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4885
_synctex_error("Missing end of container.");
4888
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4890
_synctex_next_line(scanner);
4891
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4900
_synctex_free_node(node);
4901
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4903
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4904
_synctex_error("Missing end of container.");
4907
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4909
_synctex_next_line(scanner);
4910
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4919
_synctex_free_node(node);
4920
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4922
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4923
_synctex_error("Missing end of container.");
4926
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4928
_synctex_next_line(scanner);
4929
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4938
_synctex_free_node(node);
4939
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4941
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4942
_synctex_error("Missing end of container.");
4945
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4947
_synctex_next_line(scanner);
4948
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4957
_synctex_free_node(node);
4958
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4960
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4961
_synctex_error("Missing end of container.");
4964
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4966
_synctex_next_line(scanner);
4967
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4976
_synctex_free_node(node);
4977
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
4979
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
4980
_synctex_error("Missing end of container.");
4983
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
4985
_synctex_next_line(scanner);
4986
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
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);
4997
_synctex_free_node(node);
4998
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
5000
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5001
_synctex_error("Missing end of container.");
5004
return (synctex_ns_s){node,SYNCTEX_STATUS_OK};
5006
_synctex_next_line(scanner);
5007
return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR};
5009
# undef SYNCTEX_DECODE_FAILED
5010
# undef SYNCTEX_DECODE_FAILED_V
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);
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));
5023
if (_synctex_data_line(node)>_synctex_data_line(input)) {
5024
_synctex_data_set_line(input,_synctex_data_line(node));
5029
* Free node and its siblings and return its detached child.
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);
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.
5042
SYNCTEX_INLINE static void _synctex_handle_set_tlc(synctex_node_p x_handle, synctex_node_p child, synctex_bool_t make_friend) {
5044
synctex_node_p sibling = x_handle;
5046
synctex_node_p target;
5047
while ((target = synctex_node_target(sibling))) {
5048
_synctex_data_set_tlc(target,child);
5050
_synctex_node_make_friend_tlc(target);
5052
if ((sibling = __synctex_tree_sibling(sibling))) {
5059
_synctex_tree_reset_target(x_handle);
5060
sibling = __synctex_tree_reset_sibling(x_handle);
5061
synctex_node_free(sibling);
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.
5070
SYNCTEX_INLINE static void _synctex_handle_make_friend_tlc(synctex_node_p node) {
5072
synctex_node_p target = _synctex_tree_reset_target(node);
5073
_synctex_node_make_friend_tlc(target);
5074
node = __synctex_tree_sibling(node);
5078
* Scan sheets, forms and input records.
5079
* - parameter scanner: owning scanner
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;
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.
5098
synctex_node_p x_handle = NULL;
5099
# define SYNCTEX_RETURN(STATUS) \
5100
synctex_node_free(x_handle);\
5102
synctex_node_p last_k = NULL;
5103
synctex_node_p last_g = NULL;
5104
synctex_ns_s ns = SYNCTEX_NS_NULL;
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);
5111
# ifdef SYNCTEX_NOTHING
5112
# pragma mark 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
5125
ns = _synctex_parse_new_form(scanner);
5126
if (ns.status == SYNCTEX_STATUS_OK) {
5128
if (_synctex_tree_parent(form)) {
5129
/* This form is already being parsed */
5130
++ignored_form_depth;
5133
_synctex_tree_set_parent(ns.node,form);
5137
last_k = last_g = NULL;
5140
if (form || sheet) {
5141
last_k = last_g = NULL;
5144
try_input = synctex_YES;
5146
} else if (SYNCTEX_START_SCAN(BEGIN_SHEET)) {
5147
# ifdef SYNCTEX_NOTHING
5148
# pragma mark + SCAN SHEET
5150
try_input = synctex_YES;
5151
ns = _synctex_parse_new_sheet(scanner);
5152
if (ns.status == SYNCTEX_STATUS_OK) {
5155
last_k = last_g = NULL;
5159
} else if (SYNCTEX_START_SCAN(ANCHOR)) {
5160
# ifdef SYNCTEX_NOTHING
5161
# pragma mark + SCAN ANCHOR
5165
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5166
_synctex_error("Missing anchor.");
5167
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5169
if (form || sheet) {
5170
last_k = last_g = NULL;
5173
try_input = synctex_YES;
5175
} else if (SYNCTEX_START_SCAN(ANCHOR)) {
5176
# ifdef SYNCTEX_NOTHING
5177
# pragma mark + SCAN COMMENT
5180
_synctex_next_line(scanner);
5181
try_input = synctex_YES;
5183
} else if (try_input) {
5184
# ifdef SYNCTEX_NOTHING
5185
# pragma mark + SCAN INPUT
5187
try_input = synctex_NO;
5189
input = __synctex_parse_new_input(scanner);
5190
} while (input.status == SYNCTEX_STATUS_OK);
5193
status = _synctex_match_string(scanner,"Postamble:");
5194
if (status==SYNCTEX_STATUS_OK) {
5195
scanner->flags.postamble = 1;
5196
SYNCTEX_RETURN(status);
5198
status = _synctex_next_line(scanner);
5199
if (status<SYNCTEX_STATUS_OK) {
5200
SYNCTEX_RETURN(status);
5203
/* At least 1 more character */
5204
zs = _synctex_buffer_get_available_size(scanner,1);
5206
_synctex_error("Incomplete synctex file, postamble missing.");
5207
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5211
# ifdef SYNCTEX_NOTHING
5212
# pragma mark 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;
5222
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5223
_synctex_error("Incomplete container.");
5224
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5227
zs = _synctex_buffer_get_available_size(scanner,1);
5229
_synctex_error("Incomplete synctex file, postamble missing.");
5230
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5233
if (ignored_form_depth) {
5236
last_k = last_g = NULL;
5240
# ifdef SYNCTEX_NOTHING
5241
# pragma mark 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.
5251
/* forms are everywhere */
5252
ns = SYNCTEX_NS_NULL;
5254
synctex_scanner_set_display_switcher(scanner,-1);
5255
printf("NEW CONTENT LOOP\n");
5256
#if SYNCTEX_DEBUG>500
5257
synctex_node_display(sheet);
5260
if (SYNCTEX_CUR<SYNCTEX_END) {
5261
if (SYNCTEX_START_SCAN(BEGIN_FORM)) {
5263
} else if (SYNCTEX_START_SCAN(BEGIN_VBOX)) {
5264
# ifdef SYNCTEX_NOTHING
5265
# pragma mark + SCAN VBOX
5267
ns = _synctex_parse_new_vbox(scanner);
5268
if (ns.status == SYNCTEX_STATUS_OK) {
5269
x_handle = _synctex_new_handle_with_child(x_handle);
5271
_synctex_node_set_sibling(child,ns.node);
5273
_synctex_node_set_child(parent,ns.node);
5276
child = _synctex_tree_last(parent);
5277
# if SYNCTEX_VERBOSE
1928
# define SYNCTEX_RETURN(STATUS) return STATUS;
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.
1935
synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner) {
1936
unsigned int depth = 0;
1939
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
1940
_synctex_error("Unexpected end of nested sheet (1).");
1941
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1944
if (SYNCTEX_CUR<SYNCTEX_END) {
1945
if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
1947
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
1948
_synctex_error("Unexpected end of nested sheet (2).");
1949
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1952
goto scan_next_line;
1954
SYNCTEX_RETURN(SYNCTEX_STATUS_OK);
1956
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) {
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);
1965
_synctex_error("Unexpected end of nested sheet (4).");
1966
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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.
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;
1985
/* We MUST start with a box, so at this level, the unique possibility is '[', '(' or "}". */
1987
if (SYNCTEX_CUR<SYNCTEX_END) {
1988
if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_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);
2004
SYNCTEX_SET_CHILD(parent,child);
2007
goto child_loop;/* next created node will be a child */
2009
_synctex_error("Can't create vbox record.");
2010
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2012
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_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);
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);
2032
goto child_loop;/* next created node will be a child */
2034
_synctex_error("Can't create hbox record.");
2035
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2037
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
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);
2045
# if SYNCTEX_VERBOSE
5278
2046
synctex_node_log(parent);
5280
input.node = _synctex_input_register_line(input.node,parent);
5281
last_k = last_g = NULL;
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
5290
if (NULL == _synctex_tree_child(parent) && !form) {
5291
/* only void v boxes are friends */
5292
_synctex_node_make_friend_tlc(parent);
5295
parent = _synctex_tree_parent(child);
5297
_synctex_handle_make_friend_tlc(x_handle);
5299
x_handle = _synctex_handle_pop_child(x_handle);
5300
_synctex_handle_set_tlc(x_handle,child,!form);
5301
# if SYNCTEX_VERBOSE
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 */
2052
if (_synctex_scan_nested_sheet(scanner)<SYNCTEX_STATUS_OK) {
2053
_synctex_error("Unexpected nested sheet.");
2054
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2057
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
2060
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2061
_synctex_error("Missing anchor.");
2062
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2066
/* _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
2068
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2069
_synctex_error("Unexpected end.");
2070
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
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. */
2086
if (SYNCTEX_CUR<SYNCTEX_END) {
2087
if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_VBOX) {
2089
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_VBOX) {
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);
2102
parent = SYNCTEX_PARENT(child);
2104
_synctex_error("Unexpected end of vbox, ignored.");
2106
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2107
_synctex_error("Uncomplete sheet.");
2108
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2110
# if SYNCTEX_VERBOSE
5302
2111
synctex_node_log(child);
5304
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5305
_synctex_error("Incomplete container.");
5306
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5308
last_k = last_g = NULL;
5311
} else if (SYNCTEX_START_SCAN(BEGIN_HBOX)) {
5312
# ifdef SYNCTEX_NOTHING
5313
# pragma mark + SCAN HBOX
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;
5319
ns = _synctex_parse_new_hbox(scanner);
5320
if (ns.status == SYNCTEX_STATUS_OK) {
5321
x_handle = _synctex_new_handle_with_child(x_handle);
5323
_synctex_node_set_sibling(child,ns.node);
5325
_synctex_node_set_child(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;
5334
_synctex_node_set_child(parent,child);
5335
_synctex_data_set_tlchv(child,parent);
5337
__synctex_node_make_friend_tlc(child);
5340
_synctex_error("Can't create box bdry record.");
5342
# if SYNCTEX_VERBOSE
5343
synctex_node_log(parent);
5345
input.node = _synctex_input_register_line(input.node,parent);
5346
last_k = last_g = NULL;
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
5355
/* setting the next horizontal box at the end ensures
5356
* that a child is recorded before any of its ancestors.
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);
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));
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);
5379
cumulated_line_numbers += _synctex_data_mean_line(node);
2114
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_HBOX) {
2116
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_HBOX) {
2119
if ((parent) && parent->class->type == synctex_node_type_hbox) {
2120
/* Update the mean line number */
2121
synctex_node_t node = SYNCTEX_CHILD(parent);
2123
unsigned int node_weight = 0;
2124
unsigned int cumulated_line_numbers = 0;
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);
5383
cumulated_line_numbers += synctex_node_line(node);
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);
5389
_synctex_data_set_mean_line(parent,_synctex_data_line(parent));
5390
_synctex_data_set_weight(parent,1);
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;
5397
_synctex_node_set_sibling(child,sibling);
5399
synctex_node_p N = child;
5400
while (synctex_node_type(N) == synctex_node_type_ref) {
5401
N = _synctex_tree_arg_sibling(N);
5403
_synctex_data_set_tlc(sibling,N);
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));
5409
_synctex_error("Can't create box bdry record.");
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);
5426
parent = _synctex_tree_parent(child);
5428
_synctex_handle_make_friend_tlc(x_handle);
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);
5437
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5438
_synctex_error("Incomplete container.");
5439
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5441
last_k = last_g = NULL;
5444
} else if (SYNCTEX_START_SCAN(VOID_VBOX)) {
5445
# ifdef SYNCTEX_NOTHING
5446
# pragma mark + SCAN VOID VBOX
5448
ns = _synctex_parse_new_void_vbox(scanner);
5449
if (ns.status == SYNCTEX_STATUS_OK) {
5451
_synctex_node_set_sibling(child,ns.node);
5453
_synctex_node_set_child(parent,ns.node);
5456
_synctex_handle_set_tlc(x_handle, child,!form);
5457
# if SYNCTEX_VERBOSE
5458
synctex_node_log(child);
5460
input.node = _synctex_input_register_line(input.node,child);
5461
last_k = last_g = NULL;
5464
} else if (SYNCTEX_START_SCAN(VOID_HBOX)) {
5465
# ifdef SYNCTEX_NOTHING
5466
# pragma mark + SCAN VOID HBOX
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");
5474
_synctex_node_set_sibling(child,ns.node);
5476
_synctex_node_set_child(parent,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);
5484
input.node = _synctex_input_register_line(input.node,child);
5485
last_k = last_g = NULL;
5488
} else if (SYNCTEX_START_SCAN(KERN)) {
5489
# ifdef SYNCTEX_NOTHING
5490
# pragma mark + SCAN KERN
5492
ns = _synctex_parse_new_kern(scanner);
5494
if (ns.status == SYNCTEX_STATUS_OK) {
5496
_synctex_node_set_sibling(child,ns.node);
5498
_synctex_node_set_child(parent,ns.node);
5502
__synctex_node_make_friend_tlc(child);
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);
5509
input.node = _synctex_input_register_line(input.node,child);
5514
} else if (SYNCTEX_START_SCAN(GLUE)) {
5515
# ifdef SYNCTEX_NOTHING
5516
# pragma mark + SCAN GLUE
5518
ns = _synctex_parse_new_glue(scanner);
5519
if (ns.status == SYNCTEX_STATUS_OK) {
5521
_synctex_node_set_sibling(child,ns.node);
5523
_synctex_node_set_child(parent,ns.node);
5527
__synctex_node_make_friend_tlc(child);
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);
5534
input.node = _synctex_input_register_line(input.node,child);
5538
last_k = last_g = NULL;
5542
} else if (SYNCTEX_START_SCAN(RULE)) {
5543
# ifdef SYNCTEX_NOTHING
5544
# pragma mark + SCAN RULE
5546
ns = _synctex_parse_new_rule(scanner);
5547
if (ns.status == SYNCTEX_STATUS_OK) {
5549
_synctex_node_set_sibling(child,ns.node);
5551
_synctex_node_set_child(parent,ns.node);
5555
__synctex_node_make_friend_tlc(child);
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));
5561
# if SYNCTEX_VERBOSE
5562
synctex_node_log(child);
5564
input.node = _synctex_input_register_line(input.node,child);
5565
last_k = last_g = NULL;
5568
} else if (SYNCTEX_START_SCAN(MATH)) {
5569
# ifdef SYNCTEX_NOTHING
5570
# pragma mark + SCAN MATH
5572
ns = _synctex_parse_new_math(scanner);
5573
if (ns.status == SYNCTEX_STATUS_OK) {
5575
_synctex_node_set_sibling(child,ns.node);
5577
_synctex_node_set_child(parent,ns.node);
5581
__synctex_node_make_friend_tlc(child);
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);
5588
input.node = _synctex_input_register_line(input.node,child);
5589
last_k = last_g = NULL;
5592
} else if (SYNCTEX_START_SCAN(FORM_REF)) {
5593
# ifdef SYNCTEX_NOTHING
5594
# pragma mark + SCAN FORM REF
5596
#if SYNCTEX_DEBUG>500
5597
synctex_node_display(parent);
5598
synctex_node_display(child);
5600
ns = _synctex_parse_new_ref(scanner);
5601
if (ns.status == SYNCTEX_STATUS_OK) {
5603
_synctex_node_set_sibling(child,ns.node);
5605
_synctex_node_set_child(parent,ns.node);
5609
if (scanner->ref_in_form) {
5610
synctex_tree_set_friend(child,scanner->ref_in_form);
5612
scanner->ref_in_form = child;
5614
if (scanner->ref_in_sheet) {
5615
synctex_tree_set_friend(child,scanner->ref_in_sheet);
5617
scanner->ref_in_sheet = child;
5619
# if SYNCTEX_VERBOSE
5620
synctex_node_log(child);
5622
last_k = last_g = NULL;
5625
} else if (SYNCTEX_START_SCAN(BOUNDARY)) {
5626
# ifdef SYNCTEX_NOTHING
5627
# pragma mark + SCAN BOUNDARY
5629
ns = _synctex_parse_new_boundary(scanner);
5630
if (ns.status == SYNCTEX_STATUS_OK) {
5632
_synctex_node_set_sibling(child,ns.node);
5634
_synctex_node_set_child(parent,ns.node);
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);
5642
_synctex_tree_set_target(x_handle,ns.node);
5644
__synctex_node_make_friend_tlc(ns.node);
5647
_synctex_make_hbox_contain_point(parent,_synctex_data_point(child));
5648
# if SYNCTEX_VERBOSE
5649
synctex_node_log(child);
5651
input.node = _synctex_input_register_line(input.node,child);
5652
last_k = last_g = NULL;
5655
} else if (SYNCTEX_START_SCAN(CHARACTER)) {
5656
# ifdef SYNCTEX_NOTHING
5657
# pragma mark + SCAN CHARACTER
5660
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5661
_synctex_error("Missing end of container.");
5662
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5664
last_k = last_g = NULL;
5666
} else if (SYNCTEX_START_SCAN(ANCHOR)) {
5667
# ifdef SYNCTEX_NOTHING
5668
# pragma mark + SCAN ANCHOR
5671
} else if (SYNCTEX_START_SCAN(END_SHEET)) {
5672
if (sheet && parent == sheet) {
5673
# ifdef SYNCTEX_NOTHING
5674
# pragma mark + SCAN TEEHS
5677
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5678
_synctex_error("Missing anchor.");
5680
parent = sheet = NULL;
5683
} else if (SYNCTEX_START_SCAN(END_FORM)) {
5684
if (parent == form && form_depth > 0) {
5685
# ifdef SYNCTEX_NOTHING
5686
# pragma mark + SCAN MROF
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);
5695
if ((parent = _synctex_tree_parent(form))) {
5696
_synctex_tree_reset_parent(form);
5703
child = synctex_node_last_sibling(child);
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);
5714
last_k = last_g = NULL;
5717
zs = _synctex_buffer_get_available_size(scanner,1);
5719
_synctex_error("Incomplete synctex file, postamble missing.");
5720
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
5722
last_k = last_g = NULL;
5725
#undef SYNCTEX_RETURN
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
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;
5762
#if SYNCTEX_DEBUG>500
5763
printf("! Ref replacement:\n");
5764
synctex_node_log(ref);
5765
synctex_node_display(synctex_node_sibling(ref));
5767
} else /* simply remove ref */ {
5768
_synctex_tree_set_sibling(arg_sibling,sibling);
5770
__synctex_tree_reset_parent(ref);
5772
_synctex_error("! Missing parent in __synctex_replace_ref. "
5774
ns.status = SYNCTEX_STATUS_BAD_ARGUMENT;
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
5785
SYNCTEX_INLINE static synctex_ns_s _synctex_post_process_ref(synctex_node_p ref) {
5786
synctex_ns_s ns = {NULL, SYNCTEX_STATUS_OK};
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;
5793
/* Insert all the created proxies in the list
5794
* sub_ns.node is the last friend,
5796
synctex_tree_set_friend(sub_ns.node,ns.node);
5797
ns.node = sub_ns.node;
5799
synctex_node_free(ref);
5804
typedef synctex_node_p (* synctex_processor_f)(synctex_node_p node);
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.
5810
SYNCTEX_INLINE static synctex_status_t _synctex_post_process_proxy(synctex_node_p proxy, synctex_processor_f f) {
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. */
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);
5826
#if SYNCTEX_DEBUG>500
5827
printf("POST PROCESSING %s\n",_synctex_node_abstract(proxy));
5830
for (i=0;i<proxy->class_->scanner->number_of_lists;++i) {
5831
synctex_node_p N = proxy->class_->scanner->lists_of_friends[i];
5835
printf("%s",_synctex_node_abstract(N));
5837
} while ((N = _synctex_tree_friend(N)));
5840
printf("\nBeforehand %i match\n",j);
5845
#if SYNCTEX_DEBUG>500
5848
for (i=0;i<proxy->class_->scanner->number_of_lists;++i) {
5849
synctex_node_p N = proxy->class_->scanner->lists_of_friends[i];
5853
printf("%s",_synctex_node_abstract(N));
5855
} while ((N = _synctex_tree_friend(N)));
5858
printf("\n%i match\n",j);
5862
/* Side effect: create the hierarchy on the fly */
5863
proxy = synctex_node_next(proxy); /* Change is here */
5864
#if SYNCTEX_DEBUG>500
5867
for (i=0;i<proxy->class_->scanner->number_of_lists;++i) {
5868
synctex_node_p N = proxy->class_->scanner->lists_of_friends[i];
5872
printf("%s",_synctex_node_abstract(N));
5874
} while ((N = _synctex_tree_friend(N)));
5877
printf("\nnext %i match\n",j);
5881
} while (proxy && proxy != halt);
5884
return SYNCTEX_STATUS_OK;
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
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);
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) {
5907
#if SYNCTEX_DEBUG>500
5908
printf("! ref replaced in form _synctex_post_process.\n");
5909
synctex_node_display(scanner->form);
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) {
5923
/* replace form refs inside sheets by box proxies */
5924
ns = _synctex_post_process_ref(scanner->ref_in_sheet);
5925
if (ns.status<status) {
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);
5936
for (i=0;i<scanner->number_of_lists;++i) {
5937
synctex_node_p P = ns.node;
5939
synctex_node_p N = scanner->lists_of_friends[i];
5942
printf("Already registered.\n");
5943
synctex_node_display(N);
5946
} while ((N = _synctex_tree_friend(N)));
5947
} while((P = _synctex_tree_friend(P)));
5951
#if SYNCTEX_DEBUG>10000
5954
for (i=0;i<scanner->number_of_lists;++i) {
5955
synctex_node_p P = scanner->lists_of_friends[i];
5959
synctex_node_log(P);
5960
P = _synctex_tree_friend(P);
5963
printf("friends %i -> # %i\n",i,j);
5968
ns.status = _synctex_post_process_proxy(ns.node,&__synctex_proxy_make_friend_and_next_hbox);
5969
if (ns.status<status) {
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);
2132
cumulated_line_numbers += SYNCTEX_MEAN_LINE(node);
2136
cumulated_line_numbers += SYNCTEX_LINE(node);
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;
2142
SYNCTEX_MEAN_LINE(parent)=SYNCTEX_LINE(parent);
2143
SYNCTEX_NODE_WEIGHT(parent)=1;
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);
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);
2154
parent = SYNCTEX_PARENT(child);
2156
_synctex_error("Unexpected end of hbox, ignored.");
2158
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2159
_synctex_error("Uncomplete sheet.");
2160
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2162
# if SYNCTEX_VERBOSE
2163
synctex_node_log(child);
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);
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);
2191
_synctex_error("Can't create vbox record.");
2192
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
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);
2217
_synctex_error("Can't create void hbox record.");
2218
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
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);
2241
_synctex_error("Can't create kern record.");
2242
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
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);
2263
_synctex_error("Can't create glue record.");
2264
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
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);
2285
_synctex_error("Can't create math record.");
2286
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
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);
2307
_synctex_error("Can't create math record.");
2308
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2310
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
2312
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) {
2313
/* Addendum to version 1.10 to manage nested sheets */
2315
if (_synctex_scan_nested_sheet(scanner)<SYNCTEX_STATUS_OK) {
2316
_synctex_error("Unexpected nested sheet.");
2317
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2320
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
2323
/* _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
2325
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2326
_synctex_error("Unexpected end.");
2327
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
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. */
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);
2359
SYNCTEX_SET_SIBLING(child,sibling);
2364
_synctex_error("Can't create vbox record (2).");
2365
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2367
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_VBOX) {
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);
2384
SYNCTEX_SET_SIBLING(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);
2395
_synctex_error("Can't create hbox record (2).");
2396
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2398
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_HBOX) {
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);
2414
SYNCTEX_SET_SIBLING(child,sibling);
2416
# if SYNCTEX_VERBOSE
2417
synctex_node_log(child);
2419
SYNCTEX_UPDATE_FRIEND(child);
2422
_synctex_error("can't create void vbox record (2).");
2423
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
2439
SYNCTEX_SET_SIBLING(child,sibling);
2441
# if SYNCTEX_VERBOSE
2442
synctex_node_log(child);
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));
2449
_synctex_error("can't create void hbox record (2).");
2450
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
2464
SYNCTEX_SET_SIBLING(child,sibling);
2466
# if SYNCTEX_VERBOSE
2467
synctex_node_log(child);
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));
2474
_synctex_error("Can't create kern record (2).");
2475
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
2488
SYNCTEX_SET_SIBLING(child,sibling);
2490
# if SYNCTEX_VERBOSE
2491
synctex_node_log(child);
2493
SYNCTEX_UPDATE_FRIEND(child);
2494
_synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2497
_synctex_error("Can't create glue record (2).");
2498
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
2511
SYNCTEX_SET_SIBLING(child,sibling);
2513
# if SYNCTEX_VERBOSE
2514
synctex_node_log(child);
2516
SYNCTEX_UPDATE_FRIEND(child);
2517
_synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2520
_synctex_error("Can't create math record (2).");
2521
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
2534
SYNCTEX_SET_SIBLING(child,sibling);
2536
# if SYNCTEX_VERBOSE
2537
synctex_node_log(child);
2539
SYNCTEX_UPDATE_FRIEND(child);
2540
_synctex_hbox_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2543
_synctex_error("Can't create boundary record (2).");
2544
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2546
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
2548
} else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
2550
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2551
_synctex_error("Missing anchor (2).");
2552
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
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);
2565
status = _synctex_buffer_get_available_size(scanner,&available);
2566
if (status<SYNCTEX_STATUS_OK && available>0){
2569
_synctex_error("Uncomplete sheet(2)");
2570
SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2573
# undef SYNCTEX_DECODE_FAILED
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;\
2582
SYNCTEX_SET_SIBLING(last_sheet,SHEET);\
2584
SCANNER->sheet = SHEET;\
5982
2587
/* Used when parsing the synctex file
5984
static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner) {
5985
if (NULL == scanner) {
5986
return SYNCTEX_STATUS_BAD_ARGUMENT;
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;
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;
2604
/* Find where this section starts */
5991
2605
content_not_found:
5992
status = _synctex_match_string(scanner,"Content:");
5993
if (status<SYNCTEX_STATUS_EOF) {
5996
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
5997
_synctex_error("Incomplete Content.");
5998
return SYNCTEX_STATUS_ERROR;
6000
if (status == SYNCTEX_STATUS_NOT_OK) {
6001
goto content_not_found;
6003
status = __synctex_parse_sfi(scanner);
6004
if (status == SYNCTEX_STATUS_OK) {
6005
status = _synctex_post_process(scanner);
6009
synctex_scanner_p synctex_scanner_new() {
6010
synctex_scanner_p scanner =(synctex_scanner_p)_synctex_malloc(sizeof(synctex_scanner_s));
6012
if (!(scanner->reader = _synctex_malloc(sizeof(synctex_reader_s)))) {
6013
_synctex_free(scanner);
6016
# ifdef SYNCTEX_NOTHING
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");
6049
scanner->display_switcher = 100;
6050
scanner->display_prompt = (char *)_synctex_display_prompt+strlen(_synctex_display_prompt)-1;
2606
status = _synctex_match_string(scanner,"Content:");
2607
if (status<SYNCTEX_STATUS_EOF) {
2610
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2611
_synctex_error("Uncomplete Content.");
2612
return SYNCTEX_STATUS_ERROR;
2614
if (status == SYNCTEX_STATUS_NOT_OK) {
2615
goto content_not_found;
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.");
2624
if (status<SYNCTEX_STATUS_OK) {
2625
status = _synctex_next_line(scanner);
2626
if (status < SYNCTEX_STATUS_OK) {
2627
_synctex_error("Bad content.");
2632
return SYNCTEX_STATUS_OK;
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.");
2640
SYNCTEX_FREE(sheet);
2641
return SYNCTEX_STATUS_ERROR;
2643
status = _synctex_next_line(scanner);
2644
if (status<SYNCTEX_STATUS_OK) {
2645
_synctex_error("Uncomplete file.");
2648
status = _synctex_scan_sheet(scanner,sheet);
2649
if (status<SYNCTEX_STATUS_OK) {
2650
_synctex_error("Bad sheet content.");
2653
SYNCTEX_APPEND_SHEET(scanner,sheet);
2655
/* Now read the list of Inputs between 2 sheets. */
2657
status = _synctex_scan_input(scanner);
2658
if (status<SYNCTEX_STATUS_EOF) {
2659
_synctex_error("Bad input section.");
2663
while(status >= SYNCTEX_STATUS_OK);
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);
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");
6061
if (synctex_reader_init_with_output_file(scanner->reader, output, build_directory)) {
6062
return parse? synctex_scanner_parse(scanner):scanner;
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);
2670
synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) {
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.");
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)");
2686
if (SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE) {
2687
_synctex_error("Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (2)");
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) {
2696
scanner = (synctex_scanner_t)_synctex_malloc(sizeof(_synctex_scanner_t));
2697
if (NULL == scanner) {
2698
_synctex_error("malloc problem");
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.");
2709
scanner->synctex = synctex;/* Now the scanner owns synctex */
2710
SYNCTEX_FILE = file;
2711
return parse? synctex_scanner_parse(scanner):scanner;
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;
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");
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");
2742
free(quoteless_synctex_name);
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;
2750
/* now insert quotes. */
2752
char * quoted = NULL;
2753
if (_synctex_copy_with_quoting_last_path_component(synctex_name,"ed,size) || (NULL == quoted)) {
2754
/* There was an error or quoting does not make sense: */
2755
goto return_on_error;
2757
quoteless_synctex_name = synctex_name;
2758
synctex_name = quoted;
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;
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;
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;
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;
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;
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);
2795
goto return_on_error;
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) {
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);
2812
goto return_on_error;
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);
2822
goto return_on_error;
2824
/* The quote free file name should replace the old one:*/
2826
synctex_name = quoteless_synctex_name;
2827
quoteless_synctex_name = NULL;
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;
2836
return 3; /* Bad parameter. */
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;
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);
2855
size += strlen(output);
2857
if ((build_output = (char *)malloc(size))) {
2859
build_output[0] = '\0';
2861
if (build_output != strcpy(build_output,output)) {
2865
build_output[lpc-output]='\0';
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,"/")) {
2875
/* Append the last path component of the output. */
2876
if (build_output != strcat(build_output,lpc)) {
2880
result = __synctex_open(build_output,synctex_name_ref,file_ref,add_quotes,io_mode_ref);
2889
# undef synctex_name
6070
2893
/* The scanner destructor
6072
int synctex_scanner_free(synctex_scanner_p 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;
2895
void synctex_scanner_free(synctex_scanner_t scanner) {
2896
if (NULL == scanner) {
2900
gzclose(SYNCTEX_FILE);
2901
SYNCTEX_FILE = NULL;
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);
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) {
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;
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) {
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);
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;
6116
status = _synctex_scan_preamble(scanner);
6117
if (status<SYNCTEX_STATUS_OK) {
6118
_synctex_error("Bad preamble\n");
6120
#ifdef SYNCTEX_DEBUG
6123
synctex_scanner_free(scanner);
6127
status = _synctex_scan_content(scanner);
6128
if (status<SYNCTEX_STATUS_OK) {
6129
_synctex_error("Bad content\n");
6132
status = _synctex_scan_postamble(scanner);
6133
if (status<SYNCTEX_STATUS_OK) {
6134
_synctex_error("Bad postamble. Ignored\n");
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);
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;
6153
if (scanner->pre_magnification<=0) {
6154
scanner->pre_magnification = 1000;
6156
if (scanner->unit <= 0) {
6157
/* no post magnification */
6158
scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/
6160
/* post magnification */
6161
scanner->unit *= scanner->pre_unit / 65781.76;
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);
6170
scanner->x_offset /= 65781.76f;
6171
scanner->y_offset /= 65781.76f;
2954
status = _synctex_scan_preamble(scanner);
2955
if (status<SYNCTEX_STATUS_OK) {
2956
_synctex_error("SyncTeX Error: Bad preamble\n");
2958
synctex_scanner_free(scanner);
2961
status = _synctex_scan_content(scanner);
2962
if (status<SYNCTEX_STATUS_OK) {
2963
_synctex_error("SyncTeX Error: Bad content\n");
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;
2977
if (scanner->pre_magnification<=0) {
2978
scanner->pre_magnification = 1000;
2980
if (scanner->unit <= 0) {
2981
/* no post magnification */
2982
scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/
2984
/* post magnification */
2985
scanner->unit *= scanner->pre_unit / 65781.76;
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);
2994
scanner->x_offset /= 65781.76f;
2995
scanner->y_offset /= 65781.76f;
6177
3001
/* Scanner accessors.
6179
int synctex_scanner_pre_x_offset(synctex_scanner_p scanner){
6180
return scanner?scanner->pre_x_offset:0;
6182
int synctex_scanner_pre_y_offset(synctex_scanner_p scanner){
6183
return scanner?scanner->pre_y_offset:0;
6185
int synctex_scanner_x_offset(synctex_scanner_p scanner){
6186
return scanner?scanner->x_offset:0;
6188
int synctex_scanner_y_offset(synctex_scanner_p scanner){
6189
return scanner?scanner->y_offset:0;
6191
float synctex_scanner_magnification(synctex_scanner_p scanner){
6192
return scanner?scanner->unit:1;
6194
void synctex_scanner_display(synctex_scanner_p scanner) {
6195
if (NULL == scanner) {
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;
6212
printf("Friend index:%i\n",i);
6213
node = (scanner->lists_of_friends)[i];
6215
printf("%s:%i,%i\n",
6216
synctex_node_isa(node),
6217
_synctex_data_tag(node),
6218
_synctex_data_line(node)
6220
node = _synctex_tree_friend(node);
6225
printf("SyncTeX Warning: Too many objects\n");
6229
const char * synctex_scanner_get_name(synctex_scanner_p scanner,int tag) {
6230
synctex_node_p input = NULL;
6231
if (NULL == scanner) {
6234
if ((input = scanner->input)) {;
6236
if (tag == _synctex_data_tag(input)) {
6237
return (_synctex_data_name(input));
6239
} while((input = __synctex_tree_sibling(input)));
6243
const char * synctex_node_get_name(synctex_node_p node) {
6245
return synctex_scanner_get_name(node->class_->scanner,_synctex_data_tag(node));
3003
int synctex_scanner_pre_x_offset(synctex_scanner_t scanner){
3004
return scanner?scanner->pre_x_offset:0;
3006
int synctex_scanner_pre_y_offset(synctex_scanner_t scanner){
3007
return scanner?scanner->pre_y_offset:0;
3009
int synctex_scanner_x_offset(synctex_scanner_t scanner){
3010
return scanner?scanner->x_offset:0;
3012
int synctex_scanner_y_offset(synctex_scanner_t scanner){
3013
return scanner?scanner->y_offset:0;
3015
float synctex_scanner_magnification(synctex_scanner_t scanner){
3016
return scanner?scanner->unit:1;
3018
void synctex_scanner_display(synctex_scanner_t scanner) {
3019
if (NULL == scanner) {
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;
3036
printf("Friend index:%i\n",i);
3037
node = (scanner->lists_of_friends)[i];
3039
printf("%s:%i,%i\n",
3040
synctex_node_isa(node),
3044
node = SYNCTEX_FRIEND(node);
3049
printf("SyncTeX Warning: Too many objects\n");
3053
const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag) {
3054
synctex_node_t input = NULL;
3055
if (NULL == scanner) {
3058
input = scanner->input;
3060
if (tag == SYNCTEX_TAG(input)) {
3061
return (SYNCTEX_NAME(input));
3063
} while((input = SYNCTEX_SIBLING(input)) != NULL);
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) {
6256
if ((input = scanner->input)) {
6258
if (_synctex_is_equivalent_file_name(name,(_synctex_data_name(input)))) {
6259
return _synctex_data_tag(input);
6261
} while((input = __synctex_tree_sibling(input)));
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) {
3073
input = scanner->input;
3075
if (_synctex_is_equivalent_file_name(name,(SYNCTEX_NAME(input)))) {
3076
return SYNCTEX_TAG(input);
3078
} while((input = SYNCTEX_SIBLING(input)) != NULL);
6263
3079
// 2011 version
6264
3080
name = _synctex_base_name(name);
6265
if ((input = scanner->input)) {
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
3081
input = scanner->input;
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
6277
return _synctex_data_tag(input);
6279
} while((input = __synctex_tree_sibling(input)));
3093
return SYNCTEX_TAG(input);
3095
} while((input = SYNCTEX_SIBLING(input)) != NULL);
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 */
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);
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))
6304
/* Find the last path separator before relative */
6305
while(relative > name) {
6306
if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) {
6311
if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) {
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) {
6319
if (SYNCTEX_IS_PATH_SEPARATOR(name[char_index])
6320
&& (result = _synctex_scanner_get_tag(scanner,name+char_index+1))) {
6331
synctex_node_p synctex_scanner_input(synctex_scanner_p scanner) {
6332
return scanner?scanner->input:NULL;
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))) {
6344
const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner) {
6345
return NULL != scanner && scanner->output_fmt?scanner->output_fmt:"";
6347
const char * synctex_scanner_get_output(synctex_scanner_p scanner) {
6348
return NULL != scanner && scanner->reader->output?scanner->reader->output:"";
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 */
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);
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))
3119
/* Find the last path separator before relative */
3120
while(relative > name) {
3121
if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) {
3126
if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) {
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) {
3134
if (SYNCTEX_IS_PATH_SEPARATOR(name[char_index])
3135
&& (result = _synctex_scanner_get_tag(scanner,name+char_index+1))) {
3146
synctex_node_t synctex_scanner_input(synctex_scanner_t scanner) {
3147
return scanner?scanner->input:NULL;
3149
const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner) {
3150
return NULL != scanner && scanner->output_fmt?scanner->output_fmt:"";
3152
const char * synctex_scanner_get_output(synctex_scanner_t scanner) {
3153
return NULL != scanner && scanner->output?scanner->output:"";
3155
const char * synctex_scanner_get_synctex(synctex_scanner_t scanner) {
3156
return NULL != scanner && scanner->synctex?scanner->synctex:"";
6353
3158
# ifdef SYNCTEX_NOTHING
6354
3159
# pragma mark -
6355
3160
# pragma mark Public node attributes
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; \
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); \
6367
return _synctex_data_##WHAT(proxy)+synctex_node_##WHAT(target); \
6369
return proxy? _synctex_data_##WHAT(proxy): 0; \
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; \
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.
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)
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
6410
SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_box(synctex_node_p 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)));
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
6427
SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_handle(synctex_node_p node) {
6429
(node->class_->type == synctex_node_type_handle);
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.
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;
6445
* Whether the argument is an hbox.
6446
* - parameter NODE: of type synctex_node_p
6450
SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_hbox(synctex_node_p 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)));
6458
* The horizontal location of the first box enclosing node.
6459
* - parameter node: a node with geometrical information.
6460
* - returns: an integer.
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);
6470
* The vertical location of the first box enclosing node.
6471
* - parameter node: a node with geometrical information.
6472
* - returns: an integer.
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);
6482
* The width of the first box enclosing node.
6483
* - parameter node: a node with geometrical information.
6484
* - returns: an integer.
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);
6494
* The height of the first box enclosing node.
6495
* - parameter node: a node with geometrical information.
6496
* - returns: an integer.
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);
6506
* The depth of the first box enclosing node.
6507
* - parameter node: a node with geometrical information.
6508
* - returns: an integer.
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);
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.
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));
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.
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));
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.
6557
int synctex_node_hbox_width(synctex_node_p node) {
6558
synctex_node_p target = _synctex_tree_target(node);
6562
return synctex_node_type(node) == synctex_node_type_hbox?
6563
_synctex_data_width_V(node): 0;
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.
6571
int synctex_node_hbox_height(synctex_node_p node) {
6572
synctex_node_p target = _synctex_tree_target(node);
6576
return synctex_node_type(node) == synctex_node_type_hbox?
6577
_synctex_data_height_V(node): 0;
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.
6586
int synctex_node_hbox_depth(synctex_node_p node) {
6587
synctex_node_p target = _synctex_tree_target(node);
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){
3166
return SYNCTEX_HORIZ(node);
3168
int synctex_node_v(synctex_node_t node){
3172
return SYNCTEX_VERT(node);
3174
int synctex_node_width(synctex_node_t node){
3178
return SYNCTEX_WIDTH(node);
3180
int synctex_node_box_h(synctex_node_t node){
3184
if (SYNCTEX_IS_BOX(node)) {
3186
return SYNCTEX_HORIZ(node);
3188
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3193
int synctex_node_box_v(synctex_node_t node){
3197
if (SYNCTEX_IS_BOX(node)) {
3199
return SYNCTEX_VERT(node);
3201
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3206
int synctex_node_box_width(synctex_node_t node){
3210
if (SYNCTEX_IS_BOX(node)) {
3212
return SYNCTEX_WIDTH(node);
3214
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3219
int synctex_node_box_height(synctex_node_t node){
3223
if (SYNCTEX_IS_BOX(node)) {
3225
return SYNCTEX_HEIGHT(node);
3227
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3232
int synctex_node_box_depth(synctex_node_t node){
3236
if (SYNCTEX_IS_BOX(node)) {
3238
return SYNCTEX_DEPTH(node);
3240
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
6594
3245
# ifdef SYNCTEX_NOTHING
6595
3246
# pragma mark -
6596
3247
# pragma mark Public node visible attributes
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));
6608
static float __synctex_node_visible_v(synctex_node_p node) {
6609
return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node));
6611
static float __synctex_node_visible_width(synctex_node_p node) {
6612
return SYNCTEX_VISIBLE_SIZE(node,synctex_node_width(node));
6614
static float __synctex_node_visible_height(synctex_node_p node) {
6615
return SYNCTEX_VISIBLE_SIZE(node,synctex_node_height(node));
6617
static float __synctex_node_visible_depth(synctex_node_p node) {
6618
return SYNCTEX_VISIBLE_SIZE(node,synctex_node_depth(node));
6620
static float __synctex_proxy_visible_h(synctex_node_p node) {
6621
return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node));
6623
static float __synctex_proxy_visible_v(synctex_node_p node) {
6624
return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node));
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);
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);
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);
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);
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);
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);
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);
6656
static float __synctex_rule_visible_v(synctex_noxy_p noxy) {
6657
return __synctex_node_visible_v(noxy);
6659
static float __synctex_rule_visible_height(synctex_noxy_p noxy) {
6660
return __synctex_node_visible_height(noxy);
6662
static float __synctex_rule_visible_depth(synctex_noxy_p noxy) {
6663
return __synctex_node_visible_depth(noxy);
6667
* The horizontal location of node, in page coordinates.
6668
* - parameter node: a node.
6669
* - returns: a float.
6672
float synctex_node_visible_h(synctex_node_p node){
6673
return node? node->class_->vispector->h(node): 0;
6676
* The vertical location of node, in page coordinates.
6677
* - parameter node: a node.
6678
* - returns: a float.
6681
float synctex_node_visible_v(synctex_node_p node){
6682
return node? node->class_->vispector->v(node): 0;
6685
* The width of node, in page coordinates.
6686
* - parameter node: a node.
6687
* - returns: a float.
6690
float synctex_node_visible_width(synctex_node_p node){
6691
return node? node->class_->vispector->width(node): 0;
6694
* The height of node, in page coordinates.
6695
* - parameter node: a node.
6696
* - returns: a float.
6699
float synctex_node_visible_height(synctex_node_p node){
6700
return node? node->class_->vispector->height(node): 0;
6703
* The depth of node, in page coordinates.
6704
* - parameter node: a node.
6705
* - returns: a float.
6708
float synctex_node_visible_depth(synctex_node_p node){
6709
return node? node->class_->vispector->depth(node): 0;
6713
* The V variant of geometrical information.
6714
* - parameter node: a node.
6715
* - returns: an integer.
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); \
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); \
6726
return _synctex_data_##WHAT(node); \
6731
SYNCTEX_DEFINE_V(width)
6732
SYNCTEX_DEFINE_V(height)
6733
SYNCTEX_DEFINE_V(depth)
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)};
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)};
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);
6747
SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node) {
6748
synctex_box_s box = {{0,0},{0,0}};
6750
n = synctex_node_width(node);
6752
box.max.h = synctex_node_h(node);
6753
box.min.h = box.max.h + n;
6755
box.min.h = synctex_node_h(node);
6756
box.max.h = box.min.h + n;
6758
n = synctex_node_v(node);
6759
box.min.v = n - synctex_node_height(node);
6760
box.max.v = n + synctex_node_depth(node);
6763
SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node) {
6764
synctex_box_s box = {{0,0},{0,0}};
6766
n = synctex_node_width(node);
6768
box.max.h = synctex_node_h(node);
6769
box.min.h = box.max.h - n;
6771
box.min.h = synctex_node_h(node);
6772
box.max.h = box.min.h - n;
6774
n = synctex_node_v(node);
6775
box.min.v = n - synctex_node_height(node);
6776
box.max.v = n + synctex_node_depth(node);
6779
SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node) {
6780
synctex_box_s box = {{0,0},{0,0}};
6782
n = _synctex_node_width_V(node);
6784
box.max.h = _synctex_node_h_V(node);
6785
box.min.h = box.max.h + n;
6787
box.min.h = _synctex_node_h_V(node);
6788
box.max.h = box.min.h + n;
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);
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
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.
6810
static synctex_node_p _synctex_node_box_visible(synctex_node_p node) {
6811
if ((node = _synctex_node_or_handle_target(node))) {
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))) {
6821
} else if ((node = _synctex_tree_target(node))) {
6822
if (!_synctex_node_is_box(node)) {
6823
if ((parent = _synctex_tree_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) {
6837
} else if (synctex_node_width(parent)>bound) {
6839
} else if (synctex_node_height(parent)+synctex_node_depth(parent)>bound) {
6849
* The horizontal location of the first box enclosing node, in page coordinates.
6850
* - parameter node: a node.
6851
* - returns: a float.
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)));
6858
* The vertical location of the first box enclosing node, in page coordinates.
6859
* - parameter node: a node.
6860
* - returns: a float.
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)));
6867
* The width of the first box enclosing node, in page coordinates.
6868
* - parameter node: a node.
6869
* - returns: a float.
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)));
6876
* The height of the first box enclosing node, in page coordinates.
6877
* - parameter node: a node.
6878
* - returns: a float.
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)));
6885
* The depth of the first box enclosing node, in page coordinates.
6886
* - parameter node: a node.
6887
* - returns: a float.
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){
3253
return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset;
3255
float synctex_node_visible_v(synctex_node_t node){
3259
return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset;
3261
float synctex_node_visible_width(synctex_node_t node){
3265
return SYNCTEX_WIDTH(node)*node->class->scanner->unit;
3267
float synctex_node_box_visible_h(synctex_node_t node){
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:
3278
return SYNCTEX_HORIZ_V(node)*node->class->scanner->unit+node->class->scanner->x_offset;
3280
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3285
float synctex_node_box_visible_v(synctex_node_t node){
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:
3296
return SYNCTEX_VERT_V(node)*node->class->scanner->unit+node->class->scanner->y_offset;
3298
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3303
float synctex_node_box_visible_width(synctex_node_t node){
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:
3314
return SYNCTEX_WIDTH_V(node)*node->class->scanner->unit;
3316
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3321
float synctex_node_box_visible_height(synctex_node_t node){
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:
3332
return SYNCTEX_HEIGHT_V(node)*node->class->scanner->unit;
3334
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3339
float synctex_node_box_visible_depth(synctex_node_t node){
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:
3350
return SYNCTEX_DEPTH_V(node)*node->class->scanner->unit;
3352
if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
6893
3357
# ifdef SYNCTEX_NOTHING
6894
3358
# pragma mark -
6895
3359
# pragma mark Other public node attributes
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.
6908
int synctex_node_page(synctex_node_p node){
6909
synctex_node_p parent = NULL;
6910
while((parent = _synctex_tree_parent(node))) {
6913
if (synctex_node_type(node) == synctex_node_type_sheet) {
6914
return _synctex_data_page(node);
6919
* The page number of the target.
6922
SYNCTEX_INLINE static int _synctex_node_target_page(synctex_node_p node){
6923
return synctex_node_page(_synctex_tree_target(node));
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);
6934
* The tag of the node.
6935
* - parameter node: a node.
6936
* - returns: the tag or -1 if node is NULL.
6939
int synctex_node_tag(synctex_node_p node) {
6940
return node? node->class_->tlcpector->tag(node): -1;
6943
* The line of the node.
6944
* - parameter node: a node.
6945
* - returns: the line or -1 if node is NULL.
6948
int synctex_node_line(synctex_node_p node) {
6949
return node? node->class_->tlcpector->line(node): -1;
6952
* The column of the node.
6953
* - parameter node: a node.
6954
* - returns: the column or -1 if node is NULL.
6957
int synctex_node_column(synctex_node_p node) {
6958
return node? node->class_->tlcpector->column(node): -1;
6961
* The mean line number of the node.
6962
* - parameter node: a node.
6963
* - returns: the mean line or -1 if node is NULL.
6966
int synctex_node_mean_line(synctex_node_p node) {
6967
synctex_node_p other = _synctex_tree_target(node);
6971
if (_synctex_data_has_mean_line(node)) {
6972
return _synctex_data_mean_line(node);
6974
if ((other = synctex_node_parent(node))) {
6975
if (_synctex_data_has_mean_line(other)) {
6976
return _synctex_data_mean_line(other);
6979
return synctex_node_line(node);
6982
* The weight of the node.
6983
* - parameter node: a node.
6984
* - returns: the weight or -1 if node is NULL.
6987
int synctex_node_weight(synctex_node_p node) {
6988
synctex_node_p target = _synctex_tree_target(node);
6992
return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1;
6995
* The number of children of the node.
6996
* - parameter node: a node.
6997
* - returns: the count or -1 if node is NULL.
7000
int synctex_node_child_count(synctex_node_p node) {
7001
synctex_node_p target = _synctex_tree_target(node);
7005
return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1;
7007
# ifdef SYNCTEX_NOTHING
7009
# pragma mark Sheet & Form
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.
7020
synctex_node_p synctex_sheet(synctex_scanner_p scanner,int page) {
7022
synctex_node_p sheet = scanner->sheet;
7024
if (page == _synctex_data_page(sheet)) {
7027
sheet = __synctex_tree_sibling(sheet);
7030
return scanner->sheet;
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.
7043
synctex_node_p synctex_form(synctex_scanner_p scanner,int tag) {
7045
synctex_node_p form = scanner->form;
7047
if (tag == _synctex_data_tag(form)) {
7050
form = __synctex_tree_sibling(form);
7053
return scanner->form;
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.
7066
synctex_node_p synctex_sheet_content(synctex_scanner_p scanner,int page) {
7068
return _synctex_tree_child(synctex_sheet(scanner,page));
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.
7080
synctex_node_p synctex_form_content(synctex_scanner_p scanner,int tag) {
7082
return _synctex_tree_child(synctex_form(scanner,tag));
7087
SYNCTEX_INLINE static synctex_node_p _synctex_scanner_friend(synctex_scanner_p scanner,int i) {
7089
i = _synctex_abs(i)%(scanner->number_of_lists);
7090
return (scanner->lists_of_friends)[i];
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);
7098
* The sibling argument is a parent/child list of nodes of the same page.
3362
int synctex_node_page(synctex_node_t node){
3363
synctex_node_t parent = NULL;
3367
parent = SYNCTEX_PARENT(node);
3370
parent = SYNCTEX_PARENT(node);
3372
if (node->class->type == synctex_node_type_sheet) {
3373
return SYNCTEX_PAGE(node);
3377
synctex_charindex_t synctex_node_charindex(synctex_node_t node) {
3378
return node?SYNCTEX_CHARINDEX(node):0;
3380
int synctex_node_tag(synctex_node_t node) {
3381
return node?SYNCTEX_TAG(node):-1;
3383
int synctex_node_line(synctex_node_t node) {
3384
return node?SYNCTEX_LINE(node):-1;
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;
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;
3392
int synctex_node_column(synctex_node_t node) {
3393
# ifdef __DARWIN_UNIX03
3394
# pragma unused(node)
3398
# ifdef SYNCTEX_NOTHING
3403
synctex_node_t synctex_sheet(synctex_scanner_t scanner,int page) {
3405
synctex_node_t sheet = scanner->sheet;
3407
if (page == SYNCTEX_PAGE(sheet)) {
3410
sheet = SYNCTEX_SIBLING(sheet);
3416
synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page) {
3418
return SYNCTEX_CHILD(synctex_sheet(scanner,page));
3423
# ifdef SYNCTEX_NOTHING
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)
3432
int tag = synctex_scanner_get_tag(scanner,name);
3434
int friend_index = 0;
3436
synctex_node_t node = NULL;
3438
printf("SyncTeX Warning: No tag for %s\n",name);
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])) {
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) {
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 *);
3459
*(synctex_node_t *)SYNCTEX_CUR = node;
3460
SYNCTEX_CUR += sizeof(synctex_node_t);
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 */
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) {
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 *);
3477
*(synctex_node_t *)SYNCTEX_CUR = node;
3478
SYNCTEX_CUR += sizeof(synctex_node_t);
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 */
3485
if ((tag == SYNCTEX_TAG(node))
3486
&& (line == SYNCTEX_LINE(node))) {
3487
if (SYNCTEX_CUR == SYNCTEX_END) {
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 *);
3494
*(synctex_node_t *)SYNCTEX_CUR = node;
3495
SYNCTEX_CUR += sizeof(synctex_node_t);
3497
} while((node = SYNCTEX_FRIEND(node)));
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;
3511
while (start_ref < end_ref) {
3513
*start_ref = *end_ref;
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.
3524
best_ref = start_ref = (synctex_node_t *)SYNCTEX_START;
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;
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);
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;
3549
end_ref += 1; /* we allways have start_ref<= end_ref*/
3550
if (end_ref < (synctex_node_t *)SYNCTEX_END) {
3552
while ((node = SYNCTEX_PARENT(node))) {
3553
if (SYNCTEX_PARENT(*start_ref) == node) {
3558
*start_ref = *end_ref;
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
3567
// return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); removed on behalf Jan Sundermeyer
3569
# if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__)
3578
synctex_node_t synctex_next_result(synctex_scanner_t scanner) {
3579
if (NULL == SYNCTEX_CUR) {
3580
SYNCTEX_CUR = SYNCTEX_START;
3582
SYNCTEX_CUR+=sizeof(synctex_node_t);
3584
if (SYNCTEX_CUR<SYNCTEX_END) {
3585
return *(synctex_node_t*)SYNCTEX_CUR;
3591
/* This struct records a point in TeX coordinates.*/
7100
3592
typedef struct {
7102
synctex_node_p node;
7103
} synctex_counted_node_s;
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;
7112
synctex_node_p N = NULL;
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 */
7122
N = _synctex_tree_target(h);
7123
parent = _synctex_tree_parent(N);
7124
weight = _synctex_data_weight(parent);
7126
N = _synctex_tree_child(parent);
7128
if (_synctex_nodes_are_friend(N,sibling)) {
7131
} while ((N = __synctex_tree_sibling(N)));
7132
_synctex_data_set_weight(h,weight);
7133
_synctex_data_set_weight(parent,weight);
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;
7142
if (_synctex_data_weight(h)>_synctex_data_weight(N)) {
7143
next_h = _synctex_tree_set_child(h,N);
7145
} else if (_synctex_data_weight(h) == 0) {
7147
next_h = _synctex_tree_reset_child(h);
7148
synctex_node_free(h);
7150
synctex_node_p next_N = NULL;
7151
while((next_N = _synctex_tree_child(N))) {
7153
if (_synctex_data_weight(h)<_synctex_data_weight(next_N)) {
7158
next_h = _synctex_tree_set_child(h,_synctex_tree_set_child(N,h));
7166
} while((h = _synctex_tree_child(h)));
7169
while((next_h = _synctex_tree_child(h))) {
7170
if (_synctex_data_weight(next_h)==0) {
7171
_synctex_tree_reset_child(h);
7174
while((h = _synctex_tree_child(h))) {
7177
synctex_node_free(next_h);
7186
SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hitP, synctex_node_p node);
7188
/* This struct records distances, the left one is non negative and the right one is non positive.
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.*/
7193
synctex_node_p node;
7197
#define SYNCTEX_ND_0 (synctex_nd_s){NULL,INT_MAX}
7199
typedef synctex_nd_s * synctex_nd_p;
3603
} synctex_distances_t;
3606
synctex_point_t left;
3607
synctex_point_t right;
3608
} synctex_offsets_t;
3612
synctex_node_t left;
3613
synctex_node_t right;
3614
} synctex_node_set_t;
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);
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);
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);
7213
SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node);
7215
/* Closest child, recursive. */
7216
static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node);
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);
7224
/* Returns the distance between the hit point hit point=(H,V) and the given node. */
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);
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);
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);
7232
# ifdef SYNCTEX_NOTHING
7234
# pragma mark Queries
7238
* iterator for a deep first tree traversal.
7240
struct synctex_iterator_t {
7241
synctex_node_p seed;
7243
synctex_node_p next;
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;
7257
void synctex_iterator_free(synctex_iterator_p iterator) {
7259
synctex_node_free(iterator->seed);
7260
_synctex_free(iterator);
7263
synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator) {
7264
return iterator?iterator->count>0:0;
7266
int synctex_iterator_count(synctex_iterator_p iterator) {
7267
return iterator? iterator->count: 0;
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.
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);
7283
return _synctex_tree_target(N);
7287
int synctex_iterator_reset(synctex_iterator_p iterator) {
7289
iterator->next = iterator->top = iterator->seed;
7290
return iterator->count = iterator->count0;
7295
synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner,int page,float h,float v){
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 */
7304
/* Find the proper sheet */
7305
sheet = synctex_sheet(scanner,page);
7306
if (NULL == sheet) {
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))) {
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.
7323
synctex_node_p next = node;
7324
#if defined(SYNCTEX_DEBUG)
7325
printf("--- We are lucky\n");
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);
7333
/* node is the smallest horizontal box that contains hit,
7334
* unless there is no hbox at all.
7336
node = _synctex_eq_deepest_container_v2(&hit, node);
7337
nds = _synctex_eq_get_closest_children_in_box_v2(&hit, node);
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)) {
7345
nds.r.node = nds.l.node;
7347
} else if (_synctex_data_line(nds.r.node)==_synctex_data_line(nds.l.node)) {
7348
if (nds.l.distance>nds.r.distance) {
7350
nds.r.node = nds.l.node;
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);
7360
return _synctex_iterator_new(node,1);
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;
7370
} else if (nds.r.node) {
7372
} else if (!nds.l.node) {
7375
if((node = _synctex_new_handle_with_target(nds.l.node))) {
7376
return _synctex_iterator_new(node,1);
7380
} while ((node = _synctex_tree_next_hbox(node)));
7381
/* All the horizontal boxes have been tested,
7382
* None of them contains the hit point.
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");
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);
7403
* Loop the candidate friendly list to find the ones with the proper
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
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;
7419
&& _synctex_node_is_box(target))
7420
|| (tag != synctex_node_tag(target))
7421
|| (line != synctex_node_line(target))) {
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;
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,
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;
7439
&& _synctex_node_is_box(target))
7440
|| (tag != synctex_node_tag(target))
7441
|| (line != synctex_node_line(target))) {
7444
/* Another match, same page number ? */
7445
result = _synctex_new_handle_with_target(target);
7446
if (NULL == result ) {
7447
return first_handle;
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;
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;
7459
&& _synctex_node_is_box(target))
7460
|| (tag != synctex_node_tag(target))
7461
|| (line != synctex_node_line(target))) {
7464
/* New match found, which page? */
7465
result = _synctex_new_handle_with_target(target);
7466
if (NULL == result) {
7467
return first_handle;
7469
same_page_node = first_handle;
7470
page = synctex_node_page(target);
7471
/* Find a result with the same page number */;
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))) {
7479
/* This is a new page number */
7480
__synctex_tree_set_sibling(result,first_handle);
7481
first_handle = result;
7484
} while (synctex_YES);
7486
return first_handle;
7489
} while ((target = _synctex_tree_friend(target)));
7490
return first_handle;
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)
7495
int tag = synctex_scanner_get_tag(scanner,name);/* parse if necessary */
7497
int line_offset = 1;
7498
int try_count = 100;
7499
synctex_node_p node = NULL;
7500
synctex_node_p result = NULL;
7502
printf("SyncTeX Warning: No tag for %s\n",name);
7505
node = synctex_scanner_input_with_tag(scanner, tag);
7506
max_line = _synctex_data_line(node);
7508
if (line>max_line) {
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);
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);
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.
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;
7539
synctex_counted_node_s cn = _synctex_vertically_sorted_v2(result);
7540
int count = cn.count;
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);
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);
7554
} else /*if (match>=best_match)*/ {
7555
__synctex_tree_set_sibling(sibling,__synctex_tree_sibling(result));
7556
__synctex_tree_set_sibling(result,sibling);
7559
return _synctex_iterator_new(result,count);
7562
# if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__)
7565
line += line_offset;
7566
line_offset=line_offset<0?-(line_offset-1):-(line_offset+1);
7568
line += line_offset;
7569
line_offset=line_offset<0?-(line_offset-1):-(line_offset+1);
7577
synctex_status_t synctex_display_query(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) {
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);
7583
return SYNCTEX_STATUS_ERROR;
7585
synctex_status_t synctex_edit_query(synctex_scanner_p scanner,int page,float h,float v) {
7587
synctex_iterator_free(scanner->iterator);
7588
scanner->iterator = synctex_iterator_new_edit(scanner, page, h, v);
7589
return synctex_iterator_count(scanner->iterator);
7591
return SYNCTEX_STATUS_ERROR;
7594
* The next result of a query.
7596
synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner) {
7597
return scanner? synctex_iterator_next_result(scanner->iterator): NULL;
7599
synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner) {
7600
return scanner? synctex_iterator_reset(scanner->iterator): SYNCTEX_STATUS_ERROR;
7603
synctex_node_p synctex_node_target(synctex_node_p node) {
7604
return _synctex_tree_target(node);
7607
# ifdef SYNCTEX_NOTHING
7609
# pragma mark Geometric utilities
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);
3641
#define SYNCTEX_MASK_LEFT 1
3642
#define SYNCTEX_MASK_RIGHT 2
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 */
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);
3666
if (NULL == sheet) {
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))) {
3677
if (_synctex_point_in_box(hitPoint,node,synctex_YES)) {
3678
/* Maybe the hitPoint belongs to a contained vertical box. */
3680
/* This trick is for catching overlapping boxes */
3681
if ((other_node = SYNCTEX_NEXT_hbox(node))) {
3683
if (_synctex_point_in_box(hitPoint,other_node,synctex_YES)) {
3684
node = _synctex_smallest_container(other_node,node);
3686
} while((other_node = SYNCTEX_NEXT_hbox(other_node)));
3688
/* node is the smallest horizontal box that contains hitPoint. */
3689
if ((bestContainer = _synctex_eq_deepest_container(hitPoint,node,synctex_YES))) {
3690
node = bestContainer;
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;
3702
((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.left;
3703
((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.right;
3705
SYNCTEX_END = SYNCTEX_START + 2*sizeof(synctex_node_t);
3707
return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
3709
return SYNCTEX_STATUS_ERROR;
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;
3716
bestNodes.right = NULL;
3717
} else if (bestNodes.right) {
3718
bestNodes.left = bestNodes.right;
3719
} else if (!bestNodes.left){
3720
bestNodes.left = node;
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);
3726
return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
3728
return SYNCTEX_STATUS_ERROR;
3730
} while ((node = SYNCTEX_NEXT_hbox(node)));
3731
/* All the horizontal boxes have been tested,
3732
* None of them contains the hit point.
3735
/* We are not lucky */
3736
if ((node = SYNCTEX_CHILD(sheet))) {
3742
# ifdef SYNCTEX_NOTHING
3744
# pragma mark Utilities
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
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};
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.
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 */
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 */
7653
nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */
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 */
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 */
7667
nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */
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 */
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 */
7682
nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */
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);
7692
min = _synctex_data_h(node);
7696
max = _synctex_data_h(node);
7700
/* positive kern: '.' means text, '>' means kern offset
7704
* negative kern: '.' means text, '<' means kern offset
7705
* ............................
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
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 */
7723
nd.distance = min - hit->h - 1; /* negative, the kern is to the left of the hit point */
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;
7733
case synctex_node_type_ref:
7734
nd.node = synctex_node_child(node);
7735
nd = _synctex_point_h_ordered_distance_v2(hit,nd.node);
7737
case synctex_node_type_proxy:
7738
case synctex_node_type_proxy_last:
7740
/* shift the hit point to be relative to the proxy origin,
7741
* then compute the distance to the target
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);
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) {
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.
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 */
3781
return 0; /* regions 2+5+8, inside the box, except for vertical coordinates */
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 */
3797
return 0; /* regions 2+5+8, inside the box, except for vertical coordinates */
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);
3807
min = SYNCTEX_HORIZ(node);
3811
max = SYNCTEX_HORIZ(node);
3815
/* positive kern: '.' means text, '>' means kern offset
3819
* negative kern: '.' means text, '<' means kern offset
3820
* ............................
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
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 */
3838
return min - hitPoint.h - 1; /* negative, the kern is to the left of the hitPoint */
3840
case synctex_node_type_glue:
3841
case synctex_node_type_math:
3842
return SYNCTEX_HORIZ(node) - hitPoint.h;
3845
return INT_MAX;/* We always assume that the node is faraway to the right*/
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.
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.
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 */
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 */
7794
nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */
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 */
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 */
7808
nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */
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 */
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 */
7825
nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */
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 */
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 */
7841
nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */
7844
case synctex_node_type_ref:
7845
nd.node = synctex_node_child(node);
7846
nd = _synctex_point_v_ordered_distance_v2(hit,nd.node);
7848
case synctex_node_type_proxy:
7849
case synctex_node_type_proxy_last:
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);
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)
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.
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 */
3885
return 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */
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 */
3901
return 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */
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;
3910
return INT_MAX;/* We always assume that the node is faraway to the top*/
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.
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);
7875
if (other_width<0) {
7876
other_width = -other_width;
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) {
7885
if (area>other_area) {
7888
if (_synctex_abs(_synctex_data_width(node))>_synctex_abs(_synctex_data_width(other_node))) {
7891
if (_synctex_abs(_synctex_data_width(node))<_synctex_abs(_synctex_data_width(other_node))) {
7894
if (total_height<other_total_height) {
7897
if (total_height>other_total_height) {
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)) {
3918
if (SYNCTEX_ABS_WIDTH(node)>SYNCTEX_ABS_WIDTH(other_node)) {
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) {
3926
if (height>other_height) {
7903
SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hit, synctex_node_p node) {
7905
if (0 == _synctex_point_h_ordered_distance_v2(hit,node).distance
7906
&& 0 == _synctex_point_v_ordered_distance_v2(hit,node).distance) {
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.
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;
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;
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. */
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;
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;
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;
7970
* The distance from the hit point to the node.
7972
static int _synctex_point_node_distance_v2(synctex_point_p hit, synctex_node_p node) {
7975
synctex_box_s box = {{0,0},{0,0}};
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);
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);
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:
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));
8045
static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hit, synctex_node_p node) {
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.
8055
if ((_synctex_point_in_box_v2(hit,child))) {
8056
synctex_node_p deep = _synctex_eq_deepest_container_v2(hit,child);
8058
/* One of the children contains the hit. */
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;
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};
8078
} while((child = __synctex_tree_sibling(child)));
8084
if (_synctex_point_in_box_v2(hit,node)) {
8091
static synctex_nd_s _synctex_eq_deepest_container_v3(synctex_point_p hit, synctex_node_p 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.
8100
synctex_nd_s deep = _synctex_eq_deepest_container_v3(hit, child);
8102
/* One of the children contains the hit-> */
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;
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};
8120
} while((child = synctex_node_sibling(child)));
8126
/* is the hit point inside the box? */
8127
if (_synctex_point_in_box_v2(hit,node)) {
8128
return (synctex_nd_s){node, 0};
8132
return SYNCTEX_ND_0;
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.
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;
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) {
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)))) {
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);
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) {
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)))) {
8180
} while((childd.node = synctex_node_sibling(childd.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) {
8186
if((nd = __synctex_closest_deep_child_v2(hitP,nds.l.node)).node) {
8187
nds.l.node = nd.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) {
8195
if((nd = __synctex_closest_deep_child_v2(hitP,nds.r.node)).node) {
8196
nds.r.node = nd.node;
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))) {
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) {
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)))) {
8225
} else if (nd.distance == 0) {
8226
/* hit point is inside node. */
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) {
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)))) {
8241
} while((nd.node = __synctex_tree_sibling(nd.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;
8247
if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) {
8248
nds.l.node = nd.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;
8256
if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) {
8257
nds.r.node = nd.node;
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))) {
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) {
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)))) {
8287
} else if (nd.distance == 0) {
8289
} else { /* here nd < 0 */
8290
nd.distance = -nd.distance;
8291
if (nds.l.distance > nd.distance) {
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)))) {
8302
} while((nd.node = synctex_node_sibling(nd.node)));
8304
if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) {
8305
nds.l.node = nd.node;
8307
if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) {
8308
nds.l.node = nd.node;
8312
if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) {
8313
nds.r.node = nd.node;
8315
if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) {
8316
nds.r.node = nd.node;
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.
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));
8340
#if SYNCTEX_DEBUG>500
8341
synctex_node_display(child);
8343
synctex_nd_s nd = SYNCTEX_ND_0;
8344
if (_synctex_node_is_box(child)) {
8345
nd = __synctex_closest_deep_child_v2(hitP,child);
8347
nd = (synctex_nd_s) {child, _synctex_point_node_distance_v2(hitP,child)};
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)
8353
printf("New best %i<=%i line %i\n",nd.distance,
8354
best.distance,SYNCTEX_LINEINDEX(nd.node));
8359
} while((child = synctex_node_sibling(child)));
8360
#if defined(SYNCTEX_DEBUG)
8362
printf("Found new best %i line %i\n",best.distance,SYNCTEX_LINEINDEX(best.node));
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.
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) {
8397
return SYNCTEX_ND_0;
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);
8406
return __synctex_eq_get_closest_children_in_vbox_v2(hitP,node);
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) {
3934
if (0 == _synctex_point_h_distance(hitPoint,node,visible)
3935
&& 0 == _synctex_point_v_distance(hitPoint,node,visible)) {
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)
3946
int result = INT_MAX; /* when the distance is meaning less (sheet, input...) */
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.
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;
3985
/* This is region 3. The distance to the box is the L1 distance PB. */
3986
result = minV - hitPoint.v + hitPoint.h - maxH;
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. */
3996
/* This is region 6. The distance to the box is the geometrical distance to the right edge. */
3997
result = hitPoint.h - maxH;
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;
4007
/* This is region 9. The distance to the box is the L1 distance PD. */
4008
result = hitPoint.v - maxV + hitPoint.h - maxH;
4012
case synctex_node_type_kern:
4013
maxH = SYNCTEX_WIDTH(node);
4015
minH = SYNCTEX_HORIZ(node);
4019
maxH = SYNCTEX_HORIZ(node);
4022
minV = SYNCTEX_VERT(node);
4023
if (hitPoint.h<minH) {
4024
if (hitPoint.v>minV) {
4025
result = hitPoint.v - minV + minH - hitPoint.h;
4027
result = minV - hitPoint.v + minH - hitPoint.h;
4029
} else if (hitPoint.h>maxH) {
4030
if (hitPoint.v>minV) {
4031
result = hitPoint.v - minV + hitPoint.h - maxH;
4033
result = minV - hitPoint.v + hitPoint.h - maxH;
4035
} else if (hitPoint.v>minV) {
4036
result = hitPoint.v - minV;
4038
result = minV - hitPoint.v;
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;
4049
result = minV - hitPoint.v + minH - hitPoint.h;
4051
} else if (hitPoint.v>minV) {
4052
result = hitPoint.v - minV + hitPoint.h - minH;
4054
result = minV - hitPoint.v + hitPoint.h - minH;
4062
static synctex_node_t _synctex_eq_deepest_container(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) {
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))) {
4072
if ((result = _synctex_eq_deepest_container(hitPoint,child,visible))) {
4075
} while((child = SYNCTEX_SIBLING(child)));
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;
4085
if (SYNCTEX_CHILD(child)) {
4086
int distance = _synctex_node_distance_to_point(hitPoint,child,visible);
4087
if (distance < bestDistance) {
4088
bestDistance = distance;
4092
} while((child = SYNCTEX_SIBLING(child)));
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) {
4106
if ((node = SYNCTEX_CHILD(node))) {
4108
int off7 = _synctex_point_h_distance(hitPoint,node,visible);
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;
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 */
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;
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;
4155
if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) {
4156
bestNodesRef->left = node;
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;
4164
if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) {
4165
bestNodesRef->right = node;
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) {
4174
if ((node = SYNCTEX_CHILD(node))) {
4176
int off7 = _synctex_point_v_distance(hitPoint,node,visible);/* this is what makes the difference with the h version above */
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;
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 */
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;
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;
4222
if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) {
4223
bestNodesRef->left = node;
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;
4231
if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) {
4232
bestNodesRef->right = node;
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) {
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);
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))) {
4255
int distance = _synctex_node_distance_to_point(hitPoint,node,visible);
4256
synctex_node_t candidate = NULL;
4257
if (distance<=*distanceRef) {
4258
*distanceRef = distance;
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;
4268
} while((node = SYNCTEX_SIBLING(node)));
4272
SYNCTEX_INLINE static synctex_node_t _synctex_eq_closest_child(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) {
4274
switch(node->class->type) {
4275
case synctex_node_type_hbox:
4276
case synctex_node_type_vbox:
4278
int best_distance = INT_MAX;
4279
synctex_node_t best_node = __synctex_eq_closest_child(hitPoint,node,&best_distance,visible);
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;
8414
4304
# ifdef SYNCTEX_NOTHING
8415
4305
# pragma mark -
8416
4306
# pragma mark Updater
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 */
8422
4311
# define SYNCTEX_BITS_PER_BYTE 8
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 */
4318
unsigned int no_gz:1; /* Whether zlib is used or not */
4319
unsigned int reserved:SYNCTEX_BITS_PER_BYTE*sizeof(int)-1; /* Align */
8437
__attribute__((__format__ (__printf__, 2, 3)))
8438
static int _synctex_updater_print(synctex_updater_p updater, const char * format, ...) {
8442
va_start(va, format);
8443
result = vfprintf(updater->file.as_FILE_p,
8450
#if defined(_MSC_VER)
8455
static int vasprintf(char **ret,
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);
8472
* gzvprintf is not available until OSX 10.10
8474
__attribute__((__format__ (__printf__, 2, 3)))
8475
static int _synctex_updater_print_gz(synctex_updater_p updater, const char * format, ...) {
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);
8492
static void _synctex_updater_close(synctex_updater_p updater) {
8494
fclose(updater->file.as_FILE_p);
8498
static void _synctex_updater_close_gz(synctex_updater_p updater) {
8500
gzclose(updater->file.as_gzFile);
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");
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) {
8519
_synctex_free(updater);
8520
return updater = NULL;
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))
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");
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)) {
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. */
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))) {
8531
_synctex_error("! synctex_updater_new_with_file: Can't append to %s",open.synctex);
8533
goto return_on_error;
8535
updater->print = &_synctex_updater_print;
8536
updater->close = &_synctex_updater_close;
8538
if (NULL == (updater->file.as_gzFile = gzopen(open.synctex,mode))) {
8539
goto no_write_error;
8541
updater->print = &_synctex_updater_print_gz;
8542
updater->close = &_synctex_updater_close_gz;
8544
printf("SyncTeX: updating %s...",open.synctex);
8545
_synctex_free(open.synctex);
8549
void synctex_updater_append_magnification(synctex_updater_p updater, char * magnification){
8550
if (NULL==updater) {
8553
if (magnification && strlen(magnification)) {
8555
updater->print(updater,"Magnification:%s\n",magnification);
8559
void synctex_updater_append_x_offset(synctex_updater_p updater, char * x_offset){
8560
if (NULL==updater) {
8563
if (x_offset && strlen(x_offset)) {
8564
updater->length += updater->print(updater,"X Offset:%s\n",x_offset);
8568
void synctex_updater_append_y_offset(synctex_updater_p updater, char * y_offset){
8569
if (NULL==updater) {
8572
if (y_offset && strlen(y_offset)) {
8573
updater->length += updater->print(updater,"Y Offset:%s\n",y_offset);
8577
void synctex_updater_free(synctex_updater_p updater){
8578
if (NULL==updater) {
8581
if (updater->length>0) {
8582
updater->print(updater,"!%i\n",updater->length);
8584
updater->close(updater);
8585
_synctex_free(updater);
8586
printf("... done.\n");
8591
#if defined(SYNCTEX_TESTING)
8592
# ifdef SYNCTEX_NOTHING
8594
# pragma mark Testers
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).
8603
static synctex_node_p _synctex_node_next(synctex_node_p node) {
8604
synctex_node_p N = _synctex_tree_child(node);
8608
return _synctex_node_sibling_or_parents(node);
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);
8616
int synctex_test_setup_scanner_sheets_421(synctex_scanner_p scanner) {
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;
8635
int synctex_test_input(synctex_scanner_p scanner) {
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");
8652
SYNCTEX_TEST_BODY(TC,
8653
0==memcmp(_synctex_data_name(input),
8657
synctex_node_free(input);
8660
int synctex_test_proxy(synctex_scanner_p scanner) {
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);
8673
int synctex_test_handle(synctex_scanner_p scanner) {
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);
8710
int synctex_test_setup_scanner_input(synctex_scanner_p scanner) {
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,"");
8723
int synctex_test_setup_nodes(synctex_scanner_p scanner, synctex_node_r nodes) {
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,"");
8732
int synctex_test_teardown_nodes(synctex_scanner_p scanner, synctex_node_r nodes) {
8734
for (n=0;n<synctex_node_number_of_types;++n) {
8735
synctex_node_free(nodes[n]);
8740
int synctex_test_tree(synctex_scanner_p scanner) {
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];
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]),"");
8756
synctex_test_teardown_nodes(scanner,nodes3);
8757
synctex_test_teardown_nodes(scanner,nodes2);
8758
synctex_test_teardown_nodes(scanner,nodes1);
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),"");
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;
8800
SYNCTEX_TEST_BODY(TC, (synctex_display_query(scanner,"21",21,4,-1)==3),"");
8806
char n[25]; /* name */
8807
} synctex_test_sn_s;
8809
synctex_test_sn_s synctex_test_tmp_sn(char * content) {
8810
synctex_test_sn_s sn = {0, "/tmp/test.XXXXXX.synctex"};
8812
int fd = mkstemps(sn.n,8);
8814
fprintf(stderr, "%s: %s\n", sn.n, strerror(errno));
8818
if ((sfp = fdopen(fd, "w+")) == NULL) {
8821
fprintf(stderr, "%s: %s\n", sn.n, strerror(errno));
8825
sn.s = fputs(content,sfp);
8826
printf("temp:%s\n%i\n",sn.n,sn.s);
8834
int synctex_test_sheet_1() {
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*/
8846
"[1,10:20,350:330,330,0 \n" /*60-89*/
8850
synctex_test_sn_s sn = synctex_test_tmp_sn(content);
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");
8856
printf("%s\n",_synctex_node_abstract(node));
8857
node = synctex_node_next(node);
8859
synctex_scanner_free(scanner);
8866
int synctex_test_sheet_2() {
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*/
8878
"(1,10:20,350:330,330,0 \n" /*60-89*/
8882
synctex_test_sn_s sn = synctex_test_tmp_sn(content);
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");
8888
printf("%s\n",_synctex_node_abstract(node));
8889
node = _synctex_node_next(node);
8891
TC += synctex_scanner_free(scanner);
8898
int synctex_test_charindex() {
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*/
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*/
8917
synctex_test_sn_s sn = synctex_test_tmp_sn(content);
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");
8923
printf("%s\n",_synctex_node_abstract(node));
8924
node = synctex_node_next(node);
8926
TC += synctex_scanner_free(scanner);
8933
int synctex_test_form() {
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*/
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*/
8951
"<1000 \n" /*70-79*/
8952
"(1,63:0,0:100,8,3 \n" /*80-99*/
8956
synctex_test_sn_s sn = synctex_test_tmp_sn(content);
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);
8961
printf("%s\n",_synctex_node_abstract(node));
8962
node = _synctex_node_next(node);
8964
TC += synctex_scanner_free(scanner);
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))) {
4353
_synctex_error("! synctex_updater_new_with_file: Can't append to %s",synctex);
4355
goto return_on_error;
4357
updater->fprintf = (synctex_fprintf_t)(&fprintf);
4359
if (NULL == (SYNCTEX_FILE = (void *)gzopen(synctex,mode))) {
4360
goto no_write_error;
4362
updater->fprintf = (synctex_fprintf_t)(&gzprintf);
4364
printf("SyncTeX: updating %s...",synctex);
4370
void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification){
4371
if (NULL==updater) {
4374
if (magnification && strlen(magnification)) {
4375
updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Magnification:%s\n",magnification);
4379
void synctex_updater_append_x_offset(synctex_updater_t updater, char * x_offset){
4380
if (NULL==updater) {
4383
if (x_offset && strlen(x_offset)) {
4384
updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"X Offset:%s\n",x_offset);
4388
void synctex_updater_append_y_offset(synctex_updater_t updater, char * y_offset){
4389
if (NULL==updater) {
4392
if (y_offset && strlen(y_offset)) {
4393
updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Y Offset:%s\n",y_offset);
4397
void synctex_updater_free(synctex_updater_t updater){
4398
if (NULL==updater) {
4401
if (updater->length>0) {
4402
SYNCTEX_fprintf(SYNCTEX_FILE,"!%i\n",updater->length);
4404
if (SYNCTEX_NO_GZ) {
4405
fclose((FILE *)SYNCTEX_FILE);
4407
gzclose((gzFile)SYNCTEX_FILE);
4410
printf("... done.\n");