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