]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/synctex/synctex_parser.c
397707659c29b7a6aaa1f3e5a7c44d558adb1d74
[evince.git] / cut-n-paste / synctex / synctex_parser.c
1 /* 
2 Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr
3
4 This file is part of the SyncTeX package.
5
6 Latest Revision: Fri Mar 11 07:39:12 UTC 2011
7
8 Version: 1.13
9
10 See synctex_parser_readme.txt for more details
11
12 License:
13 --------
14 Permission is hereby granted, free of charge, to any person
15 obtaining a copy of this software and associated documentation
16 files (the "Software"), to deal in the Software without
17 restriction, including without limitation the rights to use,
18 copy, modify, merge, publish, distribute, sublicense, and/or sell
19 copies of the Software, and to permit persons to whom the
20 Software is furnished to do so, subject to the following
21 conditions:
22
23 The above copyright notice and this permission notice shall be
24 included in all copies or substantial portions of the Software.
25
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
28 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
30 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
31 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
33 OTHER DEALINGS IN THE SOFTWARE
34
35 Except as contained in this notice, the name of the copyright holder  
36 shall not be used in advertising or otherwise to promote the sale,  
37 use or other dealings in this Software without prior written  
38 authorization from the copyright holder.
39
40 Acknowledgments:
41 ----------------
42 The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh,
43 and significant help from XeTeX developer Jonathan Kew
44
45 Nota Bene:
46 ----------
47 If you include or use a significant part of the synctex package into a software,
48 I would appreciate to be listed as contributor and see "SyncTeX" highlighted.
49
50 Version 1
51 Thu Jun 19 09:39:21 UTC 2008
52
53 */
54
55 /*  We assume that high level application like pdf viewers will want
56  *  to embed this code as is. We assume that they also have locale.h and setlocale.
57  *  For other tools such as TeXLive tools, you must define SYNCTEX_USE_LOCAL_HEADER,
58  *  when building. You also have to create and customize synctex_parser_local.h to fit your system.
59  *  In particular, the HAVE_LOCALE_H and HAVE_SETLOCALE macros should be properly defined.
60  *  With this design, you should not need to edit this file. */
61
62 #   if defined(SYNCTEX_USE_LOCAL_HEADER)
63 #       include "synctex_parser_local.h"
64 #   else
65 #       define HAVE_LOCALE_H 1
66 #       define HAVE_SETLOCALE 1
67 #       if defined(_MSC_VER) 
68 #          define SYNCTEX_INLINE __inline
69 #       else
70 #          define SYNCTEX_INLINE inline
71 #       endif
72 #   endif
73
74 #include <stdlib.h>
75 #include <stdio.h>
76 #include <string.h>
77 #include <errno.h>
78 #include <limits.h>
79
80 #if defined(HAVE_LOCALE_H)
81 #include <locale.h>
82 #endif
83
84 /*  The data is organized in a graph with multiple entries.
85  *  The root object is a scanner, it is created with the contents on a synctex file.
86  *  Each leaf of the tree is a synctex_node_t object.
87  *  There are 3 subtrees, two of them sharing the same leaves.
88  *  The first tree is the list of input records, where input file names are associated with tags.
89  *  The second tree is the box tree as given by TeX when shipping pages out.
90  *  First level objects are sheets, containing boxes, glues, kerns...
91  *  The third tree allows to browse leaves according to tag and line.
92  */
93
94 #include "synctex_parser.h"
95 #include "synctex_parser_utils.h"
96
97 /*  These are the possible extensions of the synctex file */
98 const char * synctex_suffix = ".synctex";
99 const char * synctex_suffix_gz = ".gz";
100
101 /*  each synctex node has a class */
102 typedef struct __synctex_class_t _synctex_class_t;
103 typedef _synctex_class_t * synctex_class_t;
104
105
106 /*  synctex_node_t is a pointer to a node
107  *  _synctex_node is the target of the synctex_node_t pointer
108  *  It is a pseudo object oriented program.
109  *  class is a pointer to the class object the node belongs to.
110  *  implementation is meant to contain the private data of the node
111  *  basically, there are 2 kinds of information: navigation information and
112  *  synctex information. Both will depend on the type of the node,
113  *  thus different nodes will have different private data.
114  *  There is no inheritancy overhead.
115  */
116 typedef union _synctex_info_t {
117         int    INT;
118         char * PTR;
119 } synctex_info_t;
120
121 struct _synctex_node {
122         synctex_class_t class;
123         synctex_info_t * implementation;
124 };
125
126 /*  Each node of the tree, except the scanner itself belongs to a class.
127  *  The class object is just a struct declaring the owning scanner
128  *  This is a pointer to the scanner as root of the tree.
129  *  The type is used to identify the kind of node.
130  *  The class declares pointers to a creator and a destructor method.
131  *  The log and display fields are used to log and display the node.
132  *  display will also display the child, sibling and parent sibling.
133  *  parent, child and sibling are used to navigate the tree,
134  *  from TeX box hierarchy point of view.
135  *  The friend field points to a method which allows to navigate from friend to friend.
136  *  A friend is a node with very close tag and line numbers.
137  *  Finally, the info field point to a method giving the private node info offset.
138  */
139
140 typedef synctex_node_t *(*_synctex_node_getter_t)(synctex_node_t);
141 typedef synctex_info_t *(*_synctex_info_getter_t)(synctex_node_t);
142
143 struct __synctex_class_t {
144         synctex_scanner_t scanner;
145         int type;
146         synctex_node_t (*new)(synctex_scanner_t scanner);
147         void (*free)(synctex_node_t);
148         void (*log)(synctex_node_t);
149         void (*display)(synctex_node_t);
150         _synctex_node_getter_t parent;
151         _synctex_node_getter_t child;
152         _synctex_node_getter_t sibling;
153         _synctex_node_getter_t friend;
154         _synctex_node_getter_t next_box;
155         _synctex_info_getter_t info;
156 };
157
158 #       ifdef SYNCTEX_NOTHING
159 #       pragma mark -
160 #       pragma mark Abstract OBJECTS and METHODS
161 #   endif
162
163 /*  These macros are shortcuts
164  *  This macro checks if a message can be sent.
165  */
166 #   define SYNCTEX_CAN_PERFORM(NODE,SELECTOR)\
167                 (NULL!=((((NODE)->class))->SELECTOR))
168
169 /*  This macro is some kind of objc_msg_send.
170  *  It takes care of sending the proper message if possible.
171  */
172 #   define SYNCTEX_MSG_SEND(NODE,SELECTOR) if (NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR)) {\
173                 (*((((NODE)->class))->SELECTOR))(NODE);\
174         }
175
176 /*  read only safe getter
177  */
178 #   define SYNCTEX_GET(NODE,SELECTOR)((NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR))?SYNCTEX_GETTER(NODE,SELECTOR)[0]:(NULL))
179
180 /*  read/write getter
181  */
182 #   define SYNCTEX_GETTER(NODE,SELECTOR)\
183                 ((synctex_node_t *)((*((((NODE)->class))->SELECTOR))(NODE)))
184
185 #   define SYNCTEX_FREE(NODE) SYNCTEX_MSG_SEND(NODE,free);
186
187 /*  Parent getter and setter
188  */
189 #   define SYNCTEX_PARENT(NODE) SYNCTEX_GET(NODE,parent)
190 #   define SYNCTEX_SET_PARENT(NODE,NEW_PARENT) if (NODE && NEW_PARENT && SYNCTEX_CAN_PERFORM(NODE,parent)){\
191                 SYNCTEX_GETTER(NODE,parent)[0]=NEW_PARENT;\
192         }
193
194 /*  Child getter and setter
195  */
196 #   define SYNCTEX_CHILD(NODE) SYNCTEX_GET(NODE,child)
197 #   define SYNCTEX_SET_CHILD(NODE,NEW_CHILD) if (NODE && NEW_CHILD){\
198                 SYNCTEX_GETTER(NODE,child)[0]=NEW_CHILD;\
199                 SYNCTEX_GETTER(NEW_CHILD,parent)[0]=NODE;\
200         }
201
202 /*  Sibling getter and setter
203  */
204 #   define SYNCTEX_SIBLING(NODE) SYNCTEX_GET(NODE,sibling)
205 #   define SYNCTEX_SET_SIBLING(NODE,NEW_SIBLING) if (NODE && NEW_SIBLING) {\
206                 SYNCTEX_GETTER(NODE,sibling)[0]=NEW_SIBLING;\
207                 if (SYNCTEX_CAN_PERFORM(NEW_SIBLING,parent) && SYNCTEX_CAN_PERFORM(NODE,parent)) {\
208                         SYNCTEX_GETTER(NEW_SIBLING,parent)[0]=SYNCTEX_GETTER(NODE,parent)[0];\
209                 }\
210         }
211 /*  Friend getter and setter. A friend is a kern, math, glue or void box node which tag and line numbers are similar.
212  *  This is a first filter on the nodes that avoids testing all of them.
213  *  Friends are used mainly in forward synchronization aka from source to output.
214  */
215 #   define SYNCTEX_FRIEND(NODE) SYNCTEX_GET(NODE,friend)
216 #   define SYNCTEX_SET_FRIEND(NODE,NEW_FRIEND) if (NODE && NEW_FRIEND){\
217                 SYNCTEX_GETTER(NODE,friend)[0]=NEW_FRIEND;\
218         }
219
220 /*  Next box getter and setter. The box tree can be traversed from one horizontal box to the other.
221  *  Navigation starts with the deeper boxes.
222  */
223 #   define SYNCTEX_NEXT_HORIZ_BOX(NODE) SYNCTEX_GET(NODE,next_box)
224 #   define SYNCTEX_SET_NEXT_HORIZ_BOX(NODE,NEXT_BOX) if (NODE && NEXT_BOX){\
225                 SYNCTEX_GETTER(NODE,next_box)[0]=NEXT_BOX;\
226         }
227
228 void _synctex_free_node(synctex_node_t node);
229 void _synctex_free_leaf(synctex_node_t node);
230
231 /*  A node is meant to own its child and sibling.
232  *  It is not owned by its parent, unless it is its first child.
233  *  This destructor is for all nodes with children.
234  */
235 void _synctex_free_node(synctex_node_t node) {
236         if (node) {
237                 (*((node->class)->sibling))(node);
238                 SYNCTEX_FREE(SYNCTEX_SIBLING(node));
239                 SYNCTEX_FREE(SYNCTEX_CHILD(node));
240                 free(node);
241         }
242         return;
243 }
244
245 /*  A node is meant to own its child and sibling.
246  *  It is not owned by its parent, unless it is its first child.
247  *  This destructor is for nodes with no child.
248  */
249 void _synctex_free_leaf(synctex_node_t node) {
250         if (node) {
251                 SYNCTEX_FREE(SYNCTEX_SIBLING(node));
252                 free(node);
253         }
254         return;
255 }
256 #       ifdef   __SYNCTEX_WORK__
257 #               include "/usr/include/zlib.h"
258 #       else
259 #               include <zlib.h>
260 #       endif
261
262 /*  The synctex scanner is the root object.
263  *  Is is initialized with the contents of a text file or a gzipped file.
264  *  The buffer_? are first used to parse the text.
265  */
266 struct __synctex_scanner_t {
267         gzFile file;                  /*  The (possibly compressed) file */
268         char * buffer_cur;            /*  current location in the buffer */
269         char * buffer_start;          /*  start of the buffer */
270         char * buffer_end;            /*  end of the buffer */
271         char * output_fmt;            /*  dvi or pdf, not yet used */
272         char * output;                /*  the output name used to create the scanner */
273         char * synctex;               /*  the .synctex or .synctex.gz name used to create the scanner */
274         int version;                  /*  1, not yet used */
275         struct {
276                 unsigned has_parsed:1;          /*  Whether the scanner has parsed its underlying synctex file. */
277                 unsigned reserved:sizeof(unsigned)-1;   /*  alignment */
278         } flags;
279         int pre_magnification;        /*  magnification from the synctex preamble */
280         int pre_unit;                 /*  unit from the synctex preamble */
281         int pre_x_offset;             /*  X offste from the synctex preamble */
282         int pre_y_offset;             /*  Y offset from the synctex preamble */
283         int count;                    /*  Number of records, from the synctex postamble */
284         float unit;                   /*  real unit, from synctex preamble or post scriptum */
285         float x_offset;               /*  X offset, from synctex preamble or post scriptum */
286         float y_offset;               /*  Y Offset, from synctex preamble or post scriptum */
287         synctex_node_t sheet;         /*  The first sheet node, its siblings are the other sheet nodes */
288         synctex_node_t input;         /*  The first input node, its siblings are the other input nodes */
289         int number_of_lists;          /*  The number of friend lists */
290         synctex_node_t * lists_of_friends;/*  The friend lists */
291         _synctex_class_t class[synctex_node_number_of_types]; /*  The classes of the nodes of the scanner */
292 };
293
294 /*  SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts
295  */
296 #   define SYNCTEX_CUR (scanner->buffer_cur)
297 #   define SYNCTEX_START (scanner->buffer_start)
298 #   define SYNCTEX_END (scanner->buffer_end)
299
300 #       ifdef SYNCTEX_NOTHING
301 #       pragma mark -
302 #       pragma mark OBJECTS, their creators and destructors.
303 #   endif
304
305 /*  Here, we define the indices for the different informations.
306  *  They are used to declare the size of the implementation.
307  *  For example, if one object uses SYNCTEX_HORIZ_IDX is its size,
308  *  then its info will contain a tag, line, column, horiz but no width nor height nor depth
309  */
310
311 /*  The sheet is a first level node.
312  *  It has no parent (the parent is the scanner itself)
313  *  Its sibling points to another sheet.
314  *  Its child points to its first child, in general a box.
315  *  A sheet node contains only one synctex information: the page.
316  *  This is the 1 based page index as given by TeX.
317  */
318 /*  The next macros are used to access the node info
319  *  SYNCTEX_INFO(node) points to the first synctex integer or pointer data of node
320  *  SYNCTEX_INFO(node)[index] is the information at index
321  *  for example, the page of a sheet is stored in SYNCTEX_INFO(sheet)[SYNCTEX_PAGE_IDX]
322  */
323 #   define SYNCTEX_INFO(NODE) ((*((((NODE)->class))->info))(NODE))
324 #   define SYNCTEX_PAGE_IDX 0
325 #   define SYNCTEX_PAGE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_PAGE_IDX].INT
326
327 /*  This macro defines implementation offsets
328  *  It is only used for pointer values
329  */
330 #   define SYNCTEX_MAKE_GET(SYNCTEX_GETTER,OFFSET)\
331 synctex_node_t * SYNCTEX_GETTER (synctex_node_t node);\
332 synctex_node_t * SYNCTEX_GETTER (synctex_node_t node) {\
333         return node?(synctex_node_t *)((&((node)->implementation))+OFFSET):NULL;\
334 }
335 SYNCTEX_MAKE_GET(_synctex_implementation_0,0)
336 SYNCTEX_MAKE_GET(_synctex_implementation_1,1)
337 SYNCTEX_MAKE_GET(_synctex_implementation_2,2)
338 SYNCTEX_MAKE_GET(_synctex_implementation_3,3)
339 SYNCTEX_MAKE_GET(_synctex_implementation_4,4)
340 SYNCTEX_MAKE_GET(_synctex_implementation_5,5)
341
342 typedef struct {
343         synctex_class_t class;
344         synctex_info_t implementation[3+SYNCTEX_PAGE_IDX+1];/*  child, sibling, next box,
345                                  *  SYNCTEX_PAGE_IDX */
346 } synctex_sheet_t;
347
348 synctex_node_t _synctex_new_sheet(synctex_scanner_t scanner);
349 void _synctex_display_sheet(synctex_node_t sheet);
350 void _synctex_log_sheet(synctex_node_t sheet);
351
352 static _synctex_class_t synctex_class_sheet = {
353         NULL,                       /*  No scanner yet */
354         synctex_node_type_sheet,    /*  Node type */
355         &_synctex_new_sheet,        /*  creator */
356         &_synctex_free_node,        /*  destructor */
357         &_synctex_log_sheet,        /*  log */
358         &_synctex_display_sheet,    /*  display */
359         NULL,                       /*  No parent */
360         &_synctex_implementation_0, /*  child */
361         &_synctex_implementation_1, /*  sibling */
362         NULL,                       /*  No friend */
363         &_synctex_implementation_2, /*  Next box */
364         (_synctex_info_getter_t)&_synctex_implementation_3  /*  info */
365 };
366
367 /*  sheet node creator */
368 synctex_node_t _synctex_new_sheet(synctex_scanner_t scanner) {
369         synctex_node_t node = _synctex_malloc(sizeof(synctex_sheet_t));
370         if (node) {
371                 node->class = scanner?scanner->class+synctex_node_type_sheet:(synctex_class_t)&synctex_class_sheet;
372         }
373         return node;
374 }
375
376 /*  A box node contains navigation and synctex information
377  *  There are different kind of boxes.
378  *  Only horizontal boxes are treated differently because of their visible size.
379  */
380 #   define SYNCTEX_TAG_IDX 0
381 #   define SYNCTEX_LINE_IDX (SYNCTEX_TAG_IDX+1)
382 #   define SYNCTEX_COLUMN_IDX (SYNCTEX_LINE_IDX+1)
383 #   define SYNCTEX_HORIZ_IDX (SYNCTEX_COLUMN_IDX+1)
384 #   define SYNCTEX_VERT_IDX (SYNCTEX_HORIZ_IDX+1)
385 #   define SYNCTEX_WIDTH_IDX (SYNCTEX_VERT_IDX+1)
386 #   define SYNCTEX_HEIGHT_IDX (SYNCTEX_WIDTH_IDX+1)
387 #   define SYNCTEX_DEPTH_IDX (SYNCTEX_HEIGHT_IDX+1)
388 /*  the corresponding info accessors */
389 #   define SYNCTEX_TAG(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_TAG_IDX].INT
390 #   define SYNCTEX_LINE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_LINE_IDX].INT
391 #   define SYNCTEX_COLUMN(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_COLUMN_IDX].INT
392 #   define SYNCTEX_HORIZ(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HORIZ_IDX].INT
393 #   define SYNCTEX_VERT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_VERT_IDX].INT
394 #   define SYNCTEX_WIDTH(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_WIDTH_IDX].INT
395 #   define SYNCTEX_HEIGHT(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HEIGHT_IDX].INT
396 #   define SYNCTEX_DEPTH(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_DEPTH_IDX].INT
397 #   define SYNCTEX_ABS_WIDTH(NODE) ((SYNCTEX_WIDTH(NODE)>0?SYNCTEX_WIDTH(NODE):-SYNCTEX_WIDTH(NODE)))
398 #   define SYNCTEX_ABS_HEIGHT(NODE) ((SYNCTEX_HEIGHT(NODE)>0?SYNCTEX_HEIGHT(NODE):-SYNCTEX_HEIGHT(NODE)))
399 #   define SYNCTEX_ABS_DEPTH(NODE) ((SYNCTEX_DEPTH(NODE)>0?SYNCTEX_DEPTH(NODE):-SYNCTEX_DEPTH(NODE)))
400
401 typedef struct {
402         synctex_class_t class;
403         synctex_info_t implementation[5+SYNCTEX_DEPTH_IDX+1]; /*  parent,child,sibling,friend,next box,
404                                                         *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
405                                                                 *  SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH */
406 } synctex_vert_box_node_t;
407
408 synctex_node_t _synctex_new_vbox(synctex_scanner_t scanner);
409 void _synctex_log_box(synctex_node_t sheet);
410 void _synctex_display_vbox(synctex_node_t node);
411
412 /*  These are static class objects, each scanner will make a copy of them and setup the scanner field.
413  */
414 static _synctex_class_t synctex_class_vbox = {
415         NULL,                       /*  No scanner yet */
416         synctex_node_type_vbox,     /*  Node type */
417         &_synctex_new_vbox,         /*  creator */
418         &_synctex_free_node,        /*  destructor */
419         &_synctex_log_box,          /*  log */
420         &_synctex_display_vbox,     /*  display */
421         &_synctex_implementation_0, /*  parent */
422         &_synctex_implementation_1, /*  child */
423         &_synctex_implementation_2, /*  sibling */
424         &_synctex_implementation_3, /*  friend */
425         &_synctex_implementation_4, /*  next box */
426         (_synctex_info_getter_t)&_synctex_implementation_5
427 };
428
429 /*  vertical box node creator */
430 synctex_node_t _synctex_new_vbox(synctex_scanner_t scanner) {
431         synctex_node_t node = _synctex_malloc(sizeof(synctex_vert_box_node_t));
432         if (node) {
433                 node->class = scanner?scanner->class+synctex_node_type_vbox:(synctex_class_t)&synctex_class_vbox;
434         }
435         return node;
436 }
437
438 #   define SYNCTEX_HORIZ_V_IDX (SYNCTEX_DEPTH_IDX+1)
439 #   define SYNCTEX_VERT_V_IDX (SYNCTEX_HORIZ_V_IDX+1)
440 #   define SYNCTEX_WIDTH_V_IDX (SYNCTEX_VERT_V_IDX+1)
441 #   define SYNCTEX_HEIGHT_V_IDX (SYNCTEX_WIDTH_V_IDX+1)
442 #   define SYNCTEX_DEPTH_V_IDX (SYNCTEX_HEIGHT_V_IDX+1)
443 /*  the corresponding info accessors */
444 #   define SYNCTEX_HORIZ_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HORIZ_V_IDX].INT
445 #   define SYNCTEX_VERT_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_VERT_V_IDX].INT
446 #   define SYNCTEX_WIDTH_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_WIDTH_V_IDX].INT
447 #   define SYNCTEX_HEIGHT_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_HEIGHT_V_IDX].INT
448 #   define SYNCTEX_DEPTH_V(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_DEPTH_V_IDX].INT
449 #   define SYNCTEX_ABS_WIDTH_V(NODE) ((SYNCTEX_WIDTH_V(NODE)>0?SYNCTEX_WIDTH_V(NODE):-SYNCTEX_WIDTH_V(NODE)))
450 #   define SYNCTEX_ABS_HEIGHT_V(NODE) ((SYNCTEX_HEIGHT_V(NODE)>0?SYNCTEX_HEIGHT_V(NODE):-SYNCTEX_HEIGHT_V(NODE)))
451 #   define SYNCTEX_ABS_DEPTH_V(NODE) ((SYNCTEX_DEPTH_V(NODE)>0?SYNCTEX_DEPTH_V(NODE):-SYNCTEX_DEPTH_V(NODE)))
452
453 /*  Horizontal boxes must contain visible size, because 0 width does not mean emptiness */
454 typedef struct {
455         synctex_class_t class;
456         synctex_info_t implementation[5+SYNCTEX_DEPTH_V_IDX+1]; /*parent,child,sibling,friend,next box,
457                                                 *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
458                                                 *  SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH,
459                                                 *  SYNCTEX_HORIZ_V,SYNCTEX_VERT_V,SYNCTEX_WIDTH_V,SYNCTEX_HEIGHT_V,SYNCTEX_DEPTH_V*/
460 } synctex_horiz_box_node_t;
461
462 synctex_node_t _synctex_new_hbox(synctex_scanner_t scanner);
463 void _synctex_display_hbox(synctex_node_t node);
464 void _synctex_log_horiz_box(synctex_node_t sheet);
465
466
467 static _synctex_class_t synctex_class_hbox = {
468         NULL,                       /*  No scanner yet */
469         synctex_node_type_hbox,     /*  Node type */
470         &_synctex_new_hbox,         /*  creator */
471         &_synctex_free_node,        /*  destructor */
472         &_synctex_log_horiz_box,    /*  log */
473         &_synctex_display_hbox,     /*  display */
474         &_synctex_implementation_0, /*  parent */
475         &_synctex_implementation_1, /*  child */
476         &_synctex_implementation_2, /*  sibling */
477         &_synctex_implementation_3, /*  friend */
478         &_synctex_implementation_4, /*  next box */
479         (_synctex_info_getter_t)&_synctex_implementation_5
480 };
481
482 /*  horizontal box node creator */
483 synctex_node_t _synctex_new_hbox(synctex_scanner_t scanner) {
484         synctex_node_t node = _synctex_malloc(sizeof(synctex_horiz_box_node_t));
485         if (node) {
486                 node->class = scanner?scanner->class+synctex_node_type_hbox:(synctex_class_t)&synctex_class_hbox;
487         }
488         return node;
489 }
490
491 /*  This void box node implementation is either horizontal or vertical
492  *  It does not contain a child field.
493  */
494 typedef struct {
495         synctex_class_t class;
496         synctex_info_t implementation[3+SYNCTEX_DEPTH_IDX+1]; /*  parent,sibling,friend,
497                           *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
498                                           *  SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH,SYNCTEX_HEIGHT,SYNCTEX_DEPTH*/
499 } synctex_void_box_node_t;
500
501 synctex_node_t _synctex_new_void_vbox(synctex_scanner_t scanner);
502 void _synctex_log_void_box(synctex_node_t sheet);
503 void _synctex_display_void_vbox(synctex_node_t node);
504
505 static _synctex_class_t synctex_class_void_vbox = {
506         NULL,                       /*  No scanner yet */
507         synctex_node_type_void_vbox,/*  Node type */
508         &_synctex_new_void_vbox,    /*  creator */
509         &_synctex_free_node,        /*  destructor */
510         &_synctex_log_void_box,     /*  log */
511         &_synctex_display_void_vbox,/*  display */
512         &_synctex_implementation_0, /*  parent */
513         NULL,                       /*  No child */
514         &_synctex_implementation_1, /*  sibling */
515         &_synctex_implementation_2, /*  friend */
516         NULL,                                           /*  No next box */
517         (_synctex_info_getter_t)&_synctex_implementation_3
518 };
519
520 /*  vertical void box node creator */
521 synctex_node_t _synctex_new_void_vbox(synctex_scanner_t scanner) {
522         synctex_node_t node = _synctex_malloc(sizeof(synctex_void_box_node_t));
523         if (node) {
524                 node->class = scanner?scanner->class+synctex_node_type_void_vbox:(synctex_class_t)&synctex_class_void_vbox;
525         }
526         return node;
527 }
528
529 synctex_node_t _synctex_new_void_hbox(synctex_scanner_t scanner);
530 void _synctex_display_void_hbox(synctex_node_t node);
531
532 static _synctex_class_t synctex_class_void_hbox = {
533         NULL,                       /*  No scanner yet */
534         synctex_node_type_void_hbox,/*  Node type */
535         &_synctex_new_void_hbox,    /*  creator */
536         &_synctex_free_node,        /*  destructor */
537         &_synctex_log_void_box,     /*  log */
538         &_synctex_display_void_hbox,/*  display */
539         &_synctex_implementation_0, /*  parent */
540         NULL,                       /*  No child */
541         &_synctex_implementation_1, /*  sibling */
542         &_synctex_implementation_2, /*  friend */
543         NULL,                                           /*  No next box */
544         (_synctex_info_getter_t)&_synctex_implementation_3
545 };
546
547 /*  horizontal void box node creator */
548 synctex_node_t _synctex_new_void_hbox(synctex_scanner_t scanner) {
549         synctex_node_t node = _synctex_malloc(sizeof(synctex_void_box_node_t));
550         if (node) {
551                 node->class = scanner?scanner->class+synctex_node_type_void_hbox:(synctex_class_t)&synctex_class_void_hbox;
552         }
553         return node;
554 }
555
556 /*  The medium nodes correspond to kern, glue, penalty and math nodes.  */
557 typedef struct {
558         synctex_class_t class;
559         synctex_info_t implementation[3+SYNCTEX_WIDTH_IDX+1]; /*  parent,sibling,friend,
560                           *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
561                                           *  SYNCTEX_HORIZ,SYNCTEX_VERT,SYNCTEX_WIDTH */
562 } synctex_medium_node_t;
563
564 #define SYNCTEX_IS_BOX(NODE)\
565         ((NODE->class->type == synctex_node_type_vbox)\
566         || (NODE->class->type == synctex_node_type_void_vbox)\
567         || (NODE->class->type == synctex_node_type_hbox)\
568         || (NODE->class->type == synctex_node_type_void_hbox))
569         
570 #define SYNCTEX_HAS_CHILDREN(NODE) (NODE && SYNCTEX_CHILD(NODE))
571         
572 void _synctex_log_medium_node(synctex_node_t node);
573
574 /*  math node creator */
575 synctex_node_t _synctex_new_math(synctex_scanner_t scanner);
576 void _synctex_display_math(synctex_node_t node);
577
578 static _synctex_class_t synctex_class_math = {
579         NULL,                       /*  No scanner yet */
580         synctex_node_type_math,     /*  Node type */
581         &_synctex_new_math,         /*  creator */
582         &_synctex_free_leaf,        /*  destructor */
583         &_synctex_log_medium_node,  /*  log */
584         &_synctex_display_math,     /*  display */
585         &_synctex_implementation_0, /*  parent */
586         NULL,                       /*  No child */
587         &_synctex_implementation_1, /*  sibling */
588         &_synctex_implementation_2, /*  friend */
589         NULL,                       /*  No next box */
590         (_synctex_info_getter_t)&_synctex_implementation_3
591 };
592
593 synctex_node_t _synctex_new_math(synctex_scanner_t scanner) {
594         synctex_node_t node = _synctex_malloc(sizeof(synctex_medium_node_t));
595         if (node) {
596                 node->class = scanner?scanner->class+synctex_node_type_math:(synctex_class_t)&synctex_class_math;
597         }
598         return node;
599 }
600
601 /*  kern node creator */
602 synctex_node_t _synctex_new_kern(synctex_scanner_t scanner);
603 void _synctex_display_kern(synctex_node_t node);
604
605 static _synctex_class_t synctex_class_kern = {
606         NULL,                       /*  No scanner yet */
607         synctex_node_type_kern,     /*  Node type */
608         &_synctex_new_kern,         /*  creator */
609         &_synctex_free_leaf,        /*  destructor */
610         &_synctex_log_medium_node,  /*  log */
611         &_synctex_display_kern,     /*  display */
612         &_synctex_implementation_0, /*  parent */
613         NULL,                       /*  No child */
614         &_synctex_implementation_1, /*  sibling */
615         &_synctex_implementation_2, /*  friend */
616         NULL,                       /*  No next box */
617         (_synctex_info_getter_t)&_synctex_implementation_3
618 };
619
620 synctex_node_t _synctex_new_kern(synctex_scanner_t scanner) {
621         synctex_node_t node = _synctex_malloc(sizeof(synctex_medium_node_t));
622         if (node) {
623                 node->class = scanner?scanner->class+synctex_node_type_kern:(synctex_class_t)&synctex_class_kern;
624         }
625         return node;
626 }
627
628 /*  The small nodes correspond to glue and boundary nodes.  */
629 typedef struct {
630         synctex_class_t class;
631         synctex_info_t implementation[3+SYNCTEX_VERT_IDX+1]; /*  parent,sibling,friend,
632                           *  SYNCTEX_TAG,SYNCTEX_LINE,SYNCTEX_COLUMN,
633                                           *  SYNCTEX_HORIZ,SYNCTEX_VERT */
634 } synctex_small_node_t;
635
636 void _synctex_log_small_node(synctex_node_t node);
637 /*  glue node creator */
638 synctex_node_t _synctex_new_glue(synctex_scanner_t scanner);
639 void _synctex_display_glue(synctex_node_t node);
640
641 static _synctex_class_t synctex_class_glue = {
642         NULL,                       /*  No scanner yet */
643         synctex_node_type_glue,     /*  Node type */
644         &_synctex_new_glue,         /*  creator */
645         &_synctex_free_leaf,        /*  destructor */
646         &_synctex_log_medium_node,  /*  log */
647         &_synctex_display_glue,     /*  display */
648         &_synctex_implementation_0, /*  parent */
649         NULL,                       /*  No child */
650         &_synctex_implementation_1, /*  sibling */
651         &_synctex_implementation_2, /*  friend */
652         NULL,                       /*  No next box */
653         (_synctex_info_getter_t)&_synctex_implementation_3
654 };
655 synctex_node_t _synctex_new_glue(synctex_scanner_t scanner) {
656         synctex_node_t node = _synctex_malloc(sizeof(synctex_medium_node_t));
657         if (node) {
658                 node->class = scanner?scanner->class+synctex_node_type_glue:(synctex_class_t)&synctex_class_glue;
659         }
660         return node;
661 }
662
663 /*  boundary node creator */
664 synctex_node_t _synctex_new_boundary(synctex_scanner_t scanner);
665 void _synctex_display_boundary(synctex_node_t node);
666
667 static _synctex_class_t synctex_class_boundary = {
668         NULL,                       /*  No scanner yet */
669         synctex_node_type_boundary,     /*  Node type */
670         &_synctex_new_boundary, /*  creator */
671         &_synctex_free_leaf,        /*  destructor */
672         &_synctex_log_small_node,   /*  log */
673         &_synctex_display_boundary,     /*  display */
674         &_synctex_implementation_0, /*  parent */
675         NULL,                       /*  No child */
676         &_synctex_implementation_1, /*  sibling */
677         &_synctex_implementation_2, /*  friend */
678         NULL,                       /*  No next box */
679         (_synctex_info_getter_t)&_synctex_implementation_3
680 };
681
682 synctex_node_t _synctex_new_boundary(synctex_scanner_t scanner) {
683         synctex_node_t node = _synctex_malloc(sizeof(synctex_small_node_t));
684         if (node) {
685                 node->class = scanner?scanner->class+synctex_node_type_boundary:(synctex_class_t)&synctex_class_boundary;
686         }
687         return node;
688 }
689
690 #   define SYNCTEX_NAME_IDX (SYNCTEX_TAG_IDX+1)
691 #   define SYNCTEX_NAME(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_NAME_IDX].PTR
692
693 /*  Input nodes only know about their sibling, which is another input node.
694  *  The synctex information is the SYNCTEX_TAG and SYNCTEX_NAME*/
695 typedef struct {
696         synctex_class_t class;
697         synctex_info_t implementation[1+SYNCTEX_NAME_IDX+1]; /*  sibling,
698                                   *  SYNCTEX_TAG,SYNCTEX_NAME */
699 } synctex_input_t;
700
701 synctex_node_t _synctex_new_input(synctex_scanner_t scanner);
702 void _synctex_free_input(synctex_node_t node);
703 void _synctex_display_input(synctex_node_t node);
704 void _synctex_log_input(synctex_node_t sheet);
705
706 static _synctex_class_t synctex_class_input = {
707         NULL,                       /*  No scanner yet */
708         synctex_node_type_input,    /*  Node type */
709         &_synctex_new_input,        /*  creator */
710         &_synctex_free_input,       /*  destructor */
711         &_synctex_log_input,        /*  log */
712         &_synctex_display_input,    /*  display */
713         NULL,                       /*  No parent */
714         NULL,                       /*  No child */
715         &_synctex_implementation_0, /*  sibling */
716         NULL,                       /*  No friend */
717         NULL,                       /*  No next box */
718         (_synctex_info_getter_t)&_synctex_implementation_1
719 };
720
721 synctex_node_t _synctex_new_input(synctex_scanner_t scanner) {
722         synctex_node_t node = _synctex_malloc(sizeof(synctex_input_t));
723         if (node) {
724                 node->class = scanner?scanner->class+synctex_node_type_input:(synctex_class_t)&synctex_class_input;
725         }
726         return node;
727 }
728 void _synctex_free_input(synctex_node_t node){
729         if (node) {
730                 SYNCTEX_FREE(SYNCTEX_SIBLING(node));
731                 free(SYNCTEX_NAME(node));
732                 free(node);
733         }
734 }
735 #       ifdef SYNCTEX_NOTHING
736 #       pragma mark -
737 #       pragma mark Navigation
738 #   endif
739 synctex_node_t synctex_node_parent(synctex_node_t node)
740 {
741         return SYNCTEX_PARENT(node);
742 }
743 synctex_node_t synctex_node_sheet(synctex_node_t node)
744 {
745         while(node && node->class->type != synctex_node_type_sheet) {
746                 node = SYNCTEX_PARENT(node);
747         }
748         /*  exit the while loop either when node is NULL or node is a sheet */
749         return node;
750 }
751 synctex_node_t synctex_node_child(synctex_node_t node)
752 {
753         return SYNCTEX_CHILD(node);
754 }
755 synctex_node_t synctex_node_sibling(synctex_node_t node)
756 {
757         return SYNCTEX_SIBLING(node);
758 }
759 synctex_node_t synctex_node_next(synctex_node_t node) {
760         if (SYNCTEX_CHILD(node)) {
761                 return SYNCTEX_CHILD(node);
762         }
763 sibling:
764         if (SYNCTEX_SIBLING(node)) {
765                 return SYNCTEX_SIBLING(node);
766         }
767         if ((node = SYNCTEX_PARENT(node))) {
768                 if (node->class->type == synctex_node_type_sheet) {/*  EXC_BAD_ACCESS? */
769                         return NULL;
770                 }
771                 goto sibling;
772         }
773         return NULL;
774 }
775 #       ifdef SYNCTEX_NOTHING
776 #       pragma mark -
777 #       pragma mark CLASS
778 #   endif
779
780 /*  Public node accessor: the type  */
781 synctex_node_type_t synctex_node_type(synctex_node_t node) {
782         if (node) {
783                 return (((node)->class))->type;
784         }
785         return synctex_node_type_error;
786 }
787
788 /*  Public node accessor: the human readable type  */
789 const char * synctex_node_isa(synctex_node_t node) {
790 static const char * isa[synctex_node_number_of_types] =
791                 {"Not a node","input","sheet","vbox","void vbox","hbox","void hbox","kern","glue","math","boundary"};
792         return isa[synctex_node_type(node)];
793 }
794
795 #       ifdef SYNCTEX_NOTHING
796 #       pragma mark -
797 #       pragma mark SYNCTEX_LOG
798 #   endif
799
800 #   define SYNCTEX_LOG(NODE) SYNCTEX_MSG_SEND(NODE,log)
801
802 /*  Public node logger  */
803 void synctex_node_log(synctex_node_t node) {
804         SYNCTEX_LOG(node);
805 }
806
807 #   define SYNCTEX_DISPLAY(NODE) SYNCTEX_MSG_SEND(NODE,display)
808
809 void synctex_node_display(synctex_node_t node) {
810         SYNCTEX_DISPLAY(node);
811 }
812
813 void _synctex_display_input(synctex_node_t node) {
814         printf("....Input:%i:%s\n",
815                 SYNCTEX_TAG(node),
816                 SYNCTEX_NAME(node));
817         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
818 }
819
820 void _synctex_log_sheet(synctex_node_t sheet) {
821         if (sheet) {
822                 printf("%s:%i\n",synctex_node_isa(sheet),SYNCTEX_PAGE(sheet));
823                 printf("SELF:%p",(void *)sheet);
824                 printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(sheet));
825                 printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(sheet));
826                 printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(sheet));
827                 printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(sheet));
828         }
829 }
830
831 void _synctex_log_small_node(synctex_node_t node) {
832         printf("%s:%i,%i:%i,%i\n",
833                 synctex_node_isa(node),
834                 SYNCTEX_TAG(node),
835                 SYNCTEX_LINE(node),
836                 SYNCTEX_HORIZ(node),
837                 SYNCTEX_VERT(node));
838         printf("SELF:%p",(void *)node);
839         printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
840         printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
841         printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
842         printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node));
843 }
844
845 void _synctex_log_medium_node(synctex_node_t node) {
846         printf("%s:%i,%i:%i,%i:%i\n",
847                 synctex_node_isa(node),
848                 SYNCTEX_TAG(node),
849                 SYNCTEX_LINE(node),
850                 SYNCTEX_HORIZ(node),
851                 SYNCTEX_VERT(node),
852                 SYNCTEX_WIDTH(node));
853         printf("SELF:%p",(void *)node);
854         printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
855         printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
856         printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
857         printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node));
858 }
859
860 void _synctex_log_void_box(synctex_node_t node) {
861         printf("%s",synctex_node_isa(node));
862         printf(":%i",SYNCTEX_TAG(node));
863         printf(",%i",SYNCTEX_LINE(node));
864         printf(",%i",0);
865         printf(":%i",SYNCTEX_HORIZ(node));
866         printf(",%i",SYNCTEX_VERT(node));
867         printf(":%i",SYNCTEX_WIDTH(node));
868         printf(",%i",SYNCTEX_HEIGHT(node));
869         printf(",%i",SYNCTEX_DEPTH(node));
870         printf("\nSELF:%p",(void *)node);
871         printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
872         printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
873         printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
874         printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node));
875 }
876
877 void _synctex_log_box(synctex_node_t node) {
878         printf("%s",synctex_node_isa(node));
879         printf(":%i",SYNCTEX_TAG(node));
880         printf(",%i",SYNCTEX_LINE(node));
881         printf(",%i",0);
882         printf(":%i",SYNCTEX_HORIZ(node));
883         printf(",%i",SYNCTEX_VERT(node));
884         printf(":%i",SYNCTEX_WIDTH(node));
885         printf(",%i",SYNCTEX_HEIGHT(node));
886         printf(",%i",SYNCTEX_DEPTH(node));
887         printf("\nSELF:%p",(void *)node);
888         printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
889         printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
890         printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
891         printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node));
892 }
893
894 void _synctex_log_horiz_box(synctex_node_t node) {
895         printf("%s",synctex_node_isa(node));
896         printf(":%i",SYNCTEX_TAG(node));
897         printf(",%i",SYNCTEX_LINE(node));
898         printf(",%i",0);
899         printf(":%i",SYNCTEX_HORIZ(node));
900         printf(",%i",SYNCTEX_VERT(node));
901         printf(":%i",SYNCTEX_WIDTH(node));
902         printf(",%i",SYNCTEX_HEIGHT(node));
903         printf(",%i",SYNCTEX_DEPTH(node));
904         printf("/%i",SYNCTEX_HORIZ_V(node));
905         printf(",%i",SYNCTEX_VERT_V(node));
906         printf(":%i",SYNCTEX_WIDTH_V(node));
907         printf(",%i",SYNCTEX_HEIGHT_V(node));
908         printf(",%i",SYNCTEX_DEPTH_V(node));
909         printf("\nSELF:%p",(void *)node);
910         printf(" SYNCTEX_PARENT:%p",(void *)SYNCTEX_PARENT(node));
911         printf(" SYNCTEX_CHILD:%p",(void *)SYNCTEX_CHILD(node));
912         printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
913         printf(" SYNCTEX_FRIEND:%p\n",(void *)SYNCTEX_FRIEND(node));
914 }
915
916 void _synctex_log_input(synctex_node_t node) {
917         printf("%s",synctex_node_isa(node));
918         printf(":%i",SYNCTEX_TAG(node));
919         printf(",%s",SYNCTEX_NAME(node));
920         printf(" SYNCTEX_SIBLING:%p",(void *)SYNCTEX_SIBLING(node));
921 }
922
923 void _synctex_display_sheet(synctex_node_t sheet) {
924         if (sheet) {
925                 printf("....{%i\n",SYNCTEX_PAGE(sheet));
926                 SYNCTEX_DISPLAY(SYNCTEX_CHILD(sheet));
927                 printf("....}\n");
928                 SYNCTEX_DISPLAY(SYNCTEX_SIBLING(sheet));
929         }
930 }
931
932 void _synctex_display_vbox(synctex_node_t node) {
933         printf("....[%i,%i:%i,%i:%i,%i,%i\n",
934                 SYNCTEX_TAG(node),
935                 SYNCTEX_LINE(node),
936                 SYNCTEX_HORIZ(node),
937                 SYNCTEX_VERT(node),
938                 SYNCTEX_WIDTH(node),
939                 SYNCTEX_HEIGHT(node),
940                 SYNCTEX_DEPTH(node));
941         SYNCTEX_DISPLAY(SYNCTEX_CHILD(node));
942         printf("....]\n");
943         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
944 }
945
946 void _synctex_display_hbox(synctex_node_t node) {
947         printf("....(%i,%i:%i,%i:%i,%i,%i\n",
948                 SYNCTEX_TAG(node),
949                 SYNCTEX_LINE(node),
950                 SYNCTEX_HORIZ(node),
951                 SYNCTEX_VERT(node),
952                 SYNCTEX_WIDTH(node),
953                 SYNCTEX_HEIGHT(node),
954                 SYNCTEX_DEPTH(node));
955         SYNCTEX_DISPLAY(SYNCTEX_CHILD(node));
956         printf("....)\n");
957         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
958 }
959
960 void _synctex_display_void_vbox(synctex_node_t node) {
961         printf("....v%i,%i;%i,%i:%i,%i,%i\n",
962                 SYNCTEX_TAG(node),
963                 SYNCTEX_LINE(node),
964                 SYNCTEX_HORIZ(node),
965                 SYNCTEX_VERT(node),
966                 SYNCTEX_WIDTH(node),
967                 SYNCTEX_HEIGHT(node),
968                 SYNCTEX_DEPTH(node));
969         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
970 }
971
972 void _synctex_display_void_hbox(synctex_node_t node) {
973         printf("....h%i,%i:%i,%i:%i,%i,%i\n",
974                 SYNCTEX_TAG(node),
975                 SYNCTEX_LINE(node),
976                 SYNCTEX_HORIZ(node),
977                 SYNCTEX_VERT(node),
978                 SYNCTEX_WIDTH(node),
979                 SYNCTEX_HEIGHT(node),
980                 SYNCTEX_DEPTH(node));
981         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
982 }
983
984 void _synctex_display_glue(synctex_node_t node) {
985         printf("....glue:%i,%i:%i,%i\n",
986                 SYNCTEX_TAG(node),
987                 SYNCTEX_LINE(node),
988                 SYNCTEX_HORIZ(node),
989                 SYNCTEX_VERT(node));
990         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
991 }
992
993 void _synctex_display_math(synctex_node_t node) {
994         printf("....math:%i,%i:%i,%i\n",
995                 SYNCTEX_TAG(node),
996                 SYNCTEX_LINE(node),
997                 SYNCTEX_HORIZ(node),
998                 SYNCTEX_VERT(node));
999         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
1000 }
1001
1002 void _synctex_display_kern(synctex_node_t node) {
1003         printf("....kern:%i,%i:%i,%i:%i\n",
1004                 SYNCTEX_TAG(node),
1005                 SYNCTEX_LINE(node),
1006                 SYNCTEX_HORIZ(node),
1007                 SYNCTEX_VERT(node),
1008                 SYNCTEX_WIDTH(node));
1009         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
1010 }
1011
1012 void _synctex_display_boundary(synctex_node_t node) {
1013         printf("....boundary:%i,%i:%i,%i\n",
1014                 SYNCTEX_TAG(node),
1015                 SYNCTEX_LINE(node),
1016                 SYNCTEX_HORIZ(node),
1017                 SYNCTEX_VERT(node));
1018         SYNCTEX_DISPLAY(SYNCTEX_SIBLING(node));
1019 }
1020
1021 #       ifdef SYNCTEX_NOTHING
1022 #       pragma mark -
1023 #       pragma mark SCANNER
1024 #   endif
1025
1026 /*  Here are gathered all the possible status that the next scanning functions will return.
1027  *  All these functions return a status, and pass their result through pointers.
1028  *  Negative values correspond to errors.
1029  *  The management of the buffer is causing some significant overhead.
1030  *  Every function that may access the buffer returns a status related to the buffer and file state.
1031  *  status >= SYNCTEX_STATUS_OK means the function worked as expected
1032  *  status < SYNCTEX_STATUS_OK means the function did not work as expected
1033  *  status == SYNCTEX_STATUS_NOT_OK means the function did not work as expected but there is still some material to parse.
1034  *  status == SYNCTEX_STATUS_EOF means the function did not work as expected and there is no more material.
1035  *  status<SYNCTEX_STATUS_EOF means an error
1036  */
1037 typedef int synctex_status_t;
1038 /*  When the end of the synctex file has been reached: */
1039 #   define SYNCTEX_STATUS_EOF 0
1040 /*  When the function could not return the value it was asked for: */
1041 #   define SYNCTEX_STATUS_NOT_OK (SYNCTEX_STATUS_EOF+1)
1042 /*  When the function returns the value it was asked for: */
1043 #   define SYNCTEX_STATUS_OK (SYNCTEX_STATUS_NOT_OK+1)
1044 /*  Generic error: */
1045 #   define SYNCTEX_STATUS_ERROR -1
1046 /*  Parameter error: */
1047 #   define SYNCTEX_STATUS_BAD_ARGUMENT -2
1048
1049 #   define SYNCTEX_FILE (scanner->file)
1050
1051 /*  Actually, the minimum buffer size is driven by integer and float parsing.
1052  *  Â±0.123456789e123
1053  */
1054 #   define SYNCTEX_BUFFER_MIN_SIZE 16
1055 #   define SYNCTEX_BUFFER_SIZE 32768
1056
1057 #       ifdef SYNCTEX_NOTHING
1058 #       pragma mark -
1059 #       pragma mark Prototypes
1060 #   endif
1061 void _synctex_log_void_box(synctex_node_t node);
1062 void _synctex_log_box(synctex_node_t node);
1063 void _synctex_log_horiz_box(synctex_node_t node);
1064 void _synctex_log_input(synctex_node_t node);
1065 synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, size_t * size_ptr);
1066 synctex_status_t _synctex_next_line(synctex_scanner_t scanner);
1067 synctex_status_t _synctex_match_string(synctex_scanner_t scanner, const char * the_string);
1068 synctex_status_t _synctex_decode_int(synctex_scanner_t scanner, int* value_ref);
1069 synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value_ref);
1070 synctex_status_t _synctex_scan_input(synctex_scanner_t scanner);
1071 synctex_status_t _synctex_scan_preamble(synctex_scanner_t scanner);
1072 synctex_status_t _synctex_scan_float_and_dimension(synctex_scanner_t scanner, float * value_ref);
1073 synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_t scanner);
1074 int _synctex_scan_postamble(synctex_scanner_t scanner);
1075 synctex_status_t _synctex_setup_visible_box(synctex_node_t box);
1076 synctex_status_t _synctex_horiz_box_setup_visible(synctex_node_t node,int h, int v);
1077 synctex_status_t _synctex_scan_sheet(synctex_scanner_t scanner, synctex_node_t parent);
1078 synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner);
1079 synctex_status_t _synctex_scan_content(synctex_scanner_t scanner);
1080 int synctex_scanner_pre_x_offset(synctex_scanner_t scanner);
1081 int synctex_scanner_pre_y_offset(synctex_scanner_t scanner);
1082 const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner);
1083 int _synctex_node_is_box(synctex_node_t node);
1084 int _synctex_bail(void);
1085
1086 /*  Try to ensure that the buffer contains at least size bytes.
1087  *  Passing a huge size argument means the whole buffer length.
1088  *  Passing a null size argument means return the available buffer length, without reading the file.
1089  *  In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL,
1090  *  in which case, SYNCTEX_STATUS_BAD_ARGUMENT is returned.
1091  *  The value returned in size_ptr is the number of bytes now available in the buffer.
1092  *  This is a nonnegative integer, it may take the value 0.
1093  *  It is the responsibility of the caller to test whether this size is conforming to its needs.
1094  *  Negative values may return in case of error, actually
1095  *  when there was an error reading the synctex file. */
1096 synctex_status_t _synctex_buffer_get_available_size(synctex_scanner_t scanner, size_t * size_ptr) {
1097         size_t available = 0;
1098         if (NULL == scanner || NULL == size_ptr) {
1099                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1100         }
1101 #   define size (* size_ptr)
1102         if (size>SYNCTEX_BUFFER_SIZE){
1103                 size = SYNCTEX_BUFFER_SIZE;
1104         }
1105         available = SYNCTEX_END - SYNCTEX_CUR; /*  available is the number of unparsed chars in the buffer */
1106         if (size<=available) {
1107                 /*  There are already sufficiently many characters in the buffer */
1108                 size = available;
1109                 return SYNCTEX_STATUS_OK;
1110         }
1111         if (SYNCTEX_FILE) {
1112                 /*  Copy the remaining part of the buffer to the beginning,
1113                  *  then read the next part of the file */
1114                 int already_read = 0;
1115                 if (available) {
1116                         memmove(SYNCTEX_START, SYNCTEX_CUR, available);
1117                 }
1118                 SYNCTEX_CUR = SYNCTEX_START + available; /*  the next character after the move, will change. */
1119                 /*  Fill the buffer up to its end */
1120                 already_read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,SYNCTEX_BUFFER_SIZE - available);
1121                 if (already_read>0) {
1122                         /*  We assume that 0<already_read<=SYNCTEX_BUFFER_SIZE - available, such that
1123                          *  SYNCTEX_CUR + already_read = SYNCTEX_START + available  + already_read <= SYNCTEX_START + SYNCTEX_BUFFER_SIZE */
1124                         SYNCTEX_END = SYNCTEX_CUR + already_read;
1125                         /*  If the end of the file was reached, all the required SYNCTEX_BUFFER_SIZE - available
1126                          *  may not be filled with values from the file.
1127                          *  In that case, the buffer should stop properly after already_read characters. */
1128                         * SYNCTEX_END = '\0';
1129                         SYNCTEX_CUR = SYNCTEX_START;
1130                         size = SYNCTEX_END - SYNCTEX_CUR; /* == old available + already_read*/
1131                         return SYNCTEX_STATUS_OK; /*  May be available is less than size, the caller will have to test. */
1132                 } else if (0>already_read) {
1133                         /*  There is a possible error in reading the file */
1134                         int errnum = 0;
1135                         const char * error_string = gzerror(SYNCTEX_FILE, &errnum);
1136                         if (Z_ERRNO == errnum) {
1137                                 /*  There is an error in zlib caused by the file system */
1138                                 _synctex_error("gzread error from the file system (%i)",errno);
1139                 return SYNCTEX_STATUS_ERROR;
1140                         } else if (errnum) {
1141                                 _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string);
1142                 return SYNCTEX_STATUS_ERROR;
1143                         }
1144                 }
1145         /*  Nothing was read, we are at the end of the file. */
1146         gzclose(SYNCTEX_FILE);
1147         SYNCTEX_FILE = NULL;
1148         SYNCTEX_END = SYNCTEX_CUR;
1149         SYNCTEX_CUR = SYNCTEX_START;
1150         * SYNCTEX_END = '\0';/*  Terminate the string properly.*/
1151         size = SYNCTEX_END - SYNCTEX_CUR;
1152         return SYNCTEX_STATUS_EOF; /*  there might be a bit of text left */
1153     }
1154         /*  We cannot enlarge the buffer because the end of the file was reached. */
1155         size = available;
1156         return SYNCTEX_STATUS_EOF;
1157 #   undef size
1158 }
1159
1160 /*  Used when parsing the synctex file.
1161  *  Advance to the next character starting a line.
1162  *  Actually, only '\n' is recognized as end of line marker.
1163  *  On normal completion, the returned value is the number of unparsed characters available in the buffer.
1164  *  In general, it is a positive value, 0 meaning that the end of file was reached.
1165  *  -1 is returned in case of error, actually because there was an error while feeding the buffer.
1166  *  When the function returns with no error, SYNCTEX_CUR points to the first character of the next line, if any.
1167  *  J. Laurens: Sat May 10 07:52:31 UTC 2008
1168  */
1169 synctex_status_t _synctex_next_line(synctex_scanner_t scanner) {
1170         synctex_status_t status = SYNCTEX_STATUS_OK;
1171         size_t available = 0;
1172         if (NULL == scanner) {
1173                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1174         }
1175 infinite_loop:
1176         while(SYNCTEX_CUR<SYNCTEX_END) {
1177                 if (*SYNCTEX_CUR == '\n') {
1178                         ++SYNCTEX_CUR;
1179                         available = 1;
1180                         return _synctex_buffer_get_available_size(scanner, &available);
1181                 }
1182                 ++SYNCTEX_CUR;
1183         }
1184         /*  Here, we have SYNCTEX_CUR == SYNCTEX_END, such that the next call to _synctex_buffer_get_available_size
1185          *  will read another bunch of synctex file. Little by little, we advance to the end of the file. */
1186         available = 1;
1187         status = _synctex_buffer_get_available_size(scanner, &available);
1188         if (status<=0) {
1189                 return status;
1190         }
1191         goto infinite_loop;
1192 }
1193
1194 /*  Scan the given string.
1195  *  Both scanner and the_string must not be NULL, and the_string must not be 0 length.
1196  *  SYNCTEX_STATUS_OK is returned if the string is found,
1197  *  SYNCTEX_STATUS_EOF is returned when the EOF is reached,
1198  *  SYNCTEX_STATUS_NOT_OK is returned is the string is not found,
1199  *  an error status is returned otherwise.
1200  *  This is a critical method because buffering renders things more difficult.
1201  *  The given string might be as long as the maximum size_t value.
1202  *  As side effect, the buffer state may have changed if the given argument string can't fit into the buffer.
1203  */
1204 synctex_status_t _synctex_match_string(synctex_scanner_t scanner, const char * the_string) {
1205         size_t tested_len = 0; /*  the number of characters at the beginning of the_string that match */
1206         size_t remaining_len = 0; /*  the number of remaining characters of the_string that should match */
1207         size_t available = 0;
1208         synctex_status_t status = 0;
1209         if (NULL == scanner || NULL == the_string) {
1210                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1211         }
1212         remaining_len = strlen(the_string); /*  All the_string should match */
1213         if (0 == remaining_len) {
1214                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1215         }
1216         /*  How many characters available in the buffer? */
1217         available = remaining_len;
1218         status = _synctex_buffer_get_available_size(scanner,&available);
1219         if (status<SYNCTEX_STATUS_EOF) {
1220                 return status;
1221         }
1222         /*  Maybe we have less characters than expected because the buffer is too small. */
1223         if (available>=remaining_len) {
1224                 /*  The buffer is sufficiently big to hold the expected number of characters. */
1225                 if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) {
1226                         return SYNCTEX_STATUS_NOT_OK;
1227                 }
1228 return_OK:
1229                 /*  Advance SYNCTEX_CUR to the next character after the_string. */
1230                 SYNCTEX_CUR += remaining_len;
1231                 return SYNCTEX_STATUS_OK;
1232         } else if (strncmp((char *)SYNCTEX_CUR,the_string,available)) {
1233                         /*  No need to goo further, this is not the expected string in the buffer. */
1234                         return SYNCTEX_STATUS_NOT_OK;
1235         } else if (SYNCTEX_FILE) {
1236                 /*  The buffer was too small to contain remaining_len characters.
1237                  *  We have to cut the string into pieces. */
1238                 z_off_t offset = 0L;
1239                 /*  the first part of the string is found, advance the_string to the next untested character. */
1240                 the_string += available;
1241                 /*  update the remaining length and the parsed length. */
1242                 remaining_len -= available;
1243                 tested_len += available;
1244                 SYNCTEX_CUR += available; /*  We validate the tested characters. */
1245                 if (0 == remaining_len) {
1246                         /*  Nothing left to test, we have found the given string, we return the length. */
1247                         return tested_len;
1248                 }
1249                 /*  We also have to record the current state of the file cursor because
1250                  *  if the_string does not match, all this should be a totally blank operation,
1251                  *  for which the file and buffer states should not be modified at all.
1252                  *  In fact, the states of the buffer before and after this function are in general different
1253                  *  but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR
1254                  *  can be safely discarded.  */
1255                 offset = gztell(SYNCTEX_FILE);
1256                 /*  offset now corresponds to the first character of the file that was not buffered. */
1257                 available = SYNCTEX_CUR - SYNCTEX_START; /*  available can be used as temporary placeholder. */
1258                 /*  available now corresponds to the number of chars that where already buffered and
1259                  *  that match the head of the_string. If in fine the_string does not match, all these chars must be recovered
1260                  *  because the buffer contents is completely replaced by _synctex_buffer_get_available_size.
1261                  *  They were buffered from offset-len location in the file. */
1262                 offset -= available;
1263 more_characters:
1264                 /*  There is still some work to be done, so read another bunch of file.
1265                  *  This is the second call to _synctex_buffer_get_available_size,
1266                  *  which means that the actual contents of the buffer will be discarded.
1267                  *  We will definitely have to recover the previous state in case we do not find the expected string. */
1268                 available = remaining_len;
1269                 status = _synctex_buffer_get_available_size(scanner,&available);
1270                 if (status<SYNCTEX_STATUS_EOF) {
1271                         return status; /*  This is an error, no need to go further. */
1272                 }
1273                 if (available==0) {
1274                         /*  Missing characters: recover the initial state of the file and return. */
1275 return_NOT_OK:
1276                         if (offset != gzseek(SYNCTEX_FILE,offset,SEEK_SET)) {
1277                                 /*  This is a critical error, we could not recover the previous state. */
1278                                 _synctex_error("can't seek file");
1279                                 return SYNCTEX_STATUS_ERROR;
1280                         }
1281                         /*  Next time we are asked to fill the buffer,
1282                          *  we will read a complete bunch of text from the file. */
1283                         SYNCTEX_CUR = SYNCTEX_END;
1284                         return SYNCTEX_STATUS_NOT_OK;
1285                 }
1286                 if (available<remaining_len) {
1287                         /*  We'll have to loop one more time. */
1288                         if (strncmp((char *)SYNCTEX_CUR,the_string,available)) {
1289                                 /*  This is not the expected string, recover the previous state and return. */
1290                                 goto return_NOT_OK;
1291                         }
1292                         /*  Advance the_string to the first untested character. */
1293                         the_string += available;
1294                         /*  update the remaining length and the parsed length. */
1295                         remaining_len -= available;
1296                         tested_len += available;
1297                         SYNCTEX_CUR += available; /*  We validate the tested characters. */
1298                         if (0 == remaining_len) {
1299                                 /*  Nothing left to test, we have found the given string. */
1300                                 return SYNCTEX_STATUS_OK;
1301                         }
1302                         goto more_characters;
1303                 }
1304                 /*  This is the last step. */
1305                 if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) {
1306                         /*  This is not the expected string, recover the previous state and return. */
1307                         goto return_NOT_OK;
1308                 }
1309                 goto return_OK;
1310         } else {
1311                 /*  The buffer can't contain the given string argument, and the EOF was reached */
1312                 return SYNCTEX_STATUS_EOF;
1313         }
1314 }
1315
1316 /*  Used when parsing the synctex file.
1317  *  Decode an integer.
1318  *  First, field separators, namely ':' and ',' characters are skipped
1319  *  The returned value is negative if there is an unrecoverable error.
1320  *  It is SYNCTEX_STATUS_NOT_OK if an integer could not be parsed, for example
1321  *  if the characters at the current cursor position are not digits or
1322  *  if the end of the file has been reached.
1323  *  It is SYNCTEX_STATUS_OK if an int has been successfully parsed.
1324  *  The given scanner argument must not be NULL, on the contrary, value_ref may be NULL.
1325  */
1326 synctex_status_t _synctex_decode_int(synctex_scanner_t scanner, int* value_ref) {
1327         char * ptr = NULL;
1328         char * end = NULL;
1329         int result = 0;
1330         size_t available = 0;
1331         synctex_status_t status = 0;
1332         if (NULL == scanner) {
1333                  return SYNCTEX_STATUS_BAD_ARGUMENT;
1334         }
1335         available = SYNCTEX_BUFFER_MIN_SIZE;
1336         status = _synctex_buffer_get_available_size(scanner, &available);
1337         if (status<SYNCTEX_STATUS_EOF) {
1338                 return status;/*  Forward error. */
1339         }
1340         if (available==0) {
1341                 return SYNCTEX_STATUS_EOF;/*  it is the end of file. */
1342         }
1343         ptr = SYNCTEX_CUR;
1344         if (*ptr==':' || *ptr==',') {
1345                 ++ptr;
1346                 --available;
1347                 if (available==0) {
1348                         return SYNCTEX_STATUS_NOT_OK;/*  It is not possible to scan an int */
1349                 }
1350         }
1351         result = (int)strtol(ptr, &end, 10);
1352         if (end>ptr) {
1353                 SYNCTEX_CUR = end;
1354                 if (value_ref) {
1355                         * value_ref = result;
1356                 }
1357                 return SYNCTEX_STATUS_OK;/*  Successfully scanned an int */
1358         }       
1359         return SYNCTEX_STATUS_NOT_OK;/*  Could not scan an int */
1360 }
1361
1362 /*  The purpose of this function is to read a string.
1363  *  A string is an array of characters from the current parser location
1364  *  and before the next '\n' character.
1365  *  If a string was properly decoded, it is returned in value_ref and
1366  *  the cursor points to the new line marker.
1367  *  The returned string was alloced on the heap, the caller is the owner and
1368  *  is responsible to free it in due time.
1369  *  If no string is parsed, * value_ref is undefined.
1370  *  The maximum length of a string that a scanner can decode is platform dependent, namely UINT_MAX.
1371  *  If you just want to blindly parse the file up to the end of the current line,
1372  *  use _synctex_next_line instead.
1373  *  On return, the scanner cursor is unchanged if a string could not be scanned or
1374  *  points to the terminating '\n' character otherwise. As a consequence,
1375  *  _synctex_next_line is necessary after.
1376  *  If either scanner or value_ref is NULL, it is considered as an error and
1377  *  SYNCTEX_STATUS_BAD_ARGUMENT is returned.
1378  */
1379 synctex_status_t _synctex_decode_string(synctex_scanner_t scanner, char ** value_ref) {
1380         char * end = NULL;
1381         size_t current_size = 0;
1382         size_t new_size = 0;
1383         size_t len = 0;/*  The number of bytes to copy */
1384         size_t available = 0;
1385         synctex_status_t status = 0;
1386         if (NULL == scanner || NULL == value_ref) {
1387                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1388         }
1389         /*  The buffer must at least contain one character: the '\n' end of line marker */
1390         if (SYNCTEX_CUR>=SYNCTEX_END) {
1391                 available = 1;
1392                 status = _synctex_buffer_get_available_size(scanner,&available);
1393                 if (status < 0) {
1394                         return status;
1395                 }
1396                 if (0 == available) {
1397                         return SYNCTEX_STATUS_EOF;
1398                 }
1399         }
1400         /*  Now we are sure that there is at least one available character, either because
1401          *  SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */
1402         /*  end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */
1403         end = SYNCTEX_CUR;
1404         * value_ref = NULL;/*  Initialize, it will be realloc'ed */
1405         /*  We scan all the characters up to the next '\n' */
1406 next_character:
1407         if (end<SYNCTEX_END) {
1408                 if (*end == '\n') {
1409                         /*  OK, we found where to stop */
1410                         len = end - SYNCTEX_CUR;
1411                         if (current_size>UINT_MAX-len-1) {
1412                                 /*  But we have reached the limit: we do not have current_size+len+1>UINT_MAX.
1413                                  *  We return the missing amount of memory.
1414                                  *  This will never occur in practice. */
1415                                 return UINT_MAX-len-1 - current_size;
1416                         }
1417                         new_size = current_size+len;
1418                         /*  We have current_size+len+1<=UINT_MAX
1419                          *  or equivalently new_size<UINT_MAX,
1420                          *  where we have assumed that len<UINT_MAX */
1421                         if ((* value_ref = realloc(* value_ref,new_size+1)) != NULL) {
1422                                 if (memcpy((*value_ref)+current_size,SYNCTEX_CUR,len)) {
1423                                         (* value_ref)[new_size]='\0'; /*  Terminate the string */
1424                                         SYNCTEX_CUR += len;/*  Advance to the terminating '\n' */
1425                                         return SYNCTEX_STATUS_OK;
1426                                 }
1427                                 free(* value_ref);
1428                                 * value_ref = NULL;
1429                                 _synctex_error("could not copy memory (1).");
1430                                 return SYNCTEX_STATUS_ERROR;
1431                         }
1432                         _synctex_error("could not allocate memory (1).");
1433                         return SYNCTEX_STATUS_ERROR;
1434                 } else {
1435                         ++end;
1436                         goto next_character;
1437                 }
1438         } else {
1439                 /*  end == SYNCTEX_END */
1440                 len = SYNCTEX_END - SYNCTEX_CUR;
1441                 if (current_size>UINT_MAX-len-1) {
1442                         /*  We have reached the limit. */
1443                         _synctex_error("limit reached (missing %i).",current_size-(UINT_MAX-len-1));
1444                         return SYNCTEX_STATUS_ERROR;
1445                 }
1446                 new_size = current_size+len;
1447                 if ((* value_ref = realloc(* value_ref,new_size+1)) != NULL) {
1448                         if (memcpy((*value_ref)+current_size,SYNCTEX_CUR,len)) {
1449                                 (* value_ref)[new_size]='\0'; /*  Terminate the string */
1450                                 SYNCTEX_CUR = SYNCTEX_END;/*  Advance the cursor to the end of the bufer */
1451                                 return SYNCTEX_STATUS_OK;
1452                         }
1453                         free(* value_ref);
1454                         * value_ref = NULL;
1455                         _synctex_error("could not copy memory (2).");
1456                         return SYNCTEX_STATUS_ERROR;
1457                 }
1458                 /*  Huge memory problem */
1459                 _synctex_error("could not allocate memory (2).");
1460                 return SYNCTEX_STATUS_ERROR;
1461         }
1462 }
1463
1464 /*  Used when parsing the synctex file.
1465  *  Read an Input record.
1466  */
1467 synctex_status_t _synctex_scan_input(synctex_scanner_t scanner) {
1468         synctex_status_t status = 0;
1469         size_t available = 0;
1470         synctex_node_t input = NULL;
1471         if (NULL == scanner) {
1472                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1473         }
1474         status = _synctex_match_string(scanner,"Input:");
1475         if (status<SYNCTEX_STATUS_OK) {
1476                 return status;
1477         }
1478         /*  Create a node */
1479         input = _synctex_new_input(scanner);
1480         if (NULL == input) {
1481                 _synctex_error("could not create an input node.");
1482                 return SYNCTEX_STATUS_ERROR;
1483         }
1484         /*  Decode the synctag  */
1485         status = _synctex_decode_int(scanner,&(SYNCTEX_TAG(input)));
1486         if (status<SYNCTEX_STATUS_OK) {
1487                 _synctex_error("bad format of input node.");
1488                 SYNCTEX_FREE(input);
1489                 return status;
1490         }
1491         /*  The next character is a field separator, we expect one character in the buffer. */
1492         available = 1;
1493         status = _synctex_buffer_get_available_size(scanner, &available);
1494         if (status<=SYNCTEX_STATUS_ERROR) {
1495                 return status;
1496         }
1497         if (0 == available) {
1498                 return SYNCTEX_STATUS_EOF;
1499         }
1500         /*  We can now safely advance to the next character, stepping over the field separator. */
1501         ++SYNCTEX_CUR;
1502         --available;
1503         /*  Then we scan the file name */
1504         status = _synctex_decode_string(scanner,&(SYNCTEX_NAME(input)));
1505         if (status<SYNCTEX_STATUS_OK) {
1506                 SYNCTEX_FREE(input);
1507                 return status;
1508         }
1509         /*  Prepend this input node to the input linked list of the scanner */
1510         SYNCTEX_SET_SIBLING(input,scanner->input);
1511         scanner->input = input;
1512         return _synctex_next_line(scanner);/*  read the line termination character, if any */
1513         /*  Now, set up the path */
1514 }
1515
1516 typedef synctex_status_t (*synctex_decoder_t)(synctex_scanner_t,void *);
1517
1518 synctex_status_t _synctex_scan_named(synctex_scanner_t scanner,const char * name,void * value_ref,synctex_decoder_t decoder);
1519
1520 /*  Used when parsing the synctex file.
1521  *  Read one of the settings.
1522  *  On normal completion, returns SYNCTEX_STATUS_OK.
1523  *  On error, returns SYNCTEX_STATUS_ERROR.
1524  *  Both arguments must not be NULL.
1525  *  On return, the scanner points to the next character after the decoded object whatever it is.
1526  *  It is the responsibility of the caller to prepare the scanner for the next line.
1527  */
1528 synctex_status_t _synctex_scan_named(synctex_scanner_t scanner,const char * name,void * value_ref,synctex_decoder_t decoder) {
1529         synctex_status_t status = 0;
1530         if (NULL == scanner || NULL == name || NULL == value_ref || NULL == decoder) {
1531                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1532         }
1533 not_found:
1534         status = _synctex_match_string(scanner,name);
1535         if (status<SYNCTEX_STATUS_NOT_OK) {
1536                 return status;
1537         } else if (status == SYNCTEX_STATUS_NOT_OK) {
1538                 status = _synctex_next_line(scanner);
1539                 if (status<SYNCTEX_STATUS_OK) {
1540                         return status;
1541                 }
1542                 goto not_found;
1543         }
1544         /*  A line is found, scan the value */
1545         return (*decoder)(scanner,value_ref);
1546 }
1547
1548 /*  Used when parsing the synctex file.
1549  *  Read the preamble.
1550  */
1551 synctex_status_t _synctex_scan_preamble(synctex_scanner_t scanner) {
1552         synctex_status_t status = 0;
1553         if (NULL == scanner) {
1554                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1555         }
1556         status = _synctex_scan_named(scanner,"SyncTeX Version:",&(scanner->version),(synctex_decoder_t)&_synctex_decode_int);
1557         if (status<SYNCTEX_STATUS_OK) {
1558                 return status;
1559         }
1560         status = _synctex_next_line(scanner);
1561         if (status<SYNCTEX_STATUS_OK) {
1562                 return status;
1563         }
1564         /*  Read all the input records */
1565         do {
1566                 status = _synctex_scan_input(scanner);
1567                 if (status<SYNCTEX_STATUS_NOT_OK) {
1568                         return status;
1569                 }
1570         } while(status == SYNCTEX_STATUS_OK);
1571         /*  the loop exits when status == SYNCTEX_STATUS_NOT_OK */
1572         /*  Now read all the required settings. */
1573         status = _synctex_scan_named(scanner,"Output:",&(scanner->output_fmt),(synctex_decoder_t)&_synctex_decode_string);
1574         if (status<SYNCTEX_STATUS_NOT_OK) {
1575                 return status;
1576         }
1577         status = _synctex_next_line(scanner);
1578         if (status<SYNCTEX_STATUS_OK) {
1579                 return status;
1580         }
1581         status = _synctex_scan_named(scanner,"Magnification:",&(scanner->pre_magnification),(synctex_decoder_t)&_synctex_decode_int);
1582         if (status<SYNCTEX_STATUS_OK) {
1583                 return status;
1584         }
1585         status = _synctex_next_line(scanner);
1586         if (status<SYNCTEX_STATUS_OK) {
1587                 return status;
1588         }
1589         status = _synctex_scan_named(scanner,"Unit:",&(scanner->pre_unit),(synctex_decoder_t)&_synctex_decode_int);
1590         if (status<SYNCTEX_STATUS_OK) {
1591                 return status;
1592         }
1593         status = _synctex_next_line(scanner);
1594         if (status<SYNCTEX_STATUS_OK) {
1595                 return status;
1596         }
1597         status = _synctex_scan_named(scanner,"X Offset:",&(scanner->pre_x_offset),(synctex_decoder_t)&_synctex_decode_int);
1598         if (status<SYNCTEX_STATUS_OK) {
1599                 return status;
1600         }
1601         status = _synctex_next_line(scanner);
1602         if (status<SYNCTEX_STATUS_OK) {
1603                 return status;
1604         }
1605         status = _synctex_scan_named(scanner,"Y Offset:",&(scanner->pre_y_offset),(synctex_decoder_t)&_synctex_decode_int);
1606         if (status<SYNCTEX_STATUS_OK) {
1607                 return status;
1608         }
1609         return _synctex_next_line(scanner);
1610 }
1611
1612 /*  parse a float with a dimension */
1613 synctex_status_t _synctex_scan_float_and_dimension(synctex_scanner_t scanner, float * value_ref) {
1614         synctex_status_t status = 0;
1615         char * endptr = NULL;
1616         float f = 0;
1617 #ifdef HAVE_SETLOCALE
1618         char * loc = setlocale(LC_NUMERIC, NULL);
1619 #endif
1620         size_t available = 0;
1621         if (NULL == scanner || NULL == value_ref) {
1622                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1623         }
1624         available = SYNCTEX_BUFFER_MIN_SIZE;
1625         status = _synctex_buffer_get_available_size(scanner, &available);
1626         if (status<SYNCTEX_STATUS_EOF) {
1627                 _synctex_error("problem with float.");
1628                 return status;
1629         }
1630 #ifdef HAVE_SETLOCALE
1631         setlocale(LC_NUMERIC, "C");
1632 #endif
1633         f = strtod(SYNCTEX_CUR,&endptr);
1634 #ifdef HAVE_SETLOCALE
1635         setlocale(LC_NUMERIC, loc);
1636 #endif
1637         if (endptr == SYNCTEX_CUR) {
1638                 _synctex_error("a float was expected.");
1639                 return SYNCTEX_STATUS_ERROR;
1640         }
1641         SYNCTEX_CUR = endptr;
1642         if ((status = _synctex_match_string(scanner,"in")) >= SYNCTEX_STATUS_OK) {
1643                 f *= 72.27f*65536;
1644         } else if (status<SYNCTEX_STATUS_EOF) {
1645 report_unit_error:
1646                 _synctex_error("problem with unit.");
1647                 return status;
1648         } else if ((status = _synctex_match_string(scanner,"cm")) >= SYNCTEX_STATUS_OK) {
1649                 f *= 72.27f*65536/2.54f;
1650         } else if (status<0) {
1651                 goto report_unit_error;
1652         } else if ((status = _synctex_match_string(scanner,"mm")) >= SYNCTEX_STATUS_OK) {
1653                 f *= 72.27f*65536/25.4f;
1654         } else if (status<0) {
1655                 goto report_unit_error;
1656         } else if ((status = _synctex_match_string(scanner,"pt")) >= SYNCTEX_STATUS_OK) {
1657                 f *= 65536.0f;
1658         } else if (status<0) {
1659                 goto report_unit_error;
1660         } else if ((status = _synctex_match_string(scanner,"bp")) >= SYNCTEX_STATUS_OK) {
1661                 f *= 72.27f/72*65536.0f;
1662         }  else if (status<0) {
1663                 goto report_unit_error;
1664         } else if ((status = _synctex_match_string(scanner,"pc")) >= SYNCTEX_STATUS_OK) {
1665                 f *= 12.0*65536.0f;
1666         }  else if (status<0) {
1667                 goto report_unit_error;
1668         } else if ((status = _synctex_match_string(scanner,"sp")) >= SYNCTEX_STATUS_OK) {
1669                 f *= 1.0f;
1670         }  else if (status<0) {
1671                 goto report_unit_error;
1672         } else if ((status = _synctex_match_string(scanner,"dd")) >= SYNCTEX_STATUS_OK) {
1673                 f *= 1238.0f/1157*65536.0f;
1674         }  else if (status<0) {
1675                 goto report_unit_error;
1676         } else if ((status = _synctex_match_string(scanner,"cc")) >= SYNCTEX_STATUS_OK) {
1677                 f *= 14856.0f/1157*65536;
1678         } else if (status<0) {
1679                 goto report_unit_error;
1680         } else if ((status = _synctex_match_string(scanner,"nd")) >= SYNCTEX_STATUS_OK) {
1681                 f *= 685.0f/642*65536;
1682         }  else if (status<0) {
1683                 goto report_unit_error;
1684         } else if ((status = _synctex_match_string(scanner,"nc")) >= SYNCTEX_STATUS_OK) {
1685                 f *= 1370.0f/107*65536;
1686         } else if (status<0) {
1687                 goto report_unit_error;
1688         }
1689         *value_ref = f;
1690         return SYNCTEX_STATUS_OK;
1691 }
1692
1693 /*  parse the post scriptum
1694  *  SYNCTEX_STATUS_OK is returned on completion
1695  *  a negative error is returned otherwise */
1696 synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_t scanner) {
1697         synctex_status_t status = 0;
1698         char * endptr = NULL;
1699 #ifdef HAVE_SETLOCALE
1700         char * loc = setlocale(LC_NUMERIC, NULL);
1701 #endif
1702         if (NULL == scanner) {
1703                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1704         }
1705         /*  Scan the file until a post scriptum line is found */
1706 post_scriptum_not_found:
1707         status = _synctex_match_string(scanner,"Post scriptum:");
1708         if (status<SYNCTEX_STATUS_NOT_OK) {
1709                 return status;
1710         }
1711         if (status == SYNCTEX_STATUS_NOT_OK) {
1712                 status = _synctex_next_line(scanner);
1713                 if (status<SYNCTEX_STATUS_EOF) {
1714                         return status;
1715                 } else if (status<SYNCTEX_STATUS_OK) {
1716                         return SYNCTEX_STATUS_OK;/*  The EOF is found, we have properly scanned the file */
1717                 }
1718                 goto post_scriptum_not_found;
1719         }
1720         /*  We found the name, advance to the next line. */
1721 next_line:
1722         status = _synctex_next_line(scanner);
1723         if (status<SYNCTEX_STATUS_EOF) {
1724                 return status;
1725         } else if (status<SYNCTEX_STATUS_OK) {
1726                 return SYNCTEX_STATUS_OK;/*  The EOF is found, we have properly scanned the file */
1727         }
1728         /*  Scanning the information */
1729         status = _synctex_match_string(scanner,"Magnification:");
1730         if (status == SYNCTEX_STATUS_OK ) {
1731 #ifdef HAVE_SETLOCALE
1732                 setlocale(LC_NUMERIC, "C");
1733 #endif
1734                 scanner->unit = strtod(SYNCTEX_CUR,&endptr);
1735 #ifdef HAVE_SETLOCALE
1736                 setlocale(LC_NUMERIC, loc);
1737 #endif
1738                 if (endptr == SYNCTEX_CUR) {
1739                         _synctex_error("bad magnification in the post scriptum, a float was expected.");
1740                         return SYNCTEX_STATUS_ERROR;
1741                 }
1742                 if (scanner->unit<=0) {
1743                         _synctex_error("bad magnification in the post scriptum, a positive float was expected.");
1744                         return SYNCTEX_STATUS_ERROR;
1745                 }
1746                 SYNCTEX_CUR = endptr;
1747                 goto next_line;
1748         }
1749         if (status<SYNCTEX_STATUS_EOF){
1750 report_record_problem:
1751                 _synctex_error("Problem reading the Post Scriptum records");
1752                 return status; /*  echo the error. */
1753         }
1754         status = _synctex_match_string(scanner,"X Offset:");
1755         if (status == SYNCTEX_STATUS_OK) {
1756                 status = _synctex_scan_float_and_dimension(scanner, &(scanner->x_offset));
1757                 if (status<SYNCTEX_STATUS_OK) {
1758                         _synctex_error("problem with X offset in the Post Scriptum.");
1759                         return status;
1760                 }
1761                 goto next_line;
1762         } else if (status<SYNCTEX_STATUS_EOF){
1763                 goto report_record_problem;
1764         }
1765         status = _synctex_match_string(scanner,"Y Offset:");
1766         if (status==SYNCTEX_STATUS_OK) {
1767                 status = _synctex_scan_float_and_dimension(scanner, &(scanner->y_offset));
1768                 if (status<SYNCTEX_STATUS_OK) {
1769                         _synctex_error("problem with Y offset in the Post Scriptum.");
1770                         return status;
1771                 }
1772                 goto next_line;
1773         } else if (status<SYNCTEX_STATUS_EOF){
1774                 goto report_record_problem;
1775         }
1776         goto next_line;
1777 }
1778
1779 /*  SYNCTEX_STATUS_OK is returned if the postamble is read
1780  *  SYNCTEX_STATUS_NOT_OK is returned if the postamble is not at the current location
1781  *  a negative error otherwise
1782  *  The postamble comprises the post scriptum section.
1783  */
1784 int _synctex_scan_postamble(synctex_scanner_t scanner) {
1785         int status = 0;
1786         if (NULL == scanner) {
1787                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1788         }
1789         status = _synctex_match_string(scanner,"Postamble:");
1790         if (status < SYNCTEX_STATUS_OK) {
1791                 return status;
1792         }
1793 count_again:
1794         status = _synctex_next_line(scanner);
1795         if (status < SYNCTEX_STATUS_OK) {
1796                 return status;
1797         }
1798         status = _synctex_scan_named(scanner,"Count:",&(scanner->count),(synctex_decoder_t)&_synctex_decode_int);
1799         if (status < SYNCTEX_STATUS_EOF) {
1800                 return status; /*  forward the error */
1801         } else if (status < SYNCTEX_STATUS_OK) { /*  No Count record found */
1802                 status = _synctex_next_line(scanner); /*  Advance one more line */
1803                 if (status<SYNCTEX_STATUS_OK) {
1804                         return status;
1805                 }
1806                 goto count_again;
1807         }
1808         /*  Now we scan the last part of the SyncTeX file: the Post Scriptum section. */
1809         return _synctex_scan_post_scriptum(scanner);
1810 }
1811
1812 /*  Horizontal boxes also have visible size.
1813  *  Visible size are bigger than real size.
1814  *  For example 0 width boxes may contain text.
1815  *  At creation time, the visible size is set to the values of the real size.
1816  */
1817 synctex_status_t _synctex_setup_visible_box(synctex_node_t box) {
1818         if (box) {
1819                 switch(box->class->type) {
1820                         case synctex_node_type_hbox:
1821                                 if (SYNCTEX_INFO(box) != NULL) {
1822                                         SYNCTEX_HORIZ_V(box)  = SYNCTEX_HORIZ(box);
1823                                         SYNCTEX_VERT_V(box)   = SYNCTEX_VERT(box);
1824                                         SYNCTEX_WIDTH_V(box)  = SYNCTEX_WIDTH(box);
1825                                         SYNCTEX_HEIGHT_V(box) = SYNCTEX_HEIGHT(box);
1826                                         SYNCTEX_DEPTH_V(box)  = SYNCTEX_DEPTH(box);
1827                                         return SYNCTEX_STATUS_OK;
1828                                 }
1829                                 return SYNCTEX_STATUS_ERROR;
1830                 }
1831         }
1832         return SYNCTEX_STATUS_BAD_ARGUMENT;
1833 }
1834
1835 /*  This method is sent to an horizontal box to setup the visible size
1836  *  Some box have 0 width but do contain text material.
1837  *  With this method, one can enlarge the box to contain the given point (h,v).
1838  */
1839 synctex_status_t _synctex_horiz_box_setup_visible(synctex_node_t node,int h, int v) {
1840 #       ifdef __DARWIN_UNIX03
1841 #       pragma unused(v)
1842 #   endif
1843         int itsBtm, itsTop;
1844         if (NULL == node || node->class->type != synctex_node_type_hbox) {
1845                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1846         }
1847         if (SYNCTEX_WIDTH_V(node)<0) {
1848                 itsBtm = SYNCTEX_HORIZ_V(node);
1849                 itsTop = SYNCTEX_HORIZ_V(node)-SYNCTEX_WIDTH_V(node);
1850                 if (h<itsBtm) {
1851                         SYNCTEX_HORIZ_V(node) = h;
1852                         SYNCTEX_WIDTH_V(node) = SYNCTEX_HORIZ_V(node) - itsTop;
1853                 } else if (h>itsTop) {
1854                         SYNCTEX_WIDTH_V(node) = SYNCTEX_HORIZ_V(node) - h;
1855                 }
1856         } else {
1857                 itsBtm = SYNCTEX_HORIZ_V(node);
1858                 itsTop = SYNCTEX_HORIZ_V(node)+SYNCTEX_WIDTH_V(node);
1859                 if (h<itsBtm) {
1860                         SYNCTEX_HORIZ_V(node) = h;
1861                         SYNCTEX_WIDTH_V(node) = itsTop - SYNCTEX_HORIZ_V(node);
1862                 } else if (h>itsTop) {
1863                         SYNCTEX_WIDTH_V(node) = h - SYNCTEX_HORIZ_V(node);
1864                 }
1865         }
1866         return SYNCTEX_STATUS_OK;
1867 }
1868
1869 /*  Here are the control characters that strat each line of the synctex output file.
1870  *  Their values define the meaning of the line.
1871  */
1872 #   define SYNCTEX_CHAR_BEGIN_SHEET '{'
1873 #   define SYNCTEX_CHAR_END_SHEET   '}'
1874 #   define SYNCTEX_CHAR_BEGIN_VBOX  '['
1875 #   define SYNCTEX_CHAR_END_VBOX    ']'
1876 #   define SYNCTEX_CHAR_BEGIN_HBOX  '('
1877 #   define SYNCTEX_CHAR_END_HBOX    ')'
1878 #   define SYNCTEX_CHAR_ANCHOR      '!'
1879 #   define SYNCTEX_CHAR_VOID_VBOX   'v'
1880 #   define SYNCTEX_CHAR_VOID_HBOX   'h'
1881 #   define SYNCTEX_CHAR_KERN        'k'
1882 #   define SYNCTEX_CHAR_GLUE        'g'
1883 #   define SYNCTEX_CHAR_MATH        '$'
1884 #   define SYNCTEX_CHAR_BOUNDARY    'x'
1885
1886 #   define SYNCTEX_RETURN(STATUS) return STATUS;
1887
1888 /*  Used when parsing the synctex file. A '{' character has just been parsed.
1889  *  The purpose is to gobble everything until the closing '}'.
1890  *  Actually only one nesting depth has been observed when using the clip option
1891  *  of \includegraphics option. Here we use arbitrary level of depth.
1892  */
1893 synctex_status_t _synctex_scan_nested_sheet(synctex_scanner_t scanner) {
1894     unsigned int depth = 0;
1895 deeper:
1896     ++depth;
1897     if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
1898         _synctex_error("Unexpected end of nested sheet (1).");
1899         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1900     }
1901 scan_next_line:
1902     if (SYNCTEX_CUR<SYNCTEX_END) {
1903                 if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
1904                         ++SYNCTEX_CUR;
1905                         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
1906                                 _synctex_error("Unexpected end of nested sheet (2).");
1907                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1908                         }
1909             if (--depth>0) {
1910                 goto scan_next_line;
1911             } else {
1912                 SYNCTEX_RETURN(SYNCTEX_STATUS_OK);
1913             }
1914                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) {
1915                         ++SYNCTEX_CUR;
1916                         goto deeper;
1917             
1918                 } else if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
1919             _synctex_error("Unexpected end of nested sheet (3).");
1920             SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1921         }
1922     }
1923     _synctex_error("Unexpected end of nested sheet (4).");
1924     SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1925 }
1926
1927 /*  Used when parsing the synctex file.
1928  *  The sheet argument is a newly created sheet node that will hold the contents.
1929  *  Something is returned in case of error.
1930  */
1931 synctex_status_t _synctex_scan_sheet(synctex_scanner_t scanner, synctex_node_t sheet) {
1932         synctex_node_t parent = sheet;
1933         synctex_node_t child = NULL;
1934         synctex_node_t sibling = NULL;
1935         synctex_node_t box = sheet;
1936         int friend_index = 0;
1937         synctex_info_t * info = NULL;
1938         synctex_status_t status = 0;
1939         size_t available = 0;
1940         if ((NULL == scanner) || (NULL == sheet)) {
1941                 return SYNCTEX_STATUS_BAD_ARGUMENT;
1942         }
1943         /*  We MUST start with a box, so at this level, the unique possibility is '[', '(' or "}". */
1944 prepare_loop:
1945         if (SYNCTEX_CUR<SYNCTEX_END) {
1946                 if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_VBOX) {
1947 scan_vbox:
1948                         ++SYNCTEX_CUR;
1949                         if ((child = _synctex_new_vbox(scanner)) && (info = SYNCTEX_INFO(child))) {
1950 #               define SYNCTEX_DECODE_FAILED(WHAT) \
1951                                         (_synctex_decode_int(scanner,&(info[WHAT].INT))<SYNCTEX_STATUS_OK)
1952                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
1953                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
1954                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
1955                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
1956                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
1957                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
1958                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
1959                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
1960                                         _synctex_error("Bad vbox record.");
1961                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1962                                 }
1963                                 SYNCTEX_SET_CHILD(parent,child);
1964                                 parent = child;
1965                                 child = NULL;
1966                                 goto child_loop;/*  next created node will be a child */
1967                         } else {
1968                                 _synctex_error("Can't create vbox record.");
1969                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1970                         }
1971                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_HBOX) {
1972 scan_hbox:
1973                         ++SYNCTEX_CUR;
1974                         if ((child = _synctex_new_hbox(scanner)) && (info = SYNCTEX_INFO(child))) {
1975                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
1976                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
1977                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
1978                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
1979                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
1980                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
1981                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
1982                                                 || _synctex_setup_visible_box(child)<SYNCTEX_STATUS_OK
1983                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
1984                                         _synctex_error("Bad hbox record.");
1985                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1986                                 }
1987                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
1988                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
1989                                 SYNCTEX_SET_CHILD(parent,child);
1990                                 parent = child;
1991                                 child = NULL;
1992                                 goto child_loop;/*  next created node will be a child */
1993                         } else {
1994                                 _synctex_error("Can't create hbox record.");
1995                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
1996                         }
1997                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
1998 scan_teehs:
1999                         ++SYNCTEX_CUR;
2000                         if (NULL == parent || parent->class->type != synctex_node_type_sheet
2001                                         || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2002                                 _synctex_error("Unexpected end of sheet.");
2003                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2004                         }
2005                         SYNCTEX_RETURN(SYNCTEX_STATUS_OK);
2006                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) {
2007                         /*  Addendum to version 1.10 to manage nested sheets  */
2008                         ++SYNCTEX_CUR;
2009                         if (_synctex_scan_nested_sheet(scanner)<SYNCTEX_STATUS_OK) {
2010                                 _synctex_error("Unexpected nested sheet.");
2011                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2012                         }
2013                         goto prepare_loop;
2014                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
2015 scan_anchor:
2016                         ++SYNCTEX_CUR;
2017                         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2018                                 _synctex_error("Missing anchor.");
2019                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2020                         }
2021                         goto prepare_loop;
2022                 } else {
2023                         /*  _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
2024                         ++SYNCTEX_CUR;
2025                         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2026                                 _synctex_error("Unexpected end.");
2027                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2028                         }
2029                         goto prepare_loop;
2030                 }
2031         } else {
2032                 available = 1;
2033                 status = _synctex_buffer_get_available_size(scanner,&available);
2034                  if (status<SYNCTEX_STATUS_OK && available>0){
2035                         _synctex_error("Uncomplete sheet(0)");
2036                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2037                 } else {
2038                         goto prepare_loop;
2039                 }
2040         }
2041         _synctex_bail();
2042 /*  The child loop means that we go do one level, when we just created a box node,
2043  *  the next node created is a child of this box. */
2044 child_loop:
2045         if (SYNCTEX_CUR<SYNCTEX_END) {
2046                 if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_VBOX) {
2047                         goto scan_vbox;
2048                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_VBOX) {
2049 scan_xobv:
2050                         ++SYNCTEX_CUR;
2051                         if (NULL != parent && parent->class->type == synctex_node_type_vbox) {
2052                                 #define SYNCTEX_UPDATE_BOX_FRIEND(NODE)\
2053                                 friend_index = ((SYNCTEX_INFO(NODE))[SYNCTEX_TAG_IDX].INT+(SYNCTEX_INFO(NODE))[SYNCTEX_LINE_IDX].INT)%(scanner->number_of_lists);\
2054                                 SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\
2055                                 (scanner->lists_of_friends)[friend_index] = NODE;
2056                                 if (NULL == SYNCTEX_CHILD(parent)) {
2057                                         /*  only void boxes are friends */
2058                                         SYNCTEX_UPDATE_BOX_FRIEND(parent);
2059                                 }
2060                                 child = parent;
2061                                 parent = SYNCTEX_PARENT(child);
2062                         } else {
2063                                 _synctex_error("Unexpected end of vbox, ignored.");
2064                         }
2065                         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2066                                 _synctex_error("Uncomplete sheet.");
2067                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2068                         }
2069                         goto sibling_loop;
2070                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_HBOX) {
2071                         goto scan_hbox;
2072                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_HBOX) {
2073 scan_xobh:
2074                         ++SYNCTEX_CUR;
2075                         if ((parent) && parent->class->type == synctex_node_type_hbox) {
2076                                 if (NULL == child) {
2077                                         /*  Only boxes with no children are friends,
2078                                          *  boxes with children are indirectly friends through one of their descendants. */
2079                                         SYNCTEX_UPDATE_BOX_FRIEND(parent);
2080                                 }
2081                                 /*  setting the next horizontal box at the end ensures that a child is recorded before any of its ancestors. */
2082                                 SYNCTEX_SET_NEXT_HORIZ_BOX(box,parent);
2083                                 box = parent;
2084                                 child = parent;
2085                                 parent = SYNCTEX_PARENT(child);
2086                         } else {
2087                                 _synctex_error("Unexpected enf of hbox, ignored.");
2088                         }
2089                         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2090                                 _synctex_error("Uncomplete sheet.");
2091                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2092                         }
2093                         goto sibling_loop;
2094                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_VBOX) {
2095                         ++SYNCTEX_CUR;
2096                         if (NULL != (child = _synctex_new_void_vbox(scanner))
2097                                         && NULL != (info = SYNCTEX_INFO(child))) {
2098                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2099                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2100                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2101                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2102                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
2103                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
2104                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
2105                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2106                                         _synctex_error("Bad void vbox record.");
2107                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2108                                 }
2109                                 SYNCTEX_SET_CHILD(parent,child);
2110                                 #define SYNCTEX_UPDATE_FRIEND(NODE)\
2111                                 friend_index = (info[SYNCTEX_TAG_IDX].INT+info[SYNCTEX_LINE_IDX].INT)%(scanner->number_of_lists);\
2112                                 SYNCTEX_SET_FRIEND(NODE,(scanner->lists_of_friends)[friend_index]);\
2113                                 (scanner->lists_of_friends)[friend_index] = NODE;
2114                                 SYNCTEX_UPDATE_FRIEND(child);
2115                                 goto sibling_loop;
2116                         } else {
2117                                 _synctex_error("Can't create vbox record.");
2118                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2119                         }
2120                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_HBOX) {
2121                         ++SYNCTEX_CUR;
2122                         if (NULL != (child = _synctex_new_void_hbox(scanner))
2123                                         && NULL != (info = SYNCTEX_INFO(child))) {
2124                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2125                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2126                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2127                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2128                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
2129                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
2130                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
2131                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2132                                         _synctex_error("Bad void hbox record.");
2133                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2134                                 }
2135                                 SYNCTEX_SET_CHILD(parent,child);
2136                                 SYNCTEX_UPDATE_FRIEND(child);
2137                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2138                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
2139                                 goto sibling_loop;
2140                         } else {
2141                                 _synctex_error("Can't create void hbox record.");
2142                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2143                         }
2144                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_KERN) {
2145                         ++SYNCTEX_CUR;
2146                         if (NULL != (child = _synctex_new_kern(scanner))
2147                                         && NULL != (info = SYNCTEX_INFO(child))) {
2148                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2149                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2150                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2151                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2152                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
2153                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2154                                         _synctex_error("Bad kern record.");
2155                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2156                                 }
2157                                 SYNCTEX_SET_CHILD(parent,child);
2158                                 SYNCTEX_UPDATE_FRIEND(child);
2159                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2160                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)-SYNCTEX_WIDTH(child),SYNCTEX_VERT(child));
2161                                 goto sibling_loop;
2162                         } else {
2163                                 _synctex_error("Can't create kern record.");
2164                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2165                         }
2166                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_GLUE) {
2167                         ++SYNCTEX_CUR;
2168                         if (NULL != (child = _synctex_new_glue(scanner))
2169                                         && NULL != (info = SYNCTEX_INFO(child))) {
2170                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2171                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2172                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2173                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2174                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2175                                         _synctex_error("Bad glue record.");
2176                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2177                                 }
2178                                 SYNCTEX_SET_CHILD(parent,child);
2179                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2180                                 SYNCTEX_UPDATE_FRIEND(child);
2181                                 goto sibling_loop;
2182                         } else {
2183                                 _synctex_error("Can't create glue record.");
2184                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2185                         }
2186                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_MATH) {
2187                         ++SYNCTEX_CUR;
2188                         if (NULL != (child = _synctex_new_math(scanner))
2189                                         && NULL != (info = SYNCTEX_INFO(child))) {
2190                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2191                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2192                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2193                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2194                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2195                                         _synctex_error("Bad math record.");
2196                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2197                                 }
2198                                 SYNCTEX_SET_CHILD(parent,child);
2199                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2200                                 SYNCTEX_UPDATE_FRIEND(child);
2201                                 goto sibling_loop;
2202                         } else {
2203                                 _synctex_error("Can't create math record.");
2204                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2205                         }
2206                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BOUNDARY) {
2207                         ++SYNCTEX_CUR;
2208                         if (NULL != (child = _synctex_new_boundary(scanner))
2209                                         && NULL != (info = SYNCTEX_INFO(child))) {
2210                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2211                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2212                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2213                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2214                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2215                                         _synctex_error("Bad boundary record.");
2216                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2217                                 }
2218                                 SYNCTEX_SET_CHILD(parent,child);
2219                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2220                                 SYNCTEX_UPDATE_FRIEND(child);
2221                                 goto sibling_loop;
2222                         } else {
2223                                 _synctex_error("Can't create math record.");
2224                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2225                         }
2226                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
2227                         goto scan_teehs;
2228                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_SHEET) {
2229                         /*  Addendum to version 1.10 to manage nested sheets  */
2230                         ++SYNCTEX_CUR;
2231                         if (_synctex_scan_nested_sheet(scanner)<SYNCTEX_STATUS_OK) {
2232                                 _synctex_error("Unexpected nested sheet.");
2233                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2234                         }
2235                         goto child_loop;
2236                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
2237                         goto scan_anchor;
2238                 } else {
2239                         /*  _synctex_error("Ignored record %c\n",*SYNCTEX_CUR); */
2240                         ++SYNCTEX_CUR;
2241                         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2242                                 _synctex_error("Unexpected end.");
2243                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2244                         }
2245                         goto child_loop;
2246                 }
2247         } else {
2248                 available = 1;
2249                 status = _synctex_buffer_get_available_size(scanner,&available);
2250                  if (status<SYNCTEX_STATUS_OK && available>0){
2251                         _synctex_error("Uncomplete sheet(0)");
2252                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2253                 } else {
2254                         goto child_loop;
2255                 }
2256         }
2257         _synctex_bail();
2258 /*  The vertical loop means that we are on the same level, for example when we just ended a box.
2259  *  If a node is created now, it will be a sibling of the current node, sharing the same parent. */
2260 sibling_loop:
2261         if (SYNCTEX_CUR<SYNCTEX_END) {
2262                 if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_VBOX) {
2263                         ++SYNCTEX_CUR;
2264                         if (NULL != (sibling = _synctex_new_vbox(scanner))
2265                                         && NULL != (info = SYNCTEX_INFO(sibling))) {
2266                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2267                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2268                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2269                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2270                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
2271                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
2272                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
2273                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2274                                         _synctex_error("Bad vbox record (2).");
2275                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2276                                 }
2277                                 SYNCTEX_SET_SIBLING(child,sibling);
2278                                 parent = sibling;
2279                                 child = NULL;
2280                                 goto child_loop;
2281                         } else {
2282                                 _synctex_error("Can't create vbox record (2).");
2283                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2284                         }
2285                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_VBOX) {
2286                         goto scan_xobv;
2287                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BEGIN_HBOX) {
2288                         ++SYNCTEX_CUR;
2289                         if (NULL != (sibling = _synctex_new_hbox(scanner)) &&
2290                                         NULL != (info = SYNCTEX_INFO(sibling))) {
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_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
2296                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
2297                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
2298                                                 || _synctex_setup_visible_box(sibling)<SYNCTEX_STATUS_OK
2299                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2300                                         _synctex_error("Bad hbox record (2).");
2301                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2302                                 }
2303                                 SYNCTEX_SET_SIBLING(child,sibling);
2304                                 child = sibling;
2305                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2306                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
2307                                 parent = child;
2308                                 child = NULL;
2309                                 goto child_loop;
2310                         } else {
2311                                 _synctex_error("Can't create hbox record (2).");
2312                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2313                         }
2314                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_HBOX) {
2315                         goto scan_xobh;
2316                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_VBOX) {
2317                         ++SYNCTEX_CUR;
2318                         if (NULL != (sibling = _synctex_new_void_vbox(scanner)) &&
2319                                         NULL != (info = SYNCTEX_INFO(sibling))) {
2320                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2321                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2322                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2323                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2324                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
2325                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
2326                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
2327                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2328                                         _synctex_error("Bad void vbox record (2).");
2329                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2330                                 }
2331                                 SYNCTEX_SET_SIBLING(child,sibling);
2332                                 child = sibling;
2333                                 SYNCTEX_UPDATE_FRIEND(child);
2334                                 goto sibling_loop;
2335                         } else {
2336                                 _synctex_error("can't create void vbox record (2).");
2337                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2338                         }
2339                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_VOID_HBOX) {
2340                         ++SYNCTEX_CUR;
2341                         if (NULL != (sibling = _synctex_new_void_hbox(scanner)) &&
2342                                         NULL != (info = SYNCTEX_INFO(sibling))) {
2343                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2344                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2345                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2346                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2347                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
2348                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HEIGHT_IDX)
2349                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_DEPTH_IDX)
2350                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2351                                         _synctex_error("Bad void hbox record (2).");
2352                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2353                                 }
2354                                 SYNCTEX_SET_SIBLING(child,sibling);
2355                                 child = sibling;
2356                                 SYNCTEX_UPDATE_FRIEND(child);
2357                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2358                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)+SYNCTEX_ABS_WIDTH(child),SYNCTEX_VERT(child));
2359                                 goto sibling_loop;
2360                         } else {
2361                                 _synctex_error("can't create void hbox record (2).");
2362                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2363                         }
2364                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_KERN) {
2365                         ++SYNCTEX_CUR;
2366                         if (NULL != (sibling = _synctex_new_kern(scanner))
2367                                         && NULL != (info = SYNCTEX_INFO(sibling))) {
2368                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2369                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2370                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2371                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2372                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_WIDTH_IDX)
2373                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2374                                         _synctex_error("Bad kern record (2).");
2375                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2376                                 }
2377                                 SYNCTEX_SET_SIBLING(child,sibling);
2378                                 child = sibling;
2379                                 SYNCTEX_UPDATE_FRIEND(child);
2380                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2381                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child)-SYNCTEX_WIDTH(child),SYNCTEX_VERT(child));
2382                                 goto sibling_loop;
2383                         } else {
2384                                 _synctex_error("Can't create kern record (2).");
2385                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2386                         }
2387                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_GLUE) {
2388                         ++SYNCTEX_CUR;
2389                         if (NULL != (sibling = _synctex_new_glue(scanner))
2390                                         && NULL != (info = SYNCTEX_INFO(sibling))) {
2391                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2392                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2393                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2394                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2395                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2396                                         _synctex_error("Bad glue record (2).");
2397                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2398                                 }
2399                                 SYNCTEX_SET_SIBLING(child,sibling);
2400                                 child = sibling;
2401                                 SYNCTEX_UPDATE_FRIEND(child);
2402                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2403                                 goto sibling_loop;
2404                         } else {
2405                                 _synctex_error("Can't create glue record (2).");
2406                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2407                         }
2408                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_MATH) {
2409                         ++SYNCTEX_CUR;
2410                         if (NULL != (sibling = _synctex_new_math(scanner))
2411                                         && NULL != (info = SYNCTEX_INFO(sibling))) {
2412                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2413                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2414                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2415                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2416                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2417                                         _synctex_error("Bad math record (2).");
2418                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2419                                 }
2420                                 SYNCTEX_SET_SIBLING(child,sibling);
2421                                 child = sibling;
2422                                 SYNCTEX_UPDATE_FRIEND(child);
2423                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2424                                 goto sibling_loop;
2425                         } else {
2426                                 _synctex_error("Can't create math record (2).");
2427                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2428                         }
2429                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_BOUNDARY) {
2430                         ++SYNCTEX_CUR;
2431                         if (NULL != (sibling = _synctex_new_boundary(scanner))
2432                                         && NULL != (info = SYNCTEX_INFO(sibling))) {
2433                                 if (SYNCTEX_DECODE_FAILED(SYNCTEX_TAG_IDX)
2434                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_LINE_IDX)
2435                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_HORIZ_IDX)
2436                                                 || SYNCTEX_DECODE_FAILED(SYNCTEX_VERT_IDX)
2437                                                 || _synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2438                                         _synctex_error("Bad boundary record (2).");
2439                                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2440                                 }
2441                                 SYNCTEX_SET_SIBLING(child,sibling);
2442                                 child = sibling;
2443                                 SYNCTEX_UPDATE_FRIEND(child);
2444                                 _synctex_horiz_box_setup_visible(parent,SYNCTEX_HORIZ(child),SYNCTEX_VERT(child));
2445                                 goto sibling_loop;
2446                         } else {
2447                                 _synctex_error("Can't create boundary record (2).");
2448                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2449                         }
2450                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_END_SHEET) {
2451                         goto scan_teehs;
2452                 } else if (*SYNCTEX_CUR == SYNCTEX_CHAR_ANCHOR) {
2453                         ++SYNCTEX_CUR;
2454                         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2455                                 _synctex_error("Missing anchor (2).");
2456                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2457                         }
2458                         goto sibling_loop;
2459                 } else {
2460                         ++SYNCTEX_CUR;
2461                         /* _synctex_error("Ignored record %c(2)\n",*SYNCTEX_CUR); */
2462                         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2463                                 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2464                         }
2465                         goto sibling_loop;
2466                 }
2467         } else {
2468                 available = 1;
2469                 status = _synctex_buffer_get_available_size(scanner,&available);
2470                 if (status<SYNCTEX_STATUS_OK && available>0){
2471                         goto sibling_loop;
2472                 } else {
2473                         _synctex_error("Uncomplete sheet(2)");
2474                         SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR);
2475                 }
2476         }
2477 #   undef SYNCTEX_DECODE_FAILED
2478 }
2479
2480 /*  Used when parsing the synctex file
2481  */
2482 synctex_status_t _synctex_scan_content(synctex_scanner_t scanner) {
2483         synctex_node_t sheet = NULL;
2484         synctex_status_t status = 0;
2485         if (NULL == scanner) {
2486                 return SYNCTEX_STATUS_BAD_ARGUMENT;
2487         }
2488         /*  set up the lists of friends */
2489         if (NULL == scanner->lists_of_friends) {
2490                 scanner->number_of_lists = 1024;
2491                 scanner->lists_of_friends = (synctex_node_t *)_synctex_malloc(scanner->number_of_lists*sizeof(synctex_node_t));
2492                 if (NULL == scanner->lists_of_friends) {
2493                         _synctex_error("malloc:2");
2494                         return SYNCTEX_STATUS_ERROR;
2495                 }
2496         }
2497         /*  Find where this section starts */
2498 content_not_found:
2499         status = _synctex_match_string(scanner,"Content:");
2500         if (status<SYNCTEX_STATUS_EOF) {
2501                 return status;
2502         }
2503         if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
2504                 _synctex_error("Uncomplete Content.");
2505                 return SYNCTEX_STATUS_ERROR;
2506         }
2507         if (status == SYNCTEX_STATUS_NOT_OK) {
2508                 goto content_not_found;
2509         }
2510 next_sheet:
2511         if (*SYNCTEX_CUR != SYNCTEX_CHAR_BEGIN_SHEET) {
2512                 status = _synctex_scan_postamble(scanner);
2513                 if (status < SYNCTEX_STATUS_EOF) {
2514                         _synctex_error("Bad content.");
2515                         return status;
2516                 }
2517                 if (status<SYNCTEX_STATUS_OK) {
2518                         status = _synctex_next_line(scanner);
2519                         if (status < SYNCTEX_STATUS_OK) {
2520                                 _synctex_error("Bad content.");
2521                                 return status;
2522                         }
2523                         goto next_sheet;
2524                 }
2525                 return SYNCTEX_STATUS_OK;
2526         }
2527         ++SYNCTEX_CUR;
2528         /*  Create a new sheet node */
2529         sheet = _synctex_new_sheet(scanner);
2530         status = _synctex_decode_int(scanner,&(SYNCTEX_PAGE(sheet)));
2531         if (status<SYNCTEX_STATUS_OK) {
2532                 _synctex_error("Missing sheet number.");
2533 bail:
2534                 SYNCTEX_FREE(sheet);
2535                 return SYNCTEX_STATUS_ERROR;
2536         }
2537         status = _synctex_next_line(scanner);
2538         if (status<SYNCTEX_STATUS_OK) {
2539                 _synctex_error("Uncomplete file.");
2540                 goto bail;
2541         }
2542         status = _synctex_scan_sheet(scanner,sheet);
2543         if (status<SYNCTEX_STATUS_OK) {
2544                 _synctex_error("Bad sheet content.");
2545                 goto bail;
2546         }
2547         SYNCTEX_SET_SIBLING(sheet,scanner->sheet);
2548         scanner->sheet = sheet;
2549         sheet = NULL;
2550         /*  Now read the list of Inputs between 2 sheets. */
2551         do {
2552                 status = _synctex_scan_input(scanner);
2553                 if (status<SYNCTEX_STATUS_EOF) {
2554                         _synctex_error("Bad input section.");
2555                         goto bail;
2556                 }
2557         }
2558         while(status >= SYNCTEX_STATUS_OK);
2559         goto next_sheet;
2560 }
2561
2562 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);
2563
2564 /*  Where the synctex scanner is created. */
2565 synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) {
2566         gzFile file = NULL;
2567         char * synctex = NULL;
2568         synctex_scanner_t scanner = NULL;
2569         synctex_io_mode_t io_mode = 0;
2570         /*  Here we assume that int are smaller than void * */
2571         if (sizeof(int)>sizeof(void*)) {
2572                 _synctex_error("INTERNAL INCONSISTENCY: int's are unexpectedly bigger than pointers, bailing out.");
2573                 return NULL;
2574         }
2575         /*  We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */
2576         if (SYNCTEX_BUFFER_SIZE >= UINT_MAX) {
2577                 _synctex_error("SyncTeX BUG: Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (1)");
2578                 return NULL;
2579         }
2580         /*  for integers: */
2581         if (SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE) {
2582                 _synctex_error("SyncTeX BUG: Internal inconsistency, bad SYNCTEX_BUFFER_SIZE (2)");
2583                 return NULL;
2584         }
2585         /*  now open the synctex file */
2586         if (_synctex_open(output,build_directory,&synctex,&file,synctex_ADD_QUOTES,&io_mode) || !file) {
2587                 if (_synctex_open(output,build_directory,&synctex,&file,synctex_DONT_ADD_QUOTES,&io_mode) || !file) {
2588                         return NULL;
2589                 }
2590         }
2591         scanner = (synctex_scanner_t)_synctex_malloc(sizeof(_synctex_scanner_t));
2592         if (NULL == scanner) {
2593                 _synctex_error("SyncTeX: malloc problem");
2594                 free(synctex);
2595                 gzclose(file);
2596                 return NULL;
2597         }
2598         /*  make a private copy of output for the scanner */
2599         if (NULL == (scanner->output = (char *)malloc(strlen(output)+1))){
2600                 _synctex_error("!  synctex_scanner_new_with_output_file: Memory problem (2), scanner's output is not reliable.");
2601         } else if (scanner->output != strcpy(scanner->output,output)) {
2602                 _synctex_error("!  synctex_scanner_new_with_output_file: Copy problem, scanner's output is not reliable.");
2603         }
2604         scanner->synctex = synctex;/*  Now the scanner owns synctex */
2605         SYNCTEX_FILE = file;
2606         return parse? synctex_scanner_parse(scanner):scanner;
2607 }
2608
2609 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);
2610
2611 /*      This functions opens the file at the "output" given location.
2612  *  It manages the problem of quoted filenames that appear with pdftex and filenames containing the space character.
2613  *  In TeXLive 2008, the synctex file created with pdftex did contain unexpected quotes.
2614  *      This function will remove them if possible.
2615  *  All the reference arguments will take a value on return. They must be non NULL.
2616  *      0 on success, non 0 on error. */
2617 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) {
2618         if (synctex_name_ref && file_ref && io_mode_ref) {
2619         /*  1 local variables that uses dynamic memory */
2620         char * synctex_name = NULL;
2621         gzFile the_file = NULL;
2622         char * quoteless_synctex_name = NULL;
2623                 size_t size = 0;
2624         synctex_io_mode_t io_mode = *io_mode_ref;
2625                 const char * mode = _synctex_get_io_mode_name(io_mode);
2626                 /*  now create the synctex file name */
2627                 size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1;
2628                 synctex_name = (char *)malloc(size);
2629                 if (NULL == synctex_name) {
2630                         _synctex_error("!  __synctex_open: Memory problem (1)\n");
2631                         return 1;
2632                 }
2633                 /*  we have reserved for synctex enough memory to copy output (including its 2 eventual quotes), both suffices,
2634                  *  including the terminating character. size is free now. */
2635                 if (synctex_name != strcpy(synctex_name,output)) {
2636                         _synctex_error("!  __synctex_open: Copy problem\n");
2637 return_on_error:
2638                         free(synctex_name);
2639                         free(quoteless_synctex_name);
2640                         return 2;
2641                 }
2642                 /*  remove the last path extension if any */
2643                 _synctex_strip_last_path_extension(synctex_name);
2644                 if (!strlen(synctex_name)) {
2645                         goto return_on_error;           
2646                 }
2647                 /*  now insert quotes. */
2648                 if (add_quotes) {
2649                         char * quoted = NULL;
2650                         if (_synctex_copy_with_quoting_last_path_component(synctex_name,&quoted,size) || (NULL == quoted)) {
2651                                 /*      There was an error or quoting does not make sense: */
2652                                 goto return_on_error;
2653                         }
2654                         quoteless_synctex_name = synctex_name;
2655                         synctex_name = quoted;
2656                 }
2657                 /*      Now add to synctex_name the first path extension. */
2658                 if (synctex_name != strcat(synctex_name,synctex_suffix)){
2659                         _synctex_error("!  __synctex_open: Concatenation problem (can't add suffix '%s')\n",synctex_suffix);
2660                         goto return_on_error;
2661                 }
2662                 /*      Add to quoteless_synctex_name as well, if relevant. */
2663                 if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix))){
2664                         free(quoteless_synctex_name);
2665                         quoteless_synctex_name = NULL;
2666                 }
2667                 if (NULL == (the_file = gzopen(synctex_name,mode))) {
2668                         /*  Could not open this file */
2669                         if (errno != ENOENT) {
2670                                 /*  The file does exist, this is a lower level error, I can't do anything. */
2671                                 _synctex_error("SyncTeX: could not open %s, error %i\n",synctex_name,errno);
2672                                 goto return_on_error;
2673                         }
2674                         /*  Apparently, there is no uncompressed synctex file. Try the compressed version */
2675                         if (synctex_name != strcat(synctex_name,synctex_suffix_gz)){
2676                                 _synctex_error("!  __synctex_open: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz);
2677                                 goto return_on_error;
2678                         }
2679                         io_mode |= synctex_io_gz_mask;
2680                         mode = _synctex_get_io_mode_name(io_mode); /* the file is a compressed and is a binary file, this caused errors on Windows */
2681                         /*      Add the suffix to the quoteless_synctex_name as well. */
2682                         if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix_gz))){
2683                                 free(quoteless_synctex_name);
2684                                 quoteless_synctex_name = NULL;
2685                         }
2686                         if (NULL == (the_file = gzopen(synctex_name,mode))) {
2687                                 /*  Could not open this file */
2688                                 if (errno != ENOENT) {
2689                                         /*  The file does exist, this is a lower level error, I can't do anything. */
2690                                         _synctex_error("SyncTeX: could not open %s, error %i\n",synctex_name,errno);
2691                                 }
2692                                 goto return_on_error;
2693                         }
2694                 }
2695                 /*      At this point, the file is properly open.
2696                  *  If we are in the add_quotes mode, we change the file name by removing the quotes. */
2697                 if (quoteless_synctex_name) {
2698                         gzclose(the_file);
2699                         if (rename(synctex_name,quoteless_synctex_name)) {
2700                                 _synctex_error("SyncTeX: could not rename %s to %s, error %i\n",synctex_name,quoteless_synctex_name,errno);
2701                                 /*      We could not rename, reopen the file with the quoted name. */
2702                                 if (NULL == (the_file = gzopen(synctex_name,mode))) {
2703                                         /*  No luck, could not re open this file, something has happened meanwhile */
2704                                         if (errno != ENOENT) {
2705                                                 /*  The file does not exist any more, it has certainly be removed somehow
2706                          *  this is a lower level error, I can't do anything. */
2707                                                 _synctex_error("SyncTeX: could not open again %s, error %i\n",synctex_name,errno);
2708                                         }
2709                                         goto return_on_error;
2710                                 }
2711                         } else {
2712                 /*  The file has been successfully renamed */
2713                                 if (NULL == (the_file = gzopen(quoteless_synctex_name,mode))) {
2714                                         /*  Could not open this file */
2715                                         if (errno != ENOENT) {
2716                                                 /*  The file does exist, this is a lower level error, I can't do anything. */
2717                                                 _synctex_error("SyncTeX: could not open renamed %s, error %i\n",quoteless_synctex_name,errno);
2718                                         }
2719                                         goto return_on_error;
2720                                 }
2721                                 /*  The quote free file name should replace the old one:*/
2722                                 free(synctex_name);
2723                                 synctex_name = quoteless_synctex_name;
2724                                 quoteless_synctex_name = NULL;
2725                         }
2726                 }
2727         /*  The operation is successfull, return the arguments by value.    */
2728         * file_ref = the_file;
2729         * io_mode_ref = io_mode;
2730         * synctex_name_ref = synctex_name;
2731                 return 0;
2732         }
2733         return 3;       /*      Bad parameter.  */
2734 }
2735
2736 /*      Opens the ouput file, taking into account the eventual build_directory.
2737  *      0 on success, non 0 on error. */
2738 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) {
2739 #       define synctex_name (*synctex_name_ref)
2740 #       define the_file (*file_ref)
2741         int result = __synctex_open(output,synctex_name_ref,file_ref,add_quotes,io_mode_ref);
2742         if ((result || !*file_ref) && build_directory && strlen(build_directory)) {
2743                 char * build_output;
2744                 const char *lpc;
2745                 size_t size;
2746                 synctex_bool_t is_absolute;
2747                 build_output = NULL;
2748                 lpc = _synctex_last_path_component(output);
2749                 size = strlen(build_directory)+strlen(lpc)+2;   /*  One for the '/' and one for the '\0'.   */
2750                 is_absolute = _synctex_path_is_absolute(build_directory);
2751                 if (!is_absolute) {
2752                         size += strlen(output);
2753                 }
2754                 if ((build_output = (char *)malloc(size))) {
2755                         if (is_absolute) {
2756                                 build_output[0] = '\0';
2757                         } else {
2758                                 if (build_output != strcpy(build_output,output)) {
2759                                         return -4;
2760                                 }
2761                                 build_output[lpc-output]='\0';
2762                         }
2763                         if (build_output == strcat(build_output,build_directory)) {
2764                                 /*      Append a path separator if necessary. */
2765                                 if (!SYNCTEX_IS_PATH_SEPARATOR(build_output[strlen(build_directory)-1])) {
2766                                         if (build_output != strcat(build_output,"/")) {
2767                                                 return -2;
2768                                         }
2769                                 }
2770                                 /*      Append the last path component of the output. */
2771                                 if (build_output != strcat(build_output,lpc)) {
2772                                         return -3;
2773                                 }
2774                                 return __synctex_open(build_output,synctex_name_ref,file_ref,add_quotes,io_mode_ref);
2775                         }
2776                 }
2777                 return -1;
2778         }
2779         return result;
2780 #       undef synctex_name
2781 #       undef the_file
2782 }
2783
2784 /*  The scanner destructor
2785  */
2786 void synctex_scanner_free(synctex_scanner_t scanner) {
2787         if (NULL == scanner) {
2788                 return;
2789         }
2790         if (SYNCTEX_FILE) {
2791                 gzclose(SYNCTEX_FILE);
2792                 SYNCTEX_FILE = NULL;
2793         }
2794         SYNCTEX_FREE(scanner->sheet);
2795         SYNCTEX_FREE(scanner->input);
2796         free(SYNCTEX_START);
2797         free(scanner->output_fmt);
2798         free(scanner->output);
2799         free(scanner->synctex);
2800         free(scanner->lists_of_friends);
2801         free(scanner);
2802 }
2803
2804 /*  Where the synctex scanner parses the contents of the file. */
2805 synctex_scanner_t synctex_scanner_parse(synctex_scanner_t scanner) {
2806         synctex_status_t status = 0;
2807         if (!scanner || scanner->flags.has_parsed) {
2808                 return scanner;
2809         }
2810         scanner->flags.has_parsed=1;
2811         scanner->pre_magnification = 1000;
2812         scanner->pre_unit = 8192;
2813         scanner->pre_x_offset = scanner->pre_y_offset = 578;
2814         /*  initialize the offset with a fake unprobable value,
2815          *  If there is a post scriptum section, this value will be overriden by the real life value */
2816         scanner->x_offset = scanner->y_offset = 6.027e23f;
2817         scanner->class[synctex_node_type_sheet] = synctex_class_sheet;
2818         scanner->class[synctex_node_type_input] = synctex_class_input;
2819         (scanner->class[synctex_node_type_input]).scanner = scanner;
2820         (scanner->class[synctex_node_type_sheet]).scanner = scanner;
2821         scanner->class[synctex_node_type_vbox] = synctex_class_vbox;
2822         (scanner->class[synctex_node_type_vbox]).scanner = scanner;
2823         scanner->class[synctex_node_type_void_vbox] = synctex_class_void_vbox;
2824         (scanner->class[synctex_node_type_void_vbox]).scanner = scanner;
2825         scanner->class[synctex_node_type_hbox] = synctex_class_hbox;
2826         (scanner->class[synctex_node_type_hbox]).scanner = scanner;
2827         scanner->class[synctex_node_type_void_hbox] = synctex_class_void_hbox;
2828         (scanner->class[synctex_node_type_void_hbox]).scanner = scanner;
2829         scanner->class[synctex_node_type_kern] = synctex_class_kern;
2830         (scanner->class[synctex_node_type_kern]).scanner = scanner;
2831         scanner->class[synctex_node_type_glue] = synctex_class_glue;
2832         (scanner->class[synctex_node_type_glue]).scanner = scanner;
2833         scanner->class[synctex_node_type_math] = synctex_class_math;
2834         (scanner->class[synctex_node_type_math]).scanner = scanner;
2835         scanner->class[synctex_node_type_boundary] = synctex_class_boundary;
2836         (scanner->class[synctex_node_type_boundary]).scanner = scanner;
2837         SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE+1); /*  one more character for null termination */
2838         if (NULL == SYNCTEX_START) {
2839                 _synctex_error("SyncTeX: malloc error");
2840                 synctex_scanner_free(scanner);
2841                 return NULL;
2842         }
2843         SYNCTEX_END = SYNCTEX_START+SYNCTEX_BUFFER_SIZE;
2844         /*  SYNCTEX_END always points to a null terminating character.
2845          *  Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1.
2846          *  At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */
2847         *SYNCTEX_END = '\0';
2848         SYNCTEX_CUR = SYNCTEX_END;
2849         status = _synctex_scan_preamble(scanner);
2850         if (status<SYNCTEX_STATUS_OK) {
2851                 _synctex_error("SyncTeX Error: Bad preamble\n");
2852 bailey:
2853                 synctex_scanner_free(scanner);
2854                 return NULL;
2855         }
2856         status = _synctex_scan_content(scanner);
2857         if (status<SYNCTEX_STATUS_OK) {
2858                 _synctex_error("SyncTeX Error: Bad content\n");
2859                 goto bailey;
2860         }
2861         /*  Everything is finished, free the buffer, close the file */
2862         free((void *)SYNCTEX_START);
2863         SYNCTEX_START = SYNCTEX_CUR = SYNCTEX_END = NULL;
2864         gzclose(SYNCTEX_FILE);
2865         SYNCTEX_FILE = NULL;
2866         /*  Final tuning: set the default values for various parameters */
2867         /*  1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp
2868          * 1 pt = 65536 sp */
2869         if (scanner->pre_unit<=0) {
2870                 scanner->pre_unit = 8192;
2871         }
2872         if (scanner->pre_magnification<=0) {
2873                 scanner->pre_magnification = 1000;
2874         }
2875         if (scanner->unit <= 0) {
2876                 /*  no post magnification */
2877                 scanner->unit = scanner->pre_unit / 65781.76;/*  65781.76 or 65536.0*/
2878         } else {
2879                 /*  post magnification */
2880                 scanner->unit *= scanner->pre_unit / 65781.76;
2881         }
2882         scanner->unit *= scanner->pre_magnification / 1000.0;
2883         if (scanner->x_offset > 6e23) {
2884                 /*  no post offset */
2885                 scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76);
2886                 scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76);
2887         } else {
2888                 /*  post offset */
2889                 scanner->x_offset /= 65781.76f;
2890                 scanner->y_offset /= 65781.76f;
2891         }
2892         return scanner;
2893         #undef SYNCTEX_FILE
2894 }
2895
2896 /*  Scanner accessors.
2897  */
2898 int synctex_scanner_pre_x_offset(synctex_scanner_t scanner){
2899         return scanner?scanner->pre_x_offset:0;
2900 }
2901 int synctex_scanner_pre_y_offset(synctex_scanner_t scanner){
2902         return scanner?scanner->pre_y_offset:0;
2903 }
2904 int synctex_scanner_x_offset(synctex_scanner_t scanner){
2905         return scanner?scanner->x_offset:0;
2906 }
2907 int synctex_scanner_y_offset(synctex_scanner_t scanner){
2908         return scanner?scanner->y_offset:0;
2909 }
2910 float synctex_scanner_magnification(synctex_scanner_t scanner){
2911         return scanner?scanner->unit:1;
2912 }
2913 void synctex_scanner_display(synctex_scanner_t scanner) {
2914         if (NULL == scanner) {
2915                 return;
2916         }
2917         printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n",scanner->output,scanner->output_fmt,scanner->version);
2918         printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n",scanner->pre_unit,scanner->pre_x_offset,scanner->pre_y_offset);
2919         printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n",
2920                 scanner->count,scanner->unit,scanner->x_offset,scanner->y_offset);
2921         printf("The input:\n");
2922         SYNCTEX_DISPLAY(scanner->input);
2923         if (scanner->count<1000) {
2924                 printf("The sheets:\n");
2925                 SYNCTEX_DISPLAY(scanner->sheet);
2926                 printf("The friends:\n");
2927                 if (scanner->lists_of_friends) {
2928                         int i = scanner->number_of_lists;
2929                         synctex_node_t node;
2930                         while(i--) {
2931                                 printf("Friend index:%i\n",i);
2932                                 node = (scanner->lists_of_friends)[i];
2933                                 while(node) {
2934                                         printf("%s:%i,%i\n",
2935                                                 synctex_node_isa(node),
2936                                                 SYNCTEX_TAG(node),
2937                                                 SYNCTEX_LINE(node)
2938                                         );
2939                                         node = SYNCTEX_FRIEND(node);
2940                                 }
2941                         }
2942                 }
2943         } else {
2944                 printf("SyncTeX Warning: Too many objects\n");
2945         }
2946 }
2947 /*  Public*/
2948 const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag) {
2949         synctex_node_t input = NULL;
2950         if (NULL == scanner) {
2951                 return NULL;
2952         }
2953         input = scanner->input;
2954         do {
2955                 if (tag == SYNCTEX_TAG(input)) {
2956                         return (SYNCTEX_NAME(input));
2957                 }
2958         } while((input = SYNCTEX_SIBLING(input)) != NULL);
2959         return NULL;
2960 }
2961
2962 int _synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name);
2963 int _synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name) {
2964         synctex_node_t input = NULL;
2965         if (NULL == scanner) {
2966                 return 0;
2967         }
2968         input = scanner->input;
2969         do {
2970                 if (_synctex_is_equivalent_file_name(name,(SYNCTEX_NAME(input)))) {
2971                         return SYNCTEX_TAG(input);
2972                 }
2973         } while((input = SYNCTEX_SIBLING(input)) != NULL);
2974         return 0;
2975 }
2976
2977 int synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name) {
2978         size_t char_index = strlen(name);
2979         if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) {
2980                 /*  the name is not void */
2981                 char_index -= 1;
2982                 if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) {
2983                         /*  the last character of name is not a path separator */
2984                         int result = _synctex_scanner_get_tag(scanner,name);
2985                         if (result) {
2986                                 return result;
2987                         } else {
2988                                 /*  the given name was not the one known by TeX
2989                                  *  try a name relative to the enclosing directory of the scanner->output file */
2990                                 const char * relative = name;
2991                                 const char * ptr = scanner->output;
2992                                 while((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr))
2993                                 {
2994                                         relative += 1;
2995                                         ptr += 1;
2996                                 }
2997                                 /*  Find the last path separator before relative */
2998                                 while(relative > name) {
2999                                         if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) {
3000                                                 break;
3001                                         }
3002                                         relative -= 1;
3003                                 }
3004                                 if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) {
3005                                         return result;
3006                                 }
3007                                 if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) {
3008                                         /*  No tag found for the given absolute name,
3009                                          *  Try each relative path starting from the shortest one */
3010                                         while(0<char_index) {
3011                                                 char_index -= 1;
3012                                                 if (SYNCTEX_IS_PATH_SEPARATOR(name[char_index])
3013                                                                 && (result = _synctex_scanner_get_tag(scanner,name+char_index+1))) {
3014                                                         return result;
3015                                                 }
3016                                         }
3017                                 }
3018                         }
3019                         return result;
3020                 }
3021         }
3022         return 0;
3023 }
3024 synctex_node_t synctex_scanner_input(synctex_scanner_t scanner) {
3025         return scanner?scanner->input:NULL;
3026 }
3027 const char * synctex_scanner_get_output_fmt(synctex_scanner_t scanner) {
3028         return NULL != scanner && scanner->output_fmt?scanner->output_fmt:"";
3029 }
3030 const char * synctex_scanner_get_output(synctex_scanner_t scanner) {
3031         return NULL != scanner && scanner->output?scanner->output:"";
3032 }
3033 const char * synctex_scanner_get_synctex(synctex_scanner_t scanner) {
3034         return NULL != scanner && scanner->synctex?scanner->synctex:"";
3035 }
3036 #       ifdef SYNCTEX_NOTHING
3037 #       pragma mark -
3038 #       pragma mark Public node attributes
3039 #   endif
3040 int synctex_node_h(synctex_node_t node){
3041         if (!node) {
3042                 return 0;
3043         }
3044         return SYNCTEX_HORIZ(node);
3045 }
3046 int synctex_node_v(synctex_node_t node){
3047         if (!node) {
3048                 return 0;
3049         }
3050         return SYNCTEX_VERT(node);
3051 }
3052 int synctex_node_width(synctex_node_t node){
3053         if (!node) {
3054                 return 0;
3055         }
3056         return SYNCTEX_WIDTH(node);
3057 }
3058 int synctex_node_box_h(synctex_node_t node){
3059         if (!node) {
3060                 return 0;
3061         }
3062         if (SYNCTEX_IS_BOX(node)) {
3063 result:
3064                 return SYNCTEX_HORIZ(node);
3065         }
3066         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3067                 goto result;
3068         }
3069         return 0;
3070 }
3071 int synctex_node_box_v(synctex_node_t node){
3072         if (!node) {
3073                 return 0;
3074         }
3075         if (SYNCTEX_IS_BOX(node)) {
3076 result:
3077                 return SYNCTEX_VERT(node);
3078         }
3079         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3080                 goto result;
3081         }
3082         return 0;
3083 }
3084 int synctex_node_box_width(synctex_node_t node){
3085         if (!node) {
3086                 return 0;
3087         }
3088         if (SYNCTEX_IS_BOX(node)) {
3089 result:
3090                 return SYNCTEX_WIDTH(node);
3091         }
3092         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3093                 goto result;
3094         }
3095         return 0;
3096 }
3097 int synctex_node_box_height(synctex_node_t node){
3098         if (!node) {
3099                 return 0;
3100         }
3101         if (SYNCTEX_IS_BOX(node)) {
3102 result:
3103                 return SYNCTEX_HEIGHT(node);
3104         }
3105         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3106                 goto result;
3107         }
3108         return 0;
3109 }
3110 int synctex_node_box_depth(synctex_node_t node){
3111         if (!node) {
3112                 return 0;
3113         }
3114         if (SYNCTEX_IS_BOX(node)) {
3115 result:
3116                 return SYNCTEX_DEPTH(node);
3117         }
3118         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3119                 goto result;
3120         }
3121         return 0;
3122 }
3123 #       ifdef SYNCTEX_NOTHING
3124 #       pragma mark -
3125 #       pragma mark Public node visible attributes
3126 #   endif
3127 float synctex_node_visible_h(synctex_node_t node){
3128         if (!node) {
3129                 return 0;
3130         }
3131         return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset;
3132 }
3133 float synctex_node_visible_v(synctex_node_t node){
3134         if (!node) {
3135                 return 0;
3136         }
3137         return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset;
3138 }
3139 float synctex_node_visible_width(synctex_node_t node){
3140         if (!node) {
3141                 return 0;
3142         }
3143         return SYNCTEX_WIDTH(node)*node->class->scanner->unit;
3144 }
3145 float synctex_node_box_visible_h(synctex_node_t node){
3146         if (!node) {
3147                 return 0;
3148         }
3149         switch(node->class->type) {
3150                 case synctex_node_type_vbox:
3151                 case synctex_node_type_void_vbox:
3152                 case synctex_node_type_void_hbox:
3153                         return SYNCTEX_HORIZ(node)*node->class->scanner->unit+node->class->scanner->x_offset;
3154                 case synctex_node_type_hbox:
3155 result:
3156                         return SYNCTEX_HORIZ_V(node)*node->class->scanner->unit+node->class->scanner->x_offset;
3157         }
3158         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3159                 goto result;
3160         }
3161         return 0;
3162 }
3163 float synctex_node_box_visible_v(synctex_node_t node){
3164         if (!node) {
3165                 return 0;
3166         }
3167         switch(node->class->type) {
3168                 case synctex_node_type_vbox:
3169                 case synctex_node_type_void_vbox:
3170                 case synctex_node_type_void_hbox:
3171                         return SYNCTEX_VERT(node)*node->class->scanner->unit+node->class->scanner->y_offset;
3172                 case synctex_node_type_hbox:
3173 result:
3174                         return SYNCTEX_VERT_V(node)*node->class->scanner->unit+node->class->scanner->y_offset;
3175         }
3176         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3177                 goto result;
3178         }
3179         return 0;
3180 }
3181 float synctex_node_box_visible_width(synctex_node_t node){
3182         if (!node) {
3183                 return 0;
3184         }
3185         switch(node->class->type) {
3186                 case synctex_node_type_vbox:
3187                 case synctex_node_type_void_vbox:
3188                 case synctex_node_type_void_hbox:
3189                         return SYNCTEX_WIDTH(node)*node->class->scanner->unit;
3190                 case synctex_node_type_hbox:
3191 result:
3192                         return SYNCTEX_WIDTH_V(node)*node->class->scanner->unit;
3193         }
3194         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3195                 goto result;
3196         }
3197         return 0;
3198 }
3199 float synctex_node_box_visible_height(synctex_node_t node){
3200         if (!node) {
3201                 return 0;
3202         }
3203         switch(node->class->type) {
3204                 case synctex_node_type_vbox:
3205                 case synctex_node_type_void_vbox:
3206                 case synctex_node_type_void_hbox:
3207                         return SYNCTEX_HEIGHT(node)*node->class->scanner->unit;
3208                 case synctex_node_type_hbox:
3209 result:
3210                         return SYNCTEX_HEIGHT_V(node)*node->class->scanner->unit;
3211         }
3212         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3213                 goto result;
3214         }
3215         return 0;
3216 }
3217 float synctex_node_box_visible_depth(synctex_node_t node){
3218         if (!node) {
3219                 return 0;
3220         }
3221         switch(node->class->type) {
3222                 case synctex_node_type_vbox:
3223                 case synctex_node_type_void_vbox:
3224                 case synctex_node_type_void_hbox:
3225                         return SYNCTEX_DEPTH(node)*node->class->scanner->unit;
3226                 case synctex_node_type_hbox:
3227 result:
3228                         return SYNCTEX_DEPTH_V(node)*node->class->scanner->unit;
3229         }
3230         if ((node = SYNCTEX_PARENT(node)) && (node->class->type != synctex_node_type_sheet)) {
3231                 goto result;
3232         }
3233         return 0;
3234 }
3235 #       ifdef SYNCTEX_NOTHING
3236 #       pragma mark -
3237 #       pragma mark Other public node attributes
3238 #   endif
3239
3240 int synctex_node_page(synctex_node_t node){
3241         synctex_node_t parent = NULL;
3242         if (!node) {
3243                 return -1;
3244         }
3245         parent = SYNCTEX_PARENT(node);
3246         while(parent) {
3247                 node = parent;
3248                 parent = SYNCTEX_PARENT(node);
3249         }
3250         if (node->class->type == synctex_node_type_sheet) {
3251                 return SYNCTEX_PAGE(node);
3252         }
3253         return -1;
3254 }
3255 int synctex_node_tag(synctex_node_t node) {
3256         return node?SYNCTEX_TAG(node):-1;
3257 }
3258 int synctex_node_line(synctex_node_t node) {
3259         return node?SYNCTEX_LINE(node):-1;
3260 }
3261 int synctex_node_column(synctex_node_t node) {
3262 #       ifdef __DARWIN_UNIX03
3263 #       pragma unused(node)
3264 #   endif
3265         return -1;
3266 }
3267 #       ifdef SYNCTEX_NOTHING
3268 #       pragma mark -
3269 #       pragma mark Sheet
3270 #   endif
3271
3272 synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page) {
3273         if (scanner) {
3274                 synctex_node_t sheet = scanner->sheet;
3275                 while(sheet) {
3276                         if (page == SYNCTEX_PAGE(sheet)) {
3277                                 return SYNCTEX_CHILD(sheet);
3278                         }
3279                         sheet = SYNCTEX_SIBLING(sheet);
3280                 }
3281         }
3282         return NULL;
3283 }
3284
3285 #       ifdef SYNCTEX_NOTHING
3286 #       pragma mark -
3287 #       pragma mark Query
3288 #   endif
3289
3290 int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column) {
3291 #       ifdef __DARWIN_UNIX03
3292 #       pragma unused(column)
3293 #   endif
3294         int tag = synctex_scanner_get_tag(scanner,name);
3295         size_t size = 0;
3296         int friend_index = 0;
3297         int max_line = 0;
3298         synctex_node_t node = NULL;
3299         if (tag == 0) {
3300                 printf("SyncTeX Warning: No tag for %s\n",name);
3301                 return -1;
3302         }
3303         free(SYNCTEX_START);
3304         SYNCTEX_CUR = SYNCTEX_END = SYNCTEX_START = NULL;
3305         max_line = line < INT_MAX-scanner->number_of_lists ? line+scanner->number_of_lists:INT_MAX;
3306         while(line<max_line) {
3307                 /*  This loop will only be performed once for advanced viewers */
3308                 friend_index = (tag+line)%(scanner->number_of_lists);
3309                 if ((node = (scanner->lists_of_friends)[friend_index])) {
3310                         do {
3311                                 if ((synctex_node_type(node)>=synctex_node_type_boundary)
3312                                         && (tag == SYNCTEX_TAG(node))
3313                                                 && (line == SYNCTEX_LINE(node))) {
3314                                         if (SYNCTEX_CUR == SYNCTEX_END) {
3315                                                 size += 16;
3316                                                 SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *));
3317                                                 SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START;
3318                                                 SYNCTEX_START = SYNCTEX_END;
3319                                                 SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *);
3320                                         }                       
3321                                         *(synctex_node_t *)SYNCTEX_CUR = node;
3322                                         SYNCTEX_CUR += sizeof(synctex_node_t);
3323                                 }
3324                         } while((node = SYNCTEX_FRIEND(node)));
3325                         if (SYNCTEX_START == NULL) {
3326                                 /*  We did not find any matching boundary, retry with glue or kern */
3327                                 node = (scanner->lists_of_friends)[friend_index];/*  no need to test it again, already done */
3328                                 do {
3329                                         if ((synctex_node_type(node)>=synctex_node_type_kern)
3330                                                 && (tag == SYNCTEX_TAG(node))
3331                                                         && (line == SYNCTEX_LINE(node))) {
3332                                                 if (SYNCTEX_CUR == SYNCTEX_END) {
3333                                                         size += 16;
3334                                                         SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *));
3335                                                         SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START;
3336                                                         SYNCTEX_START = SYNCTEX_END;
3337                                                         SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *);
3338                                                 }                       
3339                                                 *(synctex_node_t *)SYNCTEX_CUR = node;
3340                                                 SYNCTEX_CUR += sizeof(synctex_node_t);
3341                                         }
3342                                 } while((node = SYNCTEX_FRIEND(node)));
3343                                 if (SYNCTEX_START == NULL) {
3344                                         /*  We did not find any matching glue or kern, retry with boxes */
3345                                         node = (scanner->lists_of_friends)[friend_index];/*  no need to test it again, already done */
3346                                         do {
3347                                                 if ((tag == SYNCTEX_TAG(node))
3348                                                                 && (line == SYNCTEX_LINE(node))) {
3349                                                         if (SYNCTEX_CUR == SYNCTEX_END) {
3350                                                                 size += 16;
3351                                                                 SYNCTEX_END = realloc(SYNCTEX_START,size*sizeof(synctex_node_t *));
3352                                                                 SYNCTEX_CUR += SYNCTEX_END - SYNCTEX_START;
3353                                                                 SYNCTEX_START = SYNCTEX_END;
3354                                                                 SYNCTEX_END = SYNCTEX_START + size*sizeof(synctex_node_t *);
3355                                                         }                       
3356                                                         *(synctex_node_t *)SYNCTEX_CUR = node;
3357                                                         SYNCTEX_CUR += sizeof(synctex_node_t);
3358                                                 }
3359                                         } while((node = SYNCTEX_FRIEND(node)));
3360                                 }
3361                         }
3362                         SYNCTEX_END = SYNCTEX_CUR;
3363                         /*  Now reverse the order to have nodes in display order, and keep just a few nodes */
3364                         if ((SYNCTEX_START) && (SYNCTEX_END))
3365                         {
3366                                 synctex_node_t * start_ref = (synctex_node_t *)SYNCTEX_START;
3367                                 synctex_node_t * end_ref   = (synctex_node_t *)SYNCTEX_END;
3368                                 end_ref -= 1;
3369                                 while(start_ref < end_ref) {
3370                                         node = *start_ref;
3371                                         *start_ref = *end_ref;
3372                                         *end_ref = node;
3373                                         start_ref += 1;
3374                                         end_ref -= 1;
3375                                 }
3376                                 /*  Basically, we keep the first node for each parent.
3377                                  *  More precisely, we keep only nodes that are not descendants of
3378                                  *  their predecessor's parent. */
3379                                 start_ref = (synctex_node_t *)SYNCTEX_START;
3380                                 end_ref   = (synctex_node_t *)SYNCTEX_START;
3381                 next_end:
3382                                 end_ref += 1; /*  we allways have start_ref<= end_ref*/
3383                                 if (end_ref < (synctex_node_t *)SYNCTEX_END) {
3384                                         node = *end_ref;
3385                                         while((node = SYNCTEX_PARENT(node))) {
3386                                                 if (SYNCTEX_PARENT(*start_ref) == node) {
3387                                                         goto next_end;
3388                                                 }
3389                                         }
3390                                         start_ref += 1;
3391                                         *start_ref = *end_ref;
3392                                         goto next_end;
3393                                 }
3394                                 start_ref += 1;
3395                                 SYNCTEX_END = (char *)start_ref;
3396                 return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);// added on behalf Jan Sundermeyer
3397             }
3398                         SYNCTEX_CUR = NULL;
3399                         // return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); removed on behalf Jan Sundermeyer
3400                 }
3401 #       if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__)
3402                 break;
3403 #       else
3404                 ++line;
3405 #       endif
3406         }
3407         return 0;
3408 }
3409
3410 synctex_node_t synctex_next_result(synctex_scanner_t scanner) {
3411         if (NULL == SYNCTEX_CUR) {
3412                 SYNCTEX_CUR = SYNCTEX_START;
3413         } else {
3414                 SYNCTEX_CUR+=sizeof(synctex_node_t);
3415         }
3416         if (SYNCTEX_CUR<SYNCTEX_END) {
3417                 return *(synctex_node_t*)SYNCTEX_CUR;
3418         } else {
3419                 return NULL;
3420         }
3421 }
3422
3423 /*  This struct records a point in TeX coordinates.*/
3424 typedef struct {
3425         int h;
3426         int v;
3427 } synctex_point_t;
3428
3429 /*  This struct records distances, the left one is positive or 0 and the right one is negative or 0.
3430  *  When comparing the locations of 2 different graphical objects on the page, we will have to also record the
3431  *  horizontal distance as signed to keep track of the typesetting order.*/
3432 typedef struct {
3433         int left;
3434         int right;
3435 } synctex_distances_t;
3436
3437 typedef struct {
3438         synctex_point_t left;
3439         synctex_point_t right;
3440 } synctex_offsets_t;
3441
3442
3443 typedef struct {
3444         synctex_node_t left;
3445         synctex_node_t right;
3446 } synctex_node_set_t;
3447
3448 /*  The smallest container between two has the smallest width or height.
3449  *  This comparison is used when there are 2 overlapping boxes that contain the hit point.
3450  *  For ConTeXt, the problem appears at each page.
3451  *  The chosen box is the one with the smallest height, then the smallest width. */
3452 SYNCTEX_INLINE static synctex_node_t _synctex_smallest_container(synctex_node_t node, synctex_node_t other_node);
3453
3454 /*  Returns the distance between the hit point hitPoint=(H,V) and the given node. */
3455 synctex_bool_t _synctex_point_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible);
3456 int _synctex_node_distance_to_point(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible);
3457
3458 /*  The best container is the deeper box that contains the hit point (H,V).
3459  *  _synctex_eq_deepest_container starts with node whereas
3460  *  _synctex_box_child_deepest starts with node's children, if any
3461  *  if node is not a box, or a void box, NULL is returned.
3462  *  We traverse the node tree in a deep first manner and stop as soon as a result is found. */
3463 static synctex_node_t _synctex_eq_deepest_container(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible);
3464
3465 /*  Once a best container is found, the closest children are the closest nodes to the left or right of the hit point.
3466  *  Only horizontal and vertical offsets are used to compare the positions of the nodes. */
3467 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);
3468
3469 /*  The closest container is the box that is the one closest to the given point.
3470  *  The "visible" version takes into account the visible dimensions instead of the real ones given by TeX. */
3471 SYNCTEX_INLINE static synctex_node_t _synctex_eq_closest_child(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible);
3472
3473 #define SYNCTEX_MASK_LEFT 1
3474 #define SYNCTEX_MASK_RIGHT 2
3475
3476 int synctex_edit_query(synctex_scanner_t scanner,int page,float h,float v) {
3477         synctex_node_t sheet = NULL;
3478         synctex_node_t node = NULL; /*  placeholder */
3479         synctex_node_t other_node = NULL; /*  placeholder */
3480         synctex_point_t hitPoint = {0,0}; /*  placeholder */
3481         synctex_node_set_t bestNodes = {NULL,NULL}; /*  holds the best node */
3482         synctex_distances_t bestDistances = {INT_MAX,INT_MAX}; /*  holds the best distances for the best node */
3483         synctex_node_t bestContainer = NULL; /*  placeholder */
3484         if (NULL == (scanner = synctex_scanner_parse(scanner)) || 0 >= scanner->unit) {/*  scanner->unit must be >0 */
3485                 return 0;
3486         }
3487         /*  Convert the given point to scanner integer coordinates */
3488         hitPoint.h = (h-scanner->x_offset)/scanner->unit;
3489         hitPoint.v = (v-scanner->y_offset)/scanner->unit;
3490         /*  We will store in the scanner's buffer the result of the query. */
3491         free(SYNCTEX_START);
3492         SYNCTEX_START = SYNCTEX_END = SYNCTEX_CUR = NULL;
3493         /*  Find the proper sheet */
3494         sheet = scanner->sheet;
3495         while((sheet) && SYNCTEX_PAGE(sheet) != page) {
3496                 sheet = SYNCTEX_SIBLING(sheet);
3497         }
3498         if (NULL == sheet) {
3499                 return -1;
3500         }
3501         /*  Now sheet points to the sheet node with proper page number */
3502         /*  Here is how we work:
3503          *  At first we do not consider the visible box dimensions. This will cover the most frequent cases.
3504          *  Then we try with the visible box dimensions.
3505          *  We try to find a non void box containing the hit point.
3506          *  We browse all the horizontal boxes until we find one containing the hit point. */
3507         if ((node = SYNCTEX_NEXT_HORIZ_BOX(sheet))) {
3508                 do {
3509                         if (_synctex_point_in_box(hitPoint,node,synctex_YES)) {
3510                                 /*  Maybe the hitPoint belongs to a contained vertical box. */
3511 end:
3512                                 /*  This trick is for catching overlapping boxes */
3513                                 if ((other_node = SYNCTEX_NEXT_HORIZ_BOX(node))) {
3514                                         do {
3515                                                 if (_synctex_point_in_box(hitPoint,other_node,synctex_YES)) {
3516                                                         node = _synctex_smallest_container(other_node,node); 
3517                                                 }
3518                                         } while((other_node = SYNCTEX_NEXT_HORIZ_BOX(other_node)));
3519                                 }
3520                 /*  node is the smallest horizontal box that contains hitPoint. */
3521                                 if ((bestContainer = _synctex_eq_deepest_container(hitPoint,node,synctex_YES))) {
3522                                         node = bestContainer;
3523                                 }
3524                                 _synctex_eq_get_closest_children_in_box(hitPoint,node,&bestNodes,&bestDistances,synctex_YES);
3525                                 if (bestNodes.right && bestNodes.left) {
3526                                         if ((SYNCTEX_TAG(bestNodes.right)!=SYNCTEX_TAG(bestNodes.left))
3527                                                         || (SYNCTEX_LINE(bestNodes.right)!=SYNCTEX_LINE(bestNodes.left))
3528                                                                 || (SYNCTEX_COLUMN(bestNodes.right)!=SYNCTEX_COLUMN(bestNodes.left))) {
3529                                                 if ((SYNCTEX_START = malloc(2*sizeof(synctex_node_t)))) {
3530                                                         if (bestDistances.left>bestDistances.right) {
3531                                                                 ((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.right;
3532                                                                 ((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.left;
3533                                                         } else {
3534                                                                 ((synctex_node_t *)SYNCTEX_START)[0] = bestNodes.left;
3535                                                                 ((synctex_node_t *)SYNCTEX_START)[1] = bestNodes.right;
3536                                                         }
3537                                                         SYNCTEX_END = SYNCTEX_START + 2*sizeof(synctex_node_t);
3538                                                         SYNCTEX_CUR = NULL;
3539                                                         return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
3540                                                 }
3541                                                 return SYNCTEX_STATUS_ERROR;
3542                                         }
3543                                         /*  both nodes have the same input coordinates
3544                                          *  We choose the one closest to the hit point  */
3545                                         if (bestDistances.left>bestDistances.right) {
3546                                                 bestNodes.left = bestNodes.right;
3547                                         }
3548                                         bestNodes.right = NULL;
3549                                 } else if (bestNodes.right) {
3550                                         bestNodes.left = bestNodes.right;
3551                                 } else if (!bestNodes.left){
3552                                         bestNodes.left = node;
3553                                 }
3554                                 if ((SYNCTEX_START = malloc(sizeof(synctex_node_t)))) {
3555                                         * (synctex_node_t *)SYNCTEX_START = bestNodes.left;
3556                                         SYNCTEX_END = SYNCTEX_START + sizeof(synctex_node_t);
3557                                         SYNCTEX_CUR = NULL;
3558                                         return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);
3559                                 }
3560                                 return SYNCTEX_STATUS_ERROR;
3561                         }
3562                 } while ((node = SYNCTEX_NEXT_HORIZ_BOX(node)));
3563                 /*  All the horizontal boxes have been tested,
3564                  *  None of them contains the hit point.
3565                  */
3566         }
3567         /*  We are not lucky */
3568         if ((node = SYNCTEX_CHILD(sheet))) {
3569                 goto end;
3570         }
3571         return 0;
3572 }
3573
3574 #       ifdef SYNCTEX_NOTHING
3575 #       pragma mark -
3576 #       pragma mark Utilities
3577 #   endif
3578
3579 int _synctex_bail(void) {
3580                 _synctex_error("SyncTeX ERROR\n");
3581                 return -1;
3582 }
3583 /*  Rougly speaking, this is:
3584  *  node's h coordinate - hitPoint's h coordinate.
3585  *  If node is to the right of the hit point, then this distance is positive,
3586  *  if node is to the left of the hit point, this distance is negative.*/
3587 int _synctex_point_h_distance(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible);
3588 int _synctex_point_h_distance(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) {
3589         if (node) {
3590                 int min,med,max;
3591                 switch(node->class->type) {
3592                         /*  The distance between a point and a box is special.
3593                          *  It is not the euclidian distance, nor something similar.
3594                          *  We have to take into account the particular layout,
3595                          *  and the box hierarchy.
3596                          *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
3597                          *  The origin being at the top left corner of the page,
3598                          *  we also give names to the vertices of the box.
3599                          *
3600                          *   1 | 2 | 3
3601                          *  ---A---B--->
3602                          *   4 | 5 | 6
3603                          *  ---C---D--->
3604                          *   7 | 8 | 9
3605                          *     v   v
3606                          */
3607                         case synctex_node_type_hbox:
3608                                 /*  getting the box bounds, taking into account negative width, height and depth. */
3609                                 min = visible?SYNCTEX_HORIZ_V(node):SYNCTEX_HORIZ(node);
3610                                 max = min + (visible?SYNCTEX_ABS_WIDTH_V(node):SYNCTEX_ABS_WIDTH(node));
3611                                 /*  We allways have min <= max */
3612                                 if (hitPoint.h<min) {
3613                                         return min - hitPoint.h; /*  regions 1+4+7, result is > 0 */
3614                                 } else if (hitPoint.h>max) {
3615                                         return max - hitPoint.h; /*  regions 3+6+9, result is < 0 */
3616                                 } else {
3617                                         return 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
3618                                 }
3619                                 break;
3620                         case synctex_node_type_vbox:
3621                         case synctex_node_type_void_vbox:
3622                         case synctex_node_type_void_hbox:
3623                                 /*  getting the box bounds, taking into account negative width, height and depth.
3624                                  *  For these boxes, no visible dimension available */
3625                                 min = SYNCTEX_HORIZ(node);
3626                                 max = min + SYNCTEX_ABS_WIDTH(node);
3627                                 /*  We allways have min <= max */
3628                                 if (hitPoint.h<min) {
3629                                         return min - hitPoint.h; /*  regions 1+4+7, result is > 0 */
3630                                 } else if (hitPoint.h>max) {
3631                                         return max - hitPoint.h; /*  regions 3+6+9, result is < 0 */
3632                                 } else {
3633                                         return 0; /*  regions 2+5+8, inside the box, except for vertical coordinates */
3634                                 }
3635                                 break;
3636                         case synctex_node_type_kern:
3637                                 /*  IMPORTANT NOTICE: the location of the kern is recorded AFTER the move.
3638                                  *  The distance to the kern is very special,
3639                                  *  in general, there is no text material in the kern,
3640                                  *  this is why we compute the offset relative to the closest edge of the kern.*/
3641                                 max = SYNCTEX_WIDTH(node);
3642                                 if (max<0) {
3643                                         min = SYNCTEX_HORIZ(node);
3644                                         max = min - max;
3645                                 } else {
3646                                         min = -max;
3647                                         max = SYNCTEX_HORIZ(node);
3648                                         min += max;
3649                                 }
3650                                 med = (min+max)/2;
3651                                 /*  positive kern: '.' means text, '>' means kern offset
3652                                  *      .............
3653                                  *                   min>>>>med>>>>max
3654                                  *                                    ...............
3655                                  *  negative kern: '.' means text, '<' means kern offset
3656                                  *      ............................
3657                                  *                 min<<<<med<<<<max
3658                                  *                 .................................
3659                                  *  Actually, we do not take into account negative widths.
3660                                  *  There is a problem for such situation when there is efectively overlapping text.
3661                                  *  But this should be extremely rare. I guess that in that case, many different choices
3662                                  *  could be made, one being in contradiction of the other.
3663                                  *  It means that the best choice should be made according to the situation that occurs
3664                                  *  most frequently.
3665                                  */
3666                                 if (hitPoint.h<min) {
3667                                         return min - hitPoint.h + 1; /*  penalty to ensure other nodes are chosen first in case of overlapping ones */
3668                                 } else if (hitPoint.h>max) {
3669                                         return max - hitPoint.h - 1; /*  same kind of penalty */
3670                                 } else if (hitPoint.h>med) {
3671                                         /*  do things like if the node had 0 width and was placed at the max edge + 1*/
3672                                         return max - hitPoint.h + 1; /*  positive, the kern is to the right of the hitPoint */
3673                                 } else {
3674                                         return min - hitPoint.h - 1; /*  negative, the kern is to the left of the hitPoint */
3675                                 }
3676                         case synctex_node_type_glue:
3677                         case synctex_node_type_math:
3678                                 return SYNCTEX_HORIZ(node) - hitPoint.h;
3679                 }
3680         }
3681         return INT_MAX;/*  We always assume that the node is faraway to the right*/
3682 }
3683 /*  Rougly speaking, this is:
3684  *  node's v coordinate - hitPoint's v coordinate.
3685  *  If node is at the top of the hit point, then this distance is positive,
3686  *  if node is at the bottom of the hit point, this distance is negative.*/
3687 int _synctex_point_v_distance(synctex_point_t hitPoint, synctex_node_t node,synctex_bool_t visible);
3688 int _synctex_point_v_distance(synctex_point_t hitPoint, synctex_node_t node,synctex_bool_t visible) {
3689 #       ifdef __DARWIN_UNIX03
3690 #       pragma unused(visible)
3691 #   endif
3692         if (node) {
3693                 int min,max;
3694                 switch(node->class->type) {
3695                         /*  The distance between a point and a box is special.
3696                          *  It is not the euclidian distance, nor something similar.
3697                          *  We have to take into account the particular layout,
3698                          *  and the box hierarchy.
3699                          *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
3700                          *  The origin being at the top left corner of the page,
3701                          *  we also give names to the vertices of the box.
3702                          *
3703                          *   1 | 2 | 3
3704                          *  ---A---B--->
3705                          *   4 | 5 | 6
3706                          *  ---C---D--->
3707                          *   7 | 8 | 9
3708                          *     v   v
3709                          */
3710                         case synctex_node_type_hbox:
3711                                 /*  getting the box bounds, taking into account negative width, height and depth. */
3712                                 min = SYNCTEX_VERT_V(node);
3713                                 max = min + SYNCTEX_ABS_DEPTH_V(node);
3714                                 min -= SYNCTEX_ABS_HEIGHT_V(node);
3715                                 /*  We allways have min <= max */
3716                                 if (hitPoint.v<min) {
3717                                         return min - hitPoint.v; /*  regions 1+2+3, result is > 0 */
3718                                 } else if (hitPoint.v>max) {
3719                                         return max - hitPoint.v; /*  regions 7+8+9, result is < 0 */
3720                                 } else {
3721                                         return 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
3722                                 }
3723                                 break;
3724                         case synctex_node_type_vbox:
3725                         case synctex_node_type_void_vbox:
3726                         case synctex_node_type_void_hbox:
3727                                 /*  getting the box bounds, taking into account negative width, height and depth. */
3728                                 min = SYNCTEX_VERT(node);
3729                                 max = min + SYNCTEX_ABS_DEPTH(node);
3730                                 min -= SYNCTEX_ABS_HEIGHT(node);
3731                                 /*  We allways have min <= max */
3732                                 if (hitPoint.v<min) {
3733                                         return min - hitPoint.v; /*  regions 1+2+3, result is > 0 */
3734                                 } else if (hitPoint.v>max) {
3735                                         return max - hitPoint.v; /*  regions 7+8+9, result is < 0 */
3736                                 } else {
3737                                         return 0; /*  regions 4.5.6, inside the box, except for horizontal coordinates */
3738                                 }
3739                                 break;
3740                         case synctex_node_type_kern:
3741                         case synctex_node_type_glue:
3742                         case synctex_node_type_math:
3743                                 return SYNCTEX_VERT(node) - hitPoint.v;
3744                 }
3745         }
3746         return INT_MAX;/*  We always assume that the node is faraway to the top*/
3747 }
3748
3749 SYNCTEX_INLINE static synctex_node_t _synctex_smallest_container(synctex_node_t node, synctex_node_t other_node) {
3750         float height, other_height;
3751         if (SYNCTEX_ABS_WIDTH(node)<SYNCTEX_ABS_WIDTH(other_node)) {
3752                 return node;
3753         }
3754         if (SYNCTEX_ABS_WIDTH(node)>SYNCTEX_ABS_WIDTH(other_node)) {
3755                 return other_node;
3756         }
3757         height = SYNCTEX_ABS_DEPTH(node) + SYNCTEX_ABS_HEIGHT(node);
3758         other_height = SYNCTEX_ABS_DEPTH(other_node) + SYNCTEX_ABS_HEIGHT(other_node);
3759         if (height<other_height) {
3760                 return node;
3761         }
3762         if (height>other_height) {
3763                 return other_node;
3764         }
3765         return node;
3766 }
3767
3768 synctex_bool_t _synctex_point_in_box(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) {
3769         if (node) {
3770                 if (0 == _synctex_point_h_distance(hitPoint,node,visible)
3771                                 && 0 == _synctex_point_v_distance(hitPoint,node,visible)) {
3772                         return synctex_YES;
3773                 }
3774         }
3775         return synctex_NO;      
3776 }
3777
3778 int _synctex_node_distance_to_point(synctex_point_t hitPoint, synctex_node_t node, synctex_bool_t visible) {
3779 #       ifdef __DARWIN_UNIX03
3780 #       pragma unused(visible)
3781 #   endif
3782         int result = INT_MAX; /*  when the distance is meaning less (sheet, input...)  */
3783         if (node) {
3784                 int minH,maxH,minV,maxV;
3785                 switch(node->class->type) {
3786                         /*  The distance between a point and a box is special.
3787                          *  It is not the euclidian distance, nor something similar.
3788                          *  We have to take into account the particular layout,
3789                          *  and the box hierarchy.
3790                          *  Given a box, there are 9 regions delimited by the lines of the edges of the box.
3791                          *  The origin being at the top left corner of the page,
3792                          *  we also give names to the vertices of the box.
3793                          *
3794                          *   1 | 2 | 3
3795                          *  ---A---B--->
3796                          *   4 | 5 | 6
3797                          *  ---C---D--->
3798                          *   7 | 8 | 9
3799                          *     v   v
3800                          *  In each region, there is a different formula.
3801                          *  In the end we have a continuous distance which may not be a mathematical distance but who cares. */
3802                         case synctex_node_type_vbox:
3803                         case synctex_node_type_void_vbox:
3804                         case synctex_node_type_hbox:
3805                         case synctex_node_type_void_hbox:
3806                                 /*  getting the box bounds, taking into account negative widths. */
3807                                 minH = SYNCTEX_HORIZ(node);
3808                                 maxH = minH + SYNCTEX_ABS_WIDTH(node);
3809                                 minV = SYNCTEX_VERT(node);
3810                                 maxV = minV + SYNCTEX_ABS_DEPTH(node);
3811                                 minV -= SYNCTEX_ABS_HEIGHT(node);
3812                                 /*  In what region is the point hitPoint=(H,V) ? */
3813                                 if (hitPoint.v<minV) {
3814                                         if (hitPoint.h<minH) {
3815                                                 /*  This is region 1. The distance to the box is the L1 distance PA. */
3816                                                 result = minV - hitPoint.v + minH - hitPoint.h;/*  Integer overflow? probability epsilon */
3817                                         } else if (hitPoint.h<=maxH) {
3818                                                 /*  This is region 2. The distance to the box is the geometrical distance to the top edge.  */
3819                                                 result = minV - hitPoint.v;
3820                                         } else {
3821                                                 /*  This is region 3. The distance to the box is the L1 distance PB. */
3822                                                 result = minV - hitPoint.v + hitPoint.h - maxH;
3823                                         }
3824                                 } else if (hitPoint.v<=maxV) {
3825                                         if (hitPoint.h<minH) {
3826                                                 /*  This is region 4. The distance to the box is the geometrical distance to the left edge.  */
3827                                                 result = minH - hitPoint.h;
3828                                         } else if (hitPoint.h<=maxH) {
3829                                                 /*  This is region 4. We are inside the box.  */
3830                                                 result = 0;
3831                                         } else {
3832                                                 /*  This is region 6. The distance to the box is the geometrical distance to the right edge.  */
3833                                                 result = hitPoint.h - maxH;
3834                                         }
3835                                 } else {
3836                                         if (hitPoint.h<minH) {
3837                                                 /*  This is region 7. The distance to the box is the L1 distance PC. */
3838                                                 result = hitPoint.v - maxV + minH - hitPoint.h;
3839                                         } else if (hitPoint.h<=maxH) {
3840                                                 /*  This is region 8. The distance to the box is the geometrical distance to the top edge.  */
3841                                                 result = hitPoint.v - maxV;
3842                                         } else {
3843                                                 /*  This is region 9. The distance to the box is the L1 distance PD. */
3844                                                 result = hitPoint.v - maxV + hitPoint.h - maxH;
3845                                         }
3846                                 }
3847                                 break;
3848                         case synctex_node_type_kern:
3849                                 maxH = SYNCTEX_WIDTH(node);
3850                                 if (maxH<0) {
3851                                         minH = SYNCTEX_HORIZ(node);
3852                                         maxH = minH - maxH;
3853                                 } else {
3854                                         minH = -maxH;
3855                                         maxH = SYNCTEX_HORIZ(node);
3856                                         minH += maxH;
3857                                 }
3858                                 minV = SYNCTEX_VERT(node);
3859                                 if (hitPoint.h<minH) {
3860                                         if (hitPoint.v>minV) {
3861                                                 result = hitPoint.v - minV + minH - hitPoint.h;
3862                                         } else {
3863                                                 result = minV - hitPoint.v + minH - hitPoint.h;
3864                                         }
3865                                 } else if (hitPoint.h>maxH) {
3866                                         if (hitPoint.v>minV) {
3867                                                 result = hitPoint.v - minV + hitPoint.h - maxH;
3868                                         } else {
3869                                                 result = minV - hitPoint.v + hitPoint.h - maxH;
3870                                         }
3871                                 } else if (hitPoint.v>minV) {
3872                                         result = hitPoint.v - minV;
3873                                 } else {
3874                                         result = minV - hitPoint.v;
3875                                 }
3876                                 break;
3877                         case synctex_node_type_glue:
3878                         case synctex_node_type_math:
3879                                 minH = SYNCTEX_HORIZ(node);
3880                                 minV = SYNCTEX_VERT(node);
3881                                 if (hitPoint.h<minH) {
3882                                         if (hitPoint.v>minV) {
3883                                                 result = hitPoint.v - minV + minH - hitPoint.h;
3884                                         } else {
3885                                                 result = minV - hitPoint.v + minH - hitPoint.h;
3886                                         }
3887                                 } else if (hitPoint.v>minV) {
3888                                         result = hitPoint.v - minV + hitPoint.h - minH;
3889                                 } else {
3890                                         result = minV - hitPoint.v + hitPoint.h - minH;
3891                                 }
3892                                 break;
3893                 }
3894         }
3895         return result;
3896 }
3897
3898 static synctex_node_t _synctex_eq_deepest_container(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) {
3899         if (node) {
3900                 synctex_node_t result = NULL;
3901                 synctex_node_t child = NULL;
3902                 switch(node->class->type) {
3903                         case synctex_node_type_vbox:
3904                         case synctex_node_type_hbox:
3905                                 /*  test the deep nodes first */
3906                                 if ((child = SYNCTEX_CHILD(node))) {
3907                                         do {
3908                                                 if ((result = _synctex_eq_deepest_container(hitPoint,child,visible))) {
3909                                                         return result;
3910                                                 }
3911                                         } while((child = SYNCTEX_SIBLING(child)));
3912                                 }
3913                                 /*  is the hit point inside the box? */
3914                                 if (_synctex_point_in_box(hitPoint,node,visible)) {
3915                                         /*  for vboxes we try to use some node inside.
3916                                          *  Walk through the list of siblings until we find the closest one.
3917                                          *  Only consider siblings with children. */
3918                                         if ((node->class->type == synctex_node_type_vbox) && (child = SYNCTEX_CHILD(node))) {
3919                                                 int bestDistance = INT_MAX;
3920                                                 do {
3921                                                         if (SYNCTEX_CHILD(child)) {
3922                                                                 int distance = _synctex_node_distance_to_point(hitPoint,child,visible);
3923                                                                 if (distance < bestDistance) {
3924                                                                         bestDistance = distance;
3925                                                                         node = child;
3926                                                                 }
3927                                                         }
3928                                                 } while((child = SYNCTEX_SIBLING(child)));
3929                                         }
3930                                         return node;
3931                                 }
3932                 }
3933         }
3934         return NULL;
3935 }
3936
3937 /*  Compares the locations of the hitPoint with the locations of the various nodes contained in the box.
3938  *  As it is an horizontal box, we only compare horizontal coordinates. */
3939 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);
3940 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) {
3941         int result = 0;
3942         if ((node = SYNCTEX_CHILD(node))) {
3943                 do {
3944                         int off7 = _synctex_point_h_distance(hitPoint,node,visible);
3945                         if (off7 > 0) {
3946                                 /*  node is to the right of the hit point.
3947                                  *  We compare node and the previously recorded one, through the recorded distance.
3948                                  *  If the nodes have the same tag, prefer the one with the smallest line number,
3949                                  *  if the nodes also have the same line number, prefer the one with the smallest column. */
3950                                 if (bestDistancesRef->right > off7) {
3951                                         bestDistancesRef->right = off7;
3952                                         bestNodesRef->right = node;
3953                                         result |= SYNCTEX_MASK_RIGHT;
3954                                 } else if (bestDistancesRef->right == off7 && bestNodesRef->right) {
3955                                         if (SYNCTEX_TAG(bestNodesRef->right) == SYNCTEX_TAG(node)
3956                                                 && (SYNCTEX_LINE(bestNodesRef->right) > SYNCTEX_LINE(node)
3957                                                         || (SYNCTEX_LINE(bestNodesRef->right) == SYNCTEX_LINE(node)
3958                                                                 && SYNCTEX_COLUMN(bestNodesRef->right) > SYNCTEX_COLUMN(node)))) {
3959                                                 bestNodesRef->right = node;
3960                                                 result |= SYNCTEX_MASK_RIGHT;
3961                                         }
3962                                 }
3963                         } else if (off7 == 0) {
3964                                 /*  hitPoint is inside node. */ 
3965                                 bestDistancesRef->left = bestDistancesRef->right = 0;
3966                                 bestNodesRef->left = node;
3967                                 bestNodesRef->right = NULL;
3968                                 result |= SYNCTEX_MASK_LEFT;
3969                         } else { /*  here off7 < 0, hitPoint is to the right of node */
3970                                 off7 = -off7;
3971                                 if (bestDistancesRef->left > off7) {
3972                                         bestDistancesRef->left = off7;
3973                                         bestNodesRef->left = node;
3974                                         result |= SYNCTEX_MASK_LEFT;
3975                                 } else if (bestDistancesRef->left == off7 && bestNodesRef->left) {
3976                                         if (SYNCTEX_TAG(bestNodesRef->left) == SYNCTEX_TAG(node)
3977                                                 && (SYNCTEX_LINE(bestNodesRef->left) > SYNCTEX_LINE(node)
3978                                                         || (SYNCTEX_LINE(bestNodesRef->left) == SYNCTEX_LINE(node)
3979                                                                 && SYNCTEX_COLUMN(bestNodesRef->left) > SYNCTEX_COLUMN(node)))) {
3980                                                 bestNodesRef->left = node;
3981                                                 result |= SYNCTEX_MASK_LEFT;
3982                                         }
3983                                 }
3984                         }
3985                 } while((node = SYNCTEX_SIBLING(node)));
3986                 if (result & SYNCTEX_MASK_LEFT) {
3987                         /*  the left node is new, try to narrow the result */
3988                         if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->left,visible))) {
3989                                 bestNodesRef->left = node;
3990                         } 
3991                         if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) {
3992                                 bestNodesRef->left = node;
3993                         } 
3994                 }
3995                 if (result & SYNCTEX_MASK_RIGHT) {
3996                         /*  the right node is new, try to narrow the result */
3997                         if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->right,visible))) {
3998                                 bestNodesRef->right = node;
3999                         } 
4000                         if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) {
4001                                 bestNodesRef->right = node;
4002                         } 
4003                 }
4004         }
4005         return result;
4006 }
4007 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);
4008 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) {
4009         int result = 0;
4010         if ((node = SYNCTEX_CHILD(node))) {
4011                 do {
4012                         int off7 = _synctex_point_v_distance(hitPoint,node,visible);/*  this is what makes the difference with the h version above */
4013                         if (off7 > 0) {
4014                                 /*  node is to the top of the hit point (below because TeX is oriented from top to bottom.
4015                                  *  We compare node and the previously recorded one, through the recorded distance.
4016                                  *  If the nodes have the same tag, prefer the one with the smallest line number,
4017                                  *  if the nodes also have the same line number, prefer the one with the smallest column. */
4018                                 if (bestDistancesRef->right > off7) {
4019                                         bestDistancesRef->right = off7;
4020                                         bestNodesRef->right = node;
4021                                         result |= SYNCTEX_MASK_RIGHT;
4022                                 } else if (bestDistancesRef->right == off7 && bestNodesRef->right) {
4023                                         if (SYNCTEX_TAG(bestNodesRef->right) == SYNCTEX_TAG(node)
4024                                                 && (SYNCTEX_LINE(bestNodesRef->right) > SYNCTEX_LINE(node)
4025                                                         || (SYNCTEX_LINE(bestNodesRef->right) == SYNCTEX_LINE(node)
4026                                                                 && SYNCTEX_COLUMN(bestNodesRef->right) > SYNCTEX_COLUMN(node)))) {
4027                                                 bestNodesRef->right = node;
4028                                                 result |= SYNCTEX_MASK_RIGHT;
4029                                         }
4030                                 }
4031                         } else if (off7 == 0) {
4032                                 bestDistancesRef->left = bestDistancesRef->right = 0;
4033                                 bestNodesRef->left = node;
4034                                 bestNodesRef->right = NULL;
4035                                 result |= SYNCTEX_MASK_LEFT;
4036                         } else { /*  here off7 < 0 */
4037                                 off7 = -off7;
4038                                 if (bestDistancesRef->left > off7) {
4039                                         bestDistancesRef->left = off7;
4040                                         bestNodesRef->left = node;
4041                                         result |= SYNCTEX_MASK_LEFT;
4042                                 } else if (bestDistancesRef->left == off7 && bestNodesRef->left) {
4043                                         if (SYNCTEX_TAG(bestNodesRef->left) == SYNCTEX_TAG(node)
4044                                                 && (SYNCTEX_LINE(bestNodesRef->left) > SYNCTEX_LINE(node)
4045                                                         || (SYNCTEX_LINE(bestNodesRef->left) == SYNCTEX_LINE(node)
4046                                                                 && SYNCTEX_COLUMN(bestNodesRef->left) > SYNCTEX_COLUMN(node)))) {
4047                                                 bestNodesRef->left = node;
4048                                                 result |= SYNCTEX_MASK_LEFT;
4049                                         }
4050                                 }
4051                         }
4052                 } while((node = SYNCTEX_SIBLING(node)));
4053                 if (result & SYNCTEX_MASK_LEFT) {
4054                         /*  the left node is new, try to narrow the result */
4055                         if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->left,visible))) {
4056                                 bestNodesRef->left = node;
4057                         } 
4058                         if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->left,visible))) {
4059                                 bestNodesRef->left = node;
4060                         } 
4061                 }
4062                 if (result & SYNCTEX_MASK_RIGHT) {
4063                         /*  the right node is new, try to narrow the result */
4064                         if ((node = _synctex_eq_deepest_container(hitPoint,bestNodesRef->right,visible))) {
4065                                 bestNodesRef->right = node;
4066                         } 
4067                         if ((node = _synctex_eq_closest_child(hitPoint,bestNodesRef->right,visible))) {
4068                                 bestNodesRef->right = node;
4069                         } 
4070                 }
4071         }
4072         return result;
4073 }
4074 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) {
4075         if (node) {
4076                 switch(node->class->type) {
4077                         case synctex_node_type_hbox:
4078                                 return __synctex_eq_get_closest_children_in_hbox(hitPoint, node, bestNodesRef, bestDistancesRef,visible);
4079                         case synctex_node_type_vbox:
4080                                 return __synctex_eq_get_closest_children_in_vbox(hitPoint, node, bestNodesRef, bestDistancesRef,visible);
4081                 }
4082         }
4083         return 0;
4084 }
4085
4086 SYNCTEX_INLINE static synctex_node_t __synctex_eq_closest_child(synctex_point_t hitPoint, synctex_node_t node,int*  distanceRef, synctex_bool_t visible);
4087 SYNCTEX_INLINE static synctex_node_t __synctex_eq_closest_child(synctex_point_t hitPoint, synctex_node_t node,int*  distanceRef, synctex_bool_t visible) {
4088         synctex_node_t best_node = NULL;
4089         if ((node = SYNCTEX_CHILD(node))) {
4090                 do {
4091                         int distance = _synctex_node_distance_to_point(hitPoint,node,visible);
4092                         synctex_node_t candidate = NULL;
4093                         if (distance<=*distanceRef) {
4094                                 *distanceRef = distance;
4095                                 best_node = node;
4096                         }
4097                         switch(node->class->type) {
4098                                 case synctex_node_type_vbox:
4099                                 case synctex_node_type_hbox:
4100                                         if ((candidate = __synctex_eq_closest_child(hitPoint,node,distanceRef,visible))) {
4101                                                 best_node = candidate;
4102                                         }
4103                         }
4104                 } while((node = SYNCTEX_SIBLING(node)));
4105         }
4106         return best_node;
4107 }
4108 SYNCTEX_INLINE static synctex_node_t _synctex_eq_closest_child(synctex_point_t hitPoint,synctex_node_t node, synctex_bool_t visible) {
4109         if (node) {
4110                 switch(node->class->type) {
4111                         case synctex_node_type_hbox:
4112                         case synctex_node_type_vbox:
4113                         {
4114                                 int best_distance = INT_MAX;
4115                                 synctex_node_t best_node = __synctex_eq_closest_child(hitPoint,node,&best_distance,visible);
4116                                 if ((best_node)) {
4117                                         synctex_node_t child = NULL;
4118                                         switch(best_node->class->type) {
4119                                                 case synctex_node_type_vbox:
4120                                                 case synctex_node_type_hbox:
4121                                                         if ((child = SYNCTEX_CHILD(best_node))) {
4122                                                                 best_distance = _synctex_node_distance_to_point(hitPoint,child,visible);
4123                                                                 while((child = SYNCTEX_SIBLING(child))) {
4124                                                                         int distance = _synctex_node_distance_to_point(hitPoint,child,visible);
4125                                                                         if (distance<=best_distance) {
4126                                                                                 best_distance = distance;
4127                                                                                 best_node = child;
4128                                                                         }
4129                                                                 }
4130                                                         }
4131                                         }
4132                                 }
4133                                 return best_node;
4134                         }
4135                 }
4136         }
4137         return NULL;
4138 }
4139
4140 #       ifdef SYNCTEX_NOTHING
4141 #       pragma mark -
4142 #       pragma mark Updater
4143 #   endif
4144
4145 typedef int (*synctex_fprintf_t)(void *, const char * , ...); /*  print formatted to either FILE *  or gzFile */
4146
4147 #   define SYNCTEX_BITS_PER_BYTE 8
4148
4149 struct __synctex_updater_t {
4150     void *file;                 /*  the foo.synctex or foo.synctex.gz I/O identifier  */
4151         synctex_fprintf_t fprintf;  /*  either fprintf or gzprintf */
4152         int length;                 /*  the number of chars appended */
4153     struct _flags {
4154         unsigned int no_gz:1;   /*  Whether zlib is used or not */
4155         unsigned int reserved:SYNCTEX_BITS_PER_BYTE*sizeof(int)-1; /*  Align */
4156         } flags;
4157 };
4158 #   define SYNCTEX_FILE updater->file
4159 #   define SYNCTEX_NO_GZ ((updater->flags).no_gz)
4160 #   define SYNCTEX_fprintf (*(updater->fprintf))
4161
4162 synctex_updater_t synctex_updater_new_with_output_file(const char * output, const char * build_directory) {
4163         synctex_updater_t updater = NULL;
4164         char * synctex = NULL;
4165         synctex_io_mode_t io_mode = 0;
4166         const char * mode = NULL;
4167         /*  prepare the updater, the memory is the only one dynamically allocated */
4168         updater = (synctex_updater_t)_synctex_malloc(sizeof(synctex_updater_t));
4169         if (NULL == updater) {
4170                 _synctex_error("!  synctex_updater_new_with_file: malloc problem");
4171                 return NULL;
4172         }
4173         if (_synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_ADD_QUOTES,&io_mode)
4174                 && _synctex_open(output,build_directory,&synctex,&SYNCTEX_FILE,synctex_DONT_ADD_QUOTES,&io_mode)) {
4175 return_on_error:
4176                 free(updater);
4177         updater = NULL;
4178                 return NULL;
4179         }
4180         /*  OK, the file exists, we close it and reopen it with the correct mode.
4181      *  The receiver is now the owner of the "synctex" variable. */
4182         gzclose(SYNCTEX_FILE);
4183         SYNCTEX_FILE = NULL;
4184         SYNCTEX_NO_GZ = (io_mode&synctex_io_gz_mask)?synctex_NO:synctex_YES;
4185     mode = _synctex_get_io_mode_name(io_mode|synctex_io_append_mask);/* either "a" or "ab", depending on the file extension */
4186         if (SYNCTEX_NO_GZ) {
4187                 if (NULL == (SYNCTEX_FILE = (void *)fopen(synctex,mode))) {
4188 no_write_error:
4189                         _synctex_error("!  synctex_updater_new_with_file: Can't append to %s",synctex);
4190                         free(synctex);
4191                         goto return_on_error;
4192                 }
4193                 updater->fprintf = (synctex_fprintf_t)(&fprintf);
4194         } else {
4195                 if (NULL == (SYNCTEX_FILE = (void *)gzopen(synctex,mode))) {
4196                         goto no_write_error;
4197                 }
4198                 updater->fprintf = (synctex_fprintf_t)(&gzprintf);
4199         }
4200         printf("SyncTeX: updating %s...",synctex);
4201         free(synctex);
4202         return updater;
4203 }
4204
4205
4206 void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification){
4207         if (NULL==updater) {
4208                 return;
4209         }
4210         if (magnification && strlen(magnification)) {
4211                 updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Magnification:%s\n",magnification);
4212         }
4213 }
4214
4215 void synctex_updater_append_x_offset(synctex_updater_t updater, char * x_offset){
4216         if (NULL==updater) {
4217                 return;
4218         }
4219         if (x_offset && strlen(x_offset)) {
4220                 updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"X Offset:%s\n",x_offset);
4221         }
4222 }
4223
4224 void synctex_updater_append_y_offset(synctex_updater_t updater, char * y_offset){
4225         if (NULL==updater) {
4226                 return;
4227         }
4228         if (y_offset && strlen(y_offset)) {
4229                 updater->length += SYNCTEX_fprintf(SYNCTEX_FILE,"Y Offset:%s\n",y_offset);
4230         }
4231 }
4232
4233 void synctex_updater_free(synctex_updater_t updater){
4234         if (NULL==updater) {
4235                 return;
4236         }
4237         if (updater->length>0) {
4238                 SYNCTEX_fprintf(SYNCTEX_FILE,"!%i\n",updater->length);
4239         }
4240         if (SYNCTEX_NO_GZ) {
4241                 fclose((FILE *)SYNCTEX_FILE);
4242         } else {
4243                 gzclose((gzFile)SYNCTEX_FILE);
4244         }
4245         free(updater);
4246         printf("... done.\n");
4247         return;
4248 }