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