synctex_parser.c (338694B)
1 /* 2 Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr 3 4 This file is part of the __SyncTeX__ package. 5 6 [//]: # (Latest Revision: Sun Oct 15 15:09:55 UTC 2017) 7 [//]: # (Version: 1.21) 8 9 See `synctex_parser_readme.md` for more details 10 11 ## License 12 13 Permission is hereby granted, free of charge, to any person 14 obtaining a copy of this software and associated documentation 15 files (the "Software"), to deal in the Software without 16 restriction, including without limitation the rights to use, 17 copy, modify, merge, publish, distribute, sublicense, and/or sell 18 copies of the Software, and to permit persons to whom the 19 Software is furnished to do so, subject to the following 20 conditions: 21 22 The above copyright notice and this permission notice shall be 23 included in all copies or substantial portions of the Software. 24 25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 27 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 29 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 30 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 32 OTHER DEALINGS IN THE SOFTWARE 33 34 Except as contained in this notice, the name of the copyright holder 35 shall not be used in advertising or otherwise to promote the sale, 36 use or other dealings in this Software without prior written 37 authorization from the copyright holder. 38 39 Acknowledgments: 40 ---------------- 41 The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh, 42 and significant help from XeTeX developer Jonathan Kew 43 44 Nota Bene: 45 ---------- 46 If you include or use a significant part of the synctex package into a software, 47 I would appreciate to be listed as contributor and see "SyncTeX" highlighted. 48 49 */ 50 51 /* We assume that high level application like pdf viewers will want 52 * to embed this code as is. We assume that they also have locale.h and setlocale. 53 * For other tools such as TeXLive tools, you must define SYNCTEX_USE_LOCAL_HEADER, 54 * when building. You also have to create and customize synctex_parser_local.h to fit your system. 55 * In particular, the HAVE_LOCALE_H and HAVE_SETLOCALE macros should be properly defined. 56 * With this design, you should not need to edit this file. */ 57 58 /** 59 * \file synctex_parser.c 60 * \brief SyncTeX file parser and controller. 61 * - author: Jérôme LAURENS 62 * \version 1.21 63 * \date Sun Oct 15 15:09:55 UTC 2017 64 * 65 * Reads and parse *.synctex[.gz] files, 66 * performs edit and display queries. 67 * 68 * See 69 * - synctex_scanner_new_with_output_file 70 * - synctex_scanner_parse 71 * - synctex_scanner_free 72 * - synctex_display_query 73 * - synctex_edit_query 74 * - synctex_scanner_next_result 75 * - synctex_scanner_reset_result 76 * 77 * The data is organized in a graph with multiple entries. 78 * The root object is a scanner, it is created with the contents on a synctex file. 79 * Each node of the tree is a synctex_node_t object. 80 * There are 3 subtrees, two of them sharing the same leaves. 81 * The first tree is the list of input records, where input file names are associated with tags. 82 * The second tree is the box tree as given by TeX when shipping pages out. 83 * First level objects are sheets and forms, containing boxes, glues, kerns... 84 * The third tree allows to browse leaves according to tag and line. 85 */ 86 # if defined(SYNCTEX_USE_LOCAL_HEADER) 87 # include "synctex_parser_local.h" 88 # else 89 # define HAVE_LOCALE_H 1 90 # define HAVE_SETLOCALE 1 91 # if defined(_MSC_VER) 92 # define SYNCTEX_INLINE __inline 93 # else 94 # define SYNCTEX_INLINE inline 95 # endif 96 # endif 97 98 #include <stdlib.h> 99 #include <stdarg.h> 100 #include <stdio.h> 101 #include <string.h> 102 #include <errno.h> 103 #include <limits.h> 104 105 #if defined(HAVE_LOCALE_H) 106 #include <locale.h> 107 #endif 108 109 /* Mark unused parameters, so that there will be no compile warnings. */ 110 #ifdef __DARWIN_UNIX03 111 # define SYNCTEX_UNUSED(x) SYNCTEX_PRAGMA(unused(x)) 112 # define SYNCTEX_PRAGMA(x) _Pragma ( #x ) 113 #else 114 # define SYNCTEX_UNUSED(x) (void)(x); 115 #endif 116 117 #include "synctex_parser_advanced.h" 118 119 SYNCTEX_INLINE static int _synctex_abs(int x) { 120 return x>0? x: -x; 121 } 122 /* These are the possible extensions of the synctex file */ 123 const char * synctex_suffix = ".synctex"; 124 const char * synctex_suffix_gz = ".gz"; 125 126 typedef synctex_node_p(*synctex_node_new_f)(synctex_scanner_p); 127 typedef void(*synctex_node_fld_f)(synctex_node_p); 128 typedef char *(*synctex_node_str_f)(synctex_node_p); 129 130 /** 131 * Pseudo class. 132 * - author: J. Laurens 133 * 134 * Each nodes has a class, it is therefore called an object. 135 * Each class has a unique scanner. 136 * Each class has a type which is a unique identifier. 137 * The class points to various methods, 138 * each of them vary amongst objects. 139 * Each class has a data model which stores node's attributes. 140 * Each class has an tree model which stores children and parent. 141 * Inspectors give access to data and tree elements. 142 */ 143 144 /* 8 fields + size: spcflnat */ 145 typedef struct synctex_tree_model_t { 146 int sibling; 147 int parent; 148 int child; 149 int friend; 150 int last; 151 int next_hbox; 152 int arg_sibling; 153 int target; 154 int size; 155 } synctex_tree_model_s; 156 typedef const synctex_tree_model_s * synctex_tree_model_p; 157 158 typedef struct synctex_data_model_t { 159 int tag; 160 int line; 161 int column; 162 int h; 163 int v; 164 int width; 165 int height; 166 int depth; 167 int mean_line; 168 int weight; 169 int h_V; 170 int v_V; 171 int width_V; 172 int height_V; 173 int depth_V; 174 int name; 175 int page; 176 int size; 177 } synctex_data_model_s; 178 179 typedef const synctex_data_model_s * synctex_data_model_p; 180 181 typedef int (*synctex_int_getter_f)(synctex_node_p); 182 typedef struct synctex_tlcpector_t { 183 synctex_int_getter_f tag; 184 synctex_int_getter_f line; 185 synctex_int_getter_f column; 186 } synctex_tlcpector_s; 187 typedef const synctex_tlcpector_s * synctex_tlcpector_p; 188 static int _synctex_int_none(synctex_node_p node) { 189 SYNCTEX_UNUSED(node) 190 return 0; 191 } 192 static const synctex_tlcpector_s synctex_tlcpector_none = { 193 &_synctex_int_none, /* tag */ 194 &_synctex_int_none, /* line */ 195 &_synctex_int_none, /* column */ 196 }; 197 198 typedef struct synctex_inspector_t { 199 synctex_int_getter_f h; 200 synctex_int_getter_f v; 201 synctex_int_getter_f width; 202 synctex_int_getter_f height; 203 synctex_int_getter_f depth; 204 } synctex_inspector_s; 205 typedef const synctex_inspector_s * synctex_inspector_p; 206 static const synctex_inspector_s synctex_inspector_none = { 207 &_synctex_int_none, /* h */ 208 &_synctex_int_none, /* v */ 209 &_synctex_int_none, /* width */ 210 &_synctex_int_none, /* height */ 211 &_synctex_int_none, /* depth */ 212 }; 213 214 typedef float (*synctex_float_getter_f)(synctex_node_p); 215 typedef struct synctex_vispector_t { 216 synctex_float_getter_f h; 217 synctex_float_getter_f v; 218 synctex_float_getter_f width; 219 synctex_float_getter_f height; 220 synctex_float_getter_f depth; 221 } synctex_vispector_s; 222 static float _synctex_float_none(synctex_node_p node) { 223 SYNCTEX_UNUSED(node) 224 return 0; 225 } 226 static const synctex_vispector_s synctex_vispector_none = { 227 &_synctex_float_none, /* h */ 228 &_synctex_float_none, /* v */ 229 &_synctex_float_none, /* width */ 230 &_synctex_float_none, /* height */ 231 &_synctex_float_none, /* depth */ 232 }; 233 typedef const synctex_vispector_s * synctex_vispector_p; 234 235 struct synctex_class_t { 236 synctex_scanner_p scanner; 237 synctex_node_type_t type; 238 synctex_node_new_f new; 239 synctex_node_fld_f free; 240 synctex_node_fld_f log; 241 synctex_node_fld_f display; 242 synctex_node_str_f abstract; 243 synctex_tree_model_p navigator; 244 synctex_data_model_p modelator; 245 synctex_tlcpector_p tlcpector; 246 synctex_inspector_p inspector; 247 synctex_vispector_p vispector; 248 }; 249 250 /** 251 * Nota bene: naming convention. 252 * For static API, when the name contains "proxy", it applies to proxies. 253 * When the name contains "noxy", it applies to non proxies only. 254 * When the name contains "node", well it depends... 255 */ 256 257 typedef synctex_node_p synctex_proxy_p; 258 typedef synctex_node_p synctex_noxy_p; 259 260 # ifdef SYNCTEX_NOTHING 261 # pragma mark - 262 # pragma mark Abstract OBJECTS and METHODS 263 # endif 264 265 /** 266 * \def SYNCTEX_MSG_SEND 267 * \brief Takes care of sending the given message if possible. 268 * - parameter NODE: of type synctex_node_p 269 * - parameter SELECTOR: one of the class_ pointer properties 270 */ 271 # define SYNCTEX_MSG_SEND(NODE,SELECTOR) do {\ 272 synctex_node_p N__ = NODE;\ 273 if (N__ && N__->class_->SELECTOR) {\ 274 (*(N__->class_->SELECTOR))(N__);\ 275 }\ 276 } while (synctex_NO) 277 278 /** 279 * Free the given node by sending the free message. 280 * - parameter NODE: of type synctex_node_p 281 */ 282 void synctex_node_free(synctex_node_p node) { 283 SYNCTEX_MSG_SEND(node,free); 284 } 285 # if defined(SYNCTEX_TESTING) 286 # if !defined(SYNCTEX_USE_HANDLE) 287 # define SYNCTEX_USE_HANDLE 1 288 # endif 289 # if !defined(SYNCTEX_USE_CHARINDEX) 290 # define SYNCTEX_USE_CHARINDEX 1 291 # endif 292 # endif 293 SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target); 294 # if defined(SYNCTEX_USE_HANDLE) 295 # define SYNCTEX_SCANNER_FREE_HANDLE(SCANR) \ 296 __synctex_scanner_free_handle(SCANR) 297 # define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT) \ 298 __synctex_scanner_remove_handle_to(WHAT) 299 # define SYNCTEX_REGISTER_HANDLE_TO(NODE) \ 300 __synctex_scanner_register_handle_to(NODE) 301 # else 302 # define SYNCTEX_SCANNER_FREE_HANDLE(SCANR) 303 # define SYNCTEX_SCANNER_REMOVE_HANDLE_TO(WHAT) 304 # define SYNCTEX_REGISTER_HANDLE_TO(NODE) 305 # endif 306 307 # if defined(SYNCTEX_USE_CHARINDEX) 308 # define SYNCTEX_CHARINDEX(NODE) (NODE->char_index) 309 # define SYNCTEX_LINEINDEX(NODE) (NODE->line_index) 310 # define SYNCTEX_PRINT_CHARINDEX_FMT "#%i" 311 # define SYNCTEX_PRINT_CHARINDEX_WHAT ,SYNCTEX_CHARINDEX(node) 312 # define SYNCTEX_PRINT_CHARINDEX \ 313 printf(SYNCTEX_PRINT_CHARINDEX_FMT SYNCTEX_PRINT_CHARINDEX_WHAT) 314 # define SYNCTEX_PRINT_LINEINDEX_FMT "L#%i" 315 # define SYNCTEX_PRINT_LINEINDEX_WHAT ,SYNCTEX_LINEINDEX(node) 316 # define SYNCTEX_PRINT_LINEINDEX \ 317 printf(SYNCTEX_PRINT_LINEINDEX_FMT SYNCTEX_PRINT_LINEINDEX_WHAT) 318 # define SYNCTEX_PRINT_CHARINDEX_NL \ 319 printf(SYNCTEX_PRINT_CHARINDEX_FMT "\n" SYNCTEX_PRINT_CHARINDEX_WHAT) 320 # define SYNCTEX_PRINT_LINEINDEX_NL \ 321 printf(SYNCTEX_PRINT_CHARINDEX_FMT "\n"SYNCTEX_PRINT_LINEINDEX_WHAT) 322 # define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION)\ 323 NODE->char_index = (synctex_charindex_t)(scanner->reader->charindex_offset+SYNCTEX_CUR-SYNCTEX_START+(CORRECTION)); \ 324 NODE->line_index = scanner->reader->line_number; 325 # else 326 # define SYNCTEX_CHARINDEX(NODE) 0 327 # define SYNCTEX_LINEINDEX(NODE) 0 328 # define SYNCTEX_PRINT_CHARINDEX_FMT 329 # define SYNCTEX_PRINT_CHARINDEX_WHAT 330 # define SYNCTEX_PRINT_CHARINDEX 331 # define SYNCTEX_PRINT_CHARINDEX 332 # define SYNCTEX_PRINT_LINEINDEX_FMT 333 # define SYNCTEX_PRINT_LINEINDEX_WHAT 334 # define SYNCTEX_PRINT_LINEINDEX 335 # define SYNCTEX_PRINT_CHARINDEX_NL printf("\n") 336 # define SYNCTEX_PRINT_LINEINDEX_NL printf("\n") 337 # define SYNCTEX_IMPLEMENT_CHARINDEX(NODE,CORRECTION) 338 # endif 339 340 /** 341 * The next macros are used to access the node tree info 342 * SYNCTEX_DATA(node) points to the first synctex integer or pointer data of node 343 * SYNCTEX_DATA(node)[index] is the information at index 344 * for example, the page of a sheet is stored in SYNCTEX_DATA(sheet)[_synctex_data_page_idx] 345 * - parameter NODE: of type synctex_node_p 346 * If the name starts with "__", the argument is nonullable 347 */ 348 # ifdef SYNCTEX_NOTHING 349 # pragma mark - 350 # pragma mark Tree SETGET 351 # endif 352 353 #if SYNCTEX_DEBUG > 1000 354 #define SYNCTEX_PARAMETER_ASSERT(WHAT) \ 355 do { \ 356 if (!(WHAT)) { \ 357 printf("! Parameter failure: %s\n",#WHAT); \ 358 } \ 359 } while (synctex_NO) 360 #define DEFINE_SYNCTEX_TREE_HAS(WHAT)\ 361 static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node) {\ 362 if (node) {\ 363 if (node->class_->navigator->WHAT>=0) {\ 364 return synctex_YES; \ 365 } else {\ 366 printf("WARNING: NO tree %s for %s\n", #WHAT, synctex_node_isa(node));\ 367 }\ 368 }\ 369 return synctex_NO;\ 370 } 371 #else 372 #define SYNCTEX_PARAMETER_ASSERT(WHAT) 373 #define DEFINE_SYNCTEX_TREE_HAS(WHAT) \ 374 static synctex_bool_t _synctex_tree_has_##WHAT(synctex_node_p node) {\ 375 return (node && (node->class_->navigator->WHAT>=0));\ 376 } 377 #endif 378 379 # define DEFINE_SYNCTEX_TREE__GET(WHAT) \ 380 SYNCTEX_INLINE static synctex_node_p __synctex_tree_##WHAT(synctex_non_null_node_p node) {\ 381 return node->data[node->class_->navigator->WHAT].as_node;\ 382 } 383 # define DEFINE_SYNCTEX_TREE_GET(WHAT) \ 384 DEFINE_SYNCTEX_TREE__GET(WHAT) \ 385 static synctex_node_p _synctex_tree_##WHAT(synctex_node_p node) {\ 386 if (_synctex_tree_has_##WHAT(node)) {\ 387 return __synctex_tree_##WHAT(node);\ 388 }\ 389 return 0;\ 390 } 391 # define DEFINE_SYNCTEX_TREE__RESET(WHAT) \ 392 SYNCTEX_INLINE static synctex_node_p __synctex_tree_reset_##WHAT(synctex_non_null_node_p node) {\ 393 synctex_node_p old = node->data[node->class_->navigator->WHAT].as_node;\ 394 node->data[node->class_->navigator->WHAT].as_node=NULL;\ 395 return old;\ 396 } 397 # define DEFINE_SYNCTEX_TREE_RESET(WHAT) \ 398 DEFINE_SYNCTEX_TREE__RESET(WHAT) \ 399 SYNCTEX_INLINE static synctex_node_p _synctex_tree_reset_##WHAT(synctex_node_p node) {\ 400 return _synctex_tree_has_##WHAT(node)? \ 401 __synctex_tree_reset_##WHAT(node): NULL; \ 402 } 403 # define DEFINE_SYNCTEX_TREE__SET(WHAT) \ 404 SYNCTEX_INLINE static synctex_node_p __synctex_tree_set_##WHAT(synctex_non_null_node_p node, synctex_node_p new_value) {\ 405 synctex_node_p old = __synctex_tree_##WHAT(node);\ 406 node->data[node->class_->navigator->WHAT].as_node=new_value;\ 407 return old;\ 408 } 409 # define DEFINE_SYNCTEX_TREE_SET(WHAT) \ 410 DEFINE_SYNCTEX_TREE__SET(WHAT) \ 411 SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_##WHAT(synctex_node_p node, synctex_node_p new_value) {\ 412 return _synctex_tree_has_##WHAT(node)?\ 413 __synctex_tree_set_##WHAT(node,new_value):NULL;\ 414 } 415 # define DEFINE_SYNCTEX_TREE__GETSETRESET(WHAT) \ 416 DEFINE_SYNCTEX_TREE__GET(WHAT) \ 417 DEFINE_SYNCTEX_TREE__SET(WHAT) \ 418 DEFINE_SYNCTEX_TREE__RESET(WHAT) 419 420 # define DEFINE_SYNCTEX_TREE_GETSET(WHAT) \ 421 DEFINE_SYNCTEX_TREE_HAS(WHAT) \ 422 DEFINE_SYNCTEX_TREE_GET(WHAT) \ 423 DEFINE_SYNCTEX_TREE_SET(WHAT) 424 425 # define DEFINE_SYNCTEX_TREE_GETRESET(WHAT) \ 426 DEFINE_SYNCTEX_TREE_HAS(WHAT) \ 427 DEFINE_SYNCTEX_TREE_GET(WHAT) \ 428 DEFINE_SYNCTEX_TREE_RESET(WHAT) 429 430 # define DEFINE_SYNCTEX_TREE_GETSETRESET(WHAT) \ 431 DEFINE_SYNCTEX_TREE_HAS(WHAT) \ 432 DEFINE_SYNCTEX_TREE_GET(WHAT) \ 433 DEFINE_SYNCTEX_TREE_SET(WHAT) \ 434 DEFINE_SYNCTEX_TREE_RESET(WHAT) 435 436 /* 437 * _synctex_tree_set_... methods return the old value. 438 * The return value of _synctex_tree_set_child and 439 * _synctex_tree_set_sibling must be released somehown. 440 */ 441 DEFINE_SYNCTEX_TREE__GETSETRESET(sibling) 442 DEFINE_SYNCTEX_TREE_GETSETRESET(parent) 443 DEFINE_SYNCTEX_TREE_GETSETRESET(child) 444 DEFINE_SYNCTEX_TREE_GETSETRESET(friend) 445 DEFINE_SYNCTEX_TREE_GETSET(last) 446 DEFINE_SYNCTEX_TREE_GETSET(next_hbox) 447 DEFINE_SYNCTEX_TREE_GETSET(arg_sibling) 448 DEFINE_SYNCTEX_TREE_GETSETRESET(target) 449 450 #if SYNCTEX_DEBUG>1000 451 # undef SYNCTEX_USE_NODE_COUNT 452 # define SYNCTEX_USE_NODE_COUNT 1 453 #endif 454 #if SYNCTEX_USE_NODE_COUNT>0 455 # define SYNCTEX_DECLARE_NODE_COUNT int node_count; 456 # define SYNCTEX_INIT_NODE_COUNT \ 457 do { node_count = 0; } while(synctex_NO) 458 #else 459 # define SYNCTEX_DECLARE_NODE_COUNT 460 # define SYNCTEX_INIT_NODE_COUNT 461 #endif 462 463 #if SYNCTEX_USE_NODE_COUNT>10 464 # define SYNCTEX_DID_NEW(N) _synctex_did_new(N) 465 # define SYNCTEX_WILL_FREE(N) _synctex_will_free(N) 466 #else 467 # define SYNCTEX_DID_NEW(N) 468 # define SYNCTEX_WILL_FREE(N) 469 #endif 470 471 #define SYNCTEX_HAS_CHILDREN(NODE) (NODE && _synctex_tree_child(NODE)) 472 # ifdef __SYNCTEX_WORK__ 473 # include "/usr/include/zlib.h" 474 # else 475 # include <zlib.h> 476 # endif 477 478 # ifdef SYNCTEX_NOTHING 479 # pragma mark - 480 # pragma mark STATUS 481 # endif 482 /* When the end of the synctex file has been reached: */ 483 # define SYNCTEX_STATUS_EOF 0 484 /* When the function could not return the value it was asked for: */ 485 # define SYNCTEX_STATUS_NOT_OK (SYNCTEX_STATUS_EOF+1) 486 /* When the function returns the value it was asked for: 487 It must be the biggest one */ 488 # define SYNCTEX_STATUS_OK (SYNCTEX_STATUS_NOT_OK+1) 489 /* Generic error: */ 490 # define SYNCTEX_STATUS_ERROR (SYNCTEX_STATUS_EOF-1) 491 /* Parameter error: */ 492 # define SYNCTEX_STATUS_BAD_ARGUMENT (SYNCTEX_STATUS_ERROR-1) 493 494 # ifdef SYNCTEX_NOTHING 495 # pragma mark - 496 # pragma mark File reader 497 # endif 498 499 /* We ensure that SYNCTEX_BUFFER_SIZE < UINT_MAX, I don't know if it makes sense... */ 500 /* Actually, the minimum buffer size is driven by integer and float parsing, including the unit. 501 * ±0.123456789e123?? 502 */ 503 # define SYNCTEX_BUFFER_MIN_SIZE 32 504 # define SYNCTEX_BUFFER_SIZE 32768 505 506 #if SYNCTEX_BUFFER_SIZE >= UINT_MAX 507 # error BAD BUFFER SIZE(1) 508 #endif 509 #if SYNCTEX_BUFFER_SIZE < SYNCTEX_BUFFER_MIN_SIZE 510 # error BAD BUFFER SIZE(2) 511 #endif 512 513 typedef struct synctex_reader_t { 514 gzFile file; /* The (possibly compressed) file */ 515 char * output; 516 char * synctex; 517 char * current; /* current location in the buffer */ 518 char * start; /* start of the buffer */ 519 char * end; /* end of the buffer */ 520 size_t min_size; 521 size_t size; 522 int lastv; 523 int line_number; 524 SYNCTEX_DECLARE_CHAR_OFFSET 525 } synctex_reader_s; 526 527 typedef synctex_reader_s * synctex_reader_p; 528 529 typedef struct { 530 synctex_status_t status; 531 char * synctex; 532 gzFile file; 533 synctex_io_mode_t io_mode; 534 } synctex_open_s; 535 536 /* This functions opens the file at the "output" given location. 537 * It manages the problem of quoted filenames that appear with pdftex and filenames containing the space character. 538 * In TeXLive 2008, the synctex file created with pdftex did contain unexpected quotes. 539 * This function will remove them if possible. 540 * All the reference arguments will take a value on return. They must be non NULL. 541 * - returns: an open structure which status is 542 * SYNCTEX_STATUS_OK on success, 543 * SYNCTEX_STATUS_ERROR on failure. 544 * - note: on success, the caller is the owner 545 * of the fields of the returned open structure. 546 */ 547 static synctex_open_s __synctex_open_v2(const char * output, synctex_io_mode_t io_mode, synctex_bool_t add_quotes) { 548 synctex_open_s open = {SYNCTEX_STATUS_ERROR, NULL, NULL, io_mode}; 549 char * quoteless_synctex_name = NULL; 550 const char * mode = _synctex_get_io_mode_name(open.io_mode); 551 size_t size = strlen(output)+strlen(synctex_suffix)+strlen(synctex_suffix_gz)+1; 552 if (NULL == (open.synctex = (char *)malloc(size))) { 553 _synctex_error("! __synctex_open_v2: Memory problem (1)\n"); 554 return open; 555 } 556 /* we have reserved for synctex enough memory to copy output (including its 2 eventual quotes), both suffices, 557 * including the terminating character. size is free now. */ 558 if (open.synctex != strcpy(open.synctex,output)) { 559 _synctex_error("! __synctex_open_v2: Copy problem\n"); 560 return_on_error: 561 free(open.synctex); 562 open.synctex = NULL; 563 free(quoteless_synctex_name);/* We MUST have quoteless_synctex_name<>synctex_name */ 564 return open; 565 } 566 /* remove the last path extension if any */ 567 _synctex_strip_last_path_extension(open.synctex); 568 if (!strlen(open.synctex)) { 569 goto return_on_error; 570 } 571 /* now insert quotes. */ 572 if (add_quotes) { 573 char * quoted = NULL; 574 if (_synctex_copy_with_quoting_last_path_component(open.synctex,"ed,size) || quoted == NULL) { 575 /* There was an error or quoting does not make sense: */ 576 goto return_on_error; 577 } 578 quoteless_synctex_name = open.synctex; 579 open.synctex = quoted; 580 } 581 /* Now add to open.synctex the first path extension. */ 582 if (open.synctex != strcat(open.synctex,synctex_suffix)){ 583 _synctex_error("! __synctex_open_v2: Concatenation problem (can't add suffix '%s')\n",synctex_suffix); 584 goto return_on_error; 585 } 586 /* Add to quoteless_synctex_name as well, if relevant. */ 587 if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix))){ 588 free(quoteless_synctex_name); 589 quoteless_synctex_name = NULL; 590 } 591 if (NULL == (open.file = gzopen(open.synctex,mode))) { 592 /* Could not open this file */ 593 if (errno != ENOENT) { 594 /* The file does exist, this is a lower level error, I can't do anything. */ 595 _synctex_error("could not open %s, error %i\n",open.synctex,errno); 596 goto return_on_error; 597 } 598 /* Apparently, there is no uncompressed synctex file. Try the compressed version */ 599 if (open.synctex != strcat(open.synctex,synctex_suffix_gz)){ 600 _synctex_error("! __synctex_open_v2: Concatenation problem (can't add suffix '%s')\n",synctex_suffix_gz); 601 goto return_on_error; 602 } 603 open.io_mode |= synctex_io_gz_mask; 604 mode = _synctex_get_io_mode_name(open.io_mode); /* the file is a compressed and is a binary file, this caused errors on Windows */ 605 /* Add the suffix to the quoteless_synctex_name as well. */ 606 if (quoteless_synctex_name && (quoteless_synctex_name != strcat(quoteless_synctex_name,synctex_suffix_gz))){ 607 free(quoteless_synctex_name); 608 quoteless_synctex_name = NULL; 609 } 610 if (NULL == (open.file = gzopen(open.synctex,mode))) { 611 /* Could not open this file */ 612 if (errno != ENOENT) { 613 /* The file does exist, this is a lower level error, I can't do anything. */ 614 _synctex_error("Could not open %s, error %i\n",open.synctex,errno); 615 } 616 goto return_on_error; 617 } 618 } 619 /* At this point, the file is properly open. 620 * If we are in the add_quotes mode, we change the file name by removing the quotes. */ 621 if (quoteless_synctex_name) { 622 gzclose(open.file); 623 if (rename(open.synctex,quoteless_synctex_name)) { 624 _synctex_error("Could not rename %s to %s, error %i\n",open.synctex,quoteless_synctex_name,errno); 625 /* We could not rename, reopen the file with the quoted name. */ 626 if (NULL == (open.file = gzopen(open.synctex,mode))) { 627 /* No luck, could not re open this file, something has happened meanwhile */ 628 if (errno != ENOENT) { 629 /* The file does not exist any more, it has certainly be removed somehow 630 * this is a lower level error, I can't do anything. */ 631 _synctex_error("Could not open again %s, error %i\n",open.synctex,errno); 632 } 633 goto return_on_error; 634 } 635 } else { 636 /* The file has been successfully renamed */ 637 if (NULL == (open.file = gzopen(quoteless_synctex_name,mode))) { 638 /* Could not open this file */ 639 if (errno != ENOENT) { 640 /* The file does exist, this is a lower level error, I can't do anything. */ 641 _synctex_error("Could not open renamed %s, error %i\n",quoteless_synctex_name,errno); 642 } 643 goto return_on_error; 644 } 645 /* The quote free file name should replace the old one:*/ 646 free(open.synctex); 647 open.synctex = quoteless_synctex_name; 648 quoteless_synctex_name = NULL; 649 } 650 } 651 /* The operation is successful, return the arguments by value. */ 652 open.status = SYNCTEX_STATUS_OK; 653 return open; 654 } 655 656 /* Opens the output file, taking into account the eventual build_directory. 657 * - returns: an open structure which status is 658 * SYNCTEX_STATUS_OK on success, 659 * SYNCTEX_STATUS_ERROR on failure. 660 * - note: on success, the caller is the owner 661 * of the fields of the returned open structure. 662 */ 663 static synctex_open_s _synctex_open_v2(const char * output, const char * build_directory, synctex_io_mode_t io_mode, synctex_bool_t add_quotes) { 664 synctex_open_s open = __synctex_open_v2(output,io_mode,add_quotes); 665 if (open.status == SYNCTEX_STATUS_OK) { 666 return open; 667 } 668 if (build_directory && strlen(build_directory)) { 669 char * build_output; 670 const char *lpc; 671 size_t size; 672 synctex_bool_t is_absolute; 673 build_output = NULL; 674 lpc = _synctex_last_path_component(output); 675 size = strlen(build_directory)+strlen(lpc)+2; /* One for the '/' and one for the '\0'. */ 676 is_absolute = _synctex_path_is_absolute(build_directory); 677 if (!is_absolute) { 678 size += strlen(output); 679 } 680 if ((build_output = (char *)_synctex_malloc(size))) { 681 if (is_absolute) { 682 build_output[0] = '\0'; 683 } else { 684 if (build_output != strcpy(build_output,output)) { 685 _synctex_free(build_output); 686 return open; 687 } 688 build_output[lpc-output]='\0'; 689 } 690 if (build_output == strcat(build_output,build_directory)) { 691 /* Append a path separator if necessary. */ 692 if (!SYNCTEX_IS_PATH_SEPARATOR(build_output[strlen(build_directory)-1])) { 693 if (build_output != strcat(build_output,"/")) { 694 _synctex_free(build_output); 695 return open; 696 } 697 } 698 /* Append the last path component of the output. */ 699 if (build_output != strcat(build_output,lpc)) { 700 _synctex_free(build_output); 701 return open; 702 } 703 open = __synctex_open_v2(build_output,io_mode,add_quotes); 704 } 705 _synctex_free(build_output); 706 } /* if ((build_output... */ 707 } /* if (build_directory...) */ 708 return open; 709 } 710 void synctex_reader_free(synctex_reader_p reader) { 711 if (reader) { 712 _synctex_free(reader->output); 713 _synctex_free(reader->synctex); 714 _synctex_free(reader->start); 715 gzclose(reader->file); 716 _synctex_free(reader); 717 } 718 } 719 /* 720 * Return reader on success. 721 * Deallocate reader and return NULL on failure. 722 */ 723 synctex_reader_p synctex_reader_init_with_output_file(synctex_reader_p reader, const char * output, const char * build_directory) { 724 if (reader) { 725 /* now open the synctex file */ 726 synctex_open_s open = _synctex_open_v2(output,build_directory,0,synctex_ADD_QUOTES); 727 if (open.status<SYNCTEX_STATUS_OK) { 728 open = _synctex_open_v2(output,build_directory,0,synctex_DONT_ADD_QUOTES); 729 if (open.status<SYNCTEX_STATUS_OK) { 730 return NULL; 731 } 732 } 733 reader->synctex = open.synctex; 734 reader->file = open.file; 735 /* make a private copy of output */ 736 if (NULL == (reader->output = (char *)_synctex_malloc(strlen(output)+1))){ 737 _synctex_error("! synctex_scanner_new_with_output_file: Memory problem (2), reader's output is not reliable."); 738 } else if (reader->output != strcpy(reader->output,output)) { 739 _synctex_free(reader->output); 740 reader->output = NULL; 741 _synctex_error("! synctex_scanner_new_with_output_file: Copy problem, reader's output is not reliable."); 742 } 743 reader->start = reader->end = reader->current = NULL; 744 reader->min_size = SYNCTEX_BUFFER_MIN_SIZE; 745 reader->size = SYNCTEX_BUFFER_SIZE; 746 reader->start = reader->current = 747 (char *)_synctex_malloc(reader->size+1); /* one more character for null termination */ 748 if (NULL == reader->start) { 749 _synctex_error("! malloc error in synctex_reader_init_with_output_file."); 750 bailey: 751 #ifdef SYNCTEX_DEBUG 752 return reader; 753 #else 754 synctex_reader_free(reader); 755 return NULL; 756 #endif 757 } 758 reader->end = reader->start+reader->size; 759 /* reader->end always points to a null terminating character. 760 * Maybe there is another null terminating character between reader->current and reader->end-1. 761 * At least, we are sure that reader->current points to a string covering a valid part of the memory. */ 762 # if defined(SYNCTEX_USE_CHARINDEX) 763 reader->charindex_offset = -reader->size; 764 # endif 765 } 766 return reader; 767 } 768 769 # if defined(SYNCTEX_USE_HANDLE) 770 # define SYNCTEX_DECLARE_HANDLE synctex_node_p handle; 771 # else 772 # define SYNCTEX_DECLARE_HANDLE 773 # endif 774 775 # ifdef SYNCTEX_NOTHING 776 # pragma mark - 777 # pragma mark SCANNER 778 # endif 779 /** 780 * The synctex scanner is the root object. 781 * Is is initialized with the contents of a text file or a gzipped file. 782 * The buffer_.* are first used to parse the text. 783 */ 784 struct synctex_scanner_t { 785 synctex_reader_p reader; 786 SYNCTEX_DECLARE_NODE_COUNT 787 SYNCTEX_DECLARE_HANDLE 788 char * output_fmt; /* dvi or pdf, not yet used */ 789 synctex_iterator_p iterator;/* result iterator */ 790 int version; /* 1, not yet used */ 791 struct { 792 unsigned has_parsed:1; /* Whether the scanner has parsed its underlying synctex file. */ 793 unsigned postamble:1; /* Whether the scanner has parsed its underlying synctex file. */ 794 unsigned reserved:sizeof(unsigned)-2; /* alignment */ 795 } flags; 796 int pre_magnification; /* magnification from the synctex preamble */ 797 int pre_unit; /* unit from the synctex preamble */ 798 int pre_x_offset; /* X offset from the synctex preamble */ 799 int pre_y_offset; /* Y offset from the synctex preamble */ 800 int count; /* Number of records, from the synctex postamble */ 801 float unit; /* real unit, from synctex preamble or post scriptum */ 802 float x_offset; /* X offset, from synctex preamble or post scriptum */ 803 float y_offset; /* Y Offset, from synctex preamble or post scriptum */ 804 synctex_node_p input; /* The first input node, its siblings are the other input nodes */ 805 synctex_node_p sheet; /* The first sheet node, its siblings are the other sheet nodes */ 806 synctex_node_p form; /* The first form, its siblings are the other forms */ 807 synctex_node_p ref_in_sheet; /* The first form ref node in sheet, its friends are the other form ref nodes */ 808 synctex_node_p ref_in_form; /* The first form ref node, its friends are the other form ref nodes in sheet */ 809 int number_of_lists; /* The number of friend lists */ 810 synctex_node_r lists_of_friends;/* The friend lists */ 811 synctex_class_s class_[synctex_node_number_of_types]; /* The classes of the nodes of the scanner */ 812 int display_switcher; 813 char * display_prompt; 814 }; 815 816 /** 817 * Create a new node of the given type. 818 * - parameter scanner: of type synctex_node_p 819 * - parameter type: a type, the client is responsible 820 * to ask for an acceptable type. 821 */ 822 synctex_node_p synctex_node_new(synctex_scanner_p scanner, synctex_node_type_t type) { 823 return scanner? scanner->class_[type].new(scanner):NULL; 824 } 825 # if defined(SYNCTEX_USE_HANDLE) 826 SYNCTEX_INLINE static void __synctex_scanner_free_handle(synctex_scanner_p scanner) { 827 synctex_node_free(scanner->handle); 828 } 829 SYNCTEX_INLINE static void __synctex_scanner_remove_handle_to(synctex_node_p node) { 830 synctex_node_p arg_sibling = NULL; 831 synctex_node_p handle = node->class_->scanner->handle; 832 while (handle) { 833 synctex_node_p sibling; 834 if (node == _synctex_tree_target(handle)) { 835 sibling = __synctex_tree_reset_sibling(handle); 836 if (arg_sibling) { 837 __synctex_tree_set_sibling(arg_sibling, sibling); 838 } else { 839 node->class_->scanner->handle = sibling; 840 } 841 synctex_node_free(handle); 842 break; 843 } else { 844 sibling = __synctex_tree_sibling(handle); 845 } 846 arg_sibling = handle; 847 handle = sibling; 848 } 849 } 850 SYNCTEX_INLINE static void __synctex_scanner_register_handle_to(synctex_node_p node) { 851 synctex_node_p NNN = _synctex_new_handle_with_target(node); 852 __synctex_tree_set_sibling(NNN,node->class_->scanner->handle); 853 node->class_->scanner->handle = NNN; 854 } 855 #endif 856 #if SYNCTEX_USE_NODE_COUNT>10 857 SYNCTEX_INLINE static void _synctex_did_new(synctex_node_p node) { 858 printf("NODE CREATED # %i, %s, %p\n", 859 (node->class_->scanner->node_count)++, 860 synctex_node_isa(node), 861 node); 862 } 863 SYNCTEX_INLINE static void _synctex_will_free(synctex_node_p node) { 864 printf("NODE DELETED # %i, %s, %p\n", 865 --(node->class_->scanner->node_count), 866 synctex_node_isa(node), 867 node); 868 } 869 #endif 870 871 /** 872 * Free the given node. 873 * - parameter node: of type synctex_node_p 874 * - note: a node is meant to own its child and sibling. 875 * It is not owned by its parent, unless it is its first child. 876 * This destructor is for all nodes with children. 877 */ 878 static void _synctex_free_node(synctex_node_p node) { 879 if (node) { 880 SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node); 881 SYNCTEX_WILL_FREE(node); 882 synctex_node_free(__synctex_tree_sibling(node)); 883 synctex_node_free(_synctex_tree_child(node)); 884 _synctex_free(node); 885 } 886 return; 887 } 888 /** 889 * Free the given handle. 890 * - parameter node: of type synctex_node_p 891 * - note: a node is meant to own its child and sibling. 892 * It is not owned by its parent, unless it is its first child. 893 * This destructor is for all handles. 894 */ 895 static void _synctex_free_handle(synctex_node_p handle) { 896 if (handle) { 897 _synctex_free_handle(__synctex_tree_sibling(handle)); 898 _synctex_free_handle(_synctex_tree_child(handle)); 899 _synctex_free(handle); 900 } 901 return; 902 } 903 904 /** 905 * Free the given leaf node. 906 * - parameter node: of type synctex_node_p, with no child nor sibling. 907 * - note: a node is meant to own its child and sibling. 908 * It is not owned by its parent, unless it is its first child. 909 * This destructor is for all nodes with no children. 910 */ 911 static void _synctex_free_leaf(synctex_node_p node) { 912 if (node) { 913 SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node); 914 SYNCTEX_WILL_FREE(node); 915 synctex_node_free(__synctex_tree_sibling(node)); 916 _synctex_free(node); 917 } 918 return; 919 } 920 921 /** 922 SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts 923 */ 924 # define SYNCTEX_CUR (scanner->reader->current) 925 # define SYNCTEX_START (scanner->reader->start) 926 # define SYNCTEX_END (scanner->reader->end) 927 928 /* Here are gathered all the possible status that the next scanning functions will return. 929 * All these functions return a status, and pass their result through pointers. 930 * Negative values correspond to errors. 931 * The management of the buffer is causing some significant overhead. 932 * Every function that may access the buffer returns a status related to the buffer and file state. 933 * status >= SYNCTEX_STATUS_OK means the function worked as expected 934 * status < SYNCTEX_STATUS_OK means the function did not work as expected 935 * status == SYNCTEX_STATUS_NOT_OK means the function did not work as expected but there is still some material to parse. 936 * status == SYNCTEX_STATUS_EOF means the function did not work as expected and there is no more material. 937 * status<SYNCTEX_STATUS_EOF means an error 938 */ 939 #if defined(SYNCTEX_USE_CHARINDEX) 940 synctex_node_p synctex_scanner_handle(synctex_scanner_p scanner) { 941 return scanner? scanner->handle:NULL; 942 } 943 #endif 944 945 # ifdef SYNCTEX_NOTHING 946 # pragma mark - 947 # pragma mark Decoding prototypes 948 # endif 949 950 typedef struct { 951 int integer; 952 synctex_status_t status; 953 } synctex_is_s; 954 955 static synctex_is_s _synctex_decode_int(synctex_scanner_p scanner); 956 static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value); 957 static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner); 958 959 typedef struct { 960 char * string; 961 synctex_status_t status; 962 } synctex_ss_s; 963 964 static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner); 965 966 # ifdef SYNCTEX_NOTHING 967 # pragma mark - 968 # pragma mark Data SETGET 969 # endif 970 971 /** 972 * The next macros are used to access the node data info 973 * through the class modelator integer fields. 974 * - parameter NODE: of type synctex_node_p 975 */ 976 # define SYNCTEX_DATA(NODE) ((*((((NODE)->class_))->info))(NODE)) 977 #if defined SYNCTEX_DEBUG > 1000 978 # define DEFINE_SYNCTEX_DATA_HAS(WHAT) \ 979 SYNCTEX_INLINE static synctex_bool_t __synctex_data_has_##WHAT(synctex_node_p node) {\ 980 return (node && (node->class_->modelator->WHAT>=0));\ 981 }\ 982 SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node) {\ 983 if (node && (node->class_->modelator->WHAT<0)) {\ 984 printf("WARNING: NO %s for %s\n", #WHAT, synctex_node_isa(node));\ 985 }\ 986 return __synctex_data_has_##WHAT(node);\ 987 } 988 #else 989 # define DEFINE_SYNCTEX_DATA_HAS(WHAT) \ 990 SYNCTEX_INLINE static synctex_bool_t __synctex_data_has_##WHAT(synctex_node_p node) {\ 991 return (node && (node->class_->modelator->WHAT>=0));\ 992 }\ 993 SYNCTEX_INLINE static synctex_bool_t _synctex_data_has_##WHAT(synctex_node_p node) {\ 994 return __synctex_data_has_##WHAT(node);\ 995 } 996 #endif 997 998 SYNCTEX_INLINE static synctex_data_p __synctex_data(synctex_node_p node) { 999 return node->data+node->class_->navigator->size; 1000 } 1001 # define DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \ 1002 DEFINE_SYNCTEX_DATA_HAS(WHAT)\ 1003 static int _synctex_data_##WHAT(synctex_node_p node) {\ 1004 if (_synctex_data_has_##WHAT(node)) {\ 1005 return __synctex_data(node)[node->class_->modelator->WHAT].as_integer;\ 1006 }\ 1007 return 0;\ 1008 }\ 1009 static int _synctex_data_set_##WHAT(synctex_node_p node, int new_value) {\ 1010 int old = 0;\ 1011 if (_synctex_data_has_##WHAT(node)) {\ 1012 old = __synctex_data(node)[node->class_->modelator->WHAT].as_integer;\ 1013 __synctex_data(node)[node->class_->modelator->WHAT].as_integer=new_value;\ 1014 }\ 1015 return old;\ 1016 } 1017 #define DEFINE_SYNCTEX_DATA_INT_DECODE(WHAT) \ 1018 static synctex_status_t _synctex_data_decode_##WHAT(synctex_node_p node) {\ 1019 if (_synctex_data_has_##WHAT(node)) {\ 1020 synctex_is_s is = _synctex_decode_int(node->class_->scanner);\ 1021 if (is.status == SYNCTEX_STATUS_OK) {\ 1022 _synctex_data_set_##WHAT(node,is.integer);\ 1023 } \ 1024 return is.status;\ 1025 }\ 1026 return SYNCTEX_STATUS_BAD_ARGUMENT;\ 1027 } 1028 # define DEFINE_SYNCTEX_DATA_INT_DECODE_v(WHAT) \ 1029 static synctex_status_t _synctex_data_decode_##WHAT##_v(synctex_node_p node) {\ 1030 if (_synctex_data_has_##WHAT(node)) {\ 1031 synctex_is_s is = _synctex_decode_int_v(node->class_->scanner);\ 1032 if (is.status == SYNCTEX_STATUS_OK) {\ 1033 _synctex_data_set_##WHAT(node,is.integer);\ 1034 } \ 1035 return is.status;\ 1036 }\ 1037 return SYNCTEX_STATUS_BAD_ARGUMENT;\ 1038 } 1039 #define DEFINE_SYNCTEX_DATA_STR_GETSET(WHAT) \ 1040 DEFINE_SYNCTEX_DATA_HAS(WHAT)\ 1041 static char * _synctex_data_##WHAT(synctex_node_p node) {\ 1042 if (_synctex_data_has_##WHAT(node)) {\ 1043 return node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string;\ 1044 }\ 1045 return NULL;\ 1046 }\ 1047 static char * _synctex_data_set_##WHAT(synctex_node_p node, char * new_value) {\ 1048 char * old = "";\ 1049 if (_synctex_data_has_##WHAT(node)) {\ 1050 old = node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string;\ 1051 node->data[node->class_->navigator->size+node->class_->modelator->WHAT].as_string =new_value;\ 1052 }\ 1053 return old;\ 1054 } 1055 #define DEFINE_SYNCTEX_DATA_STR_DECODE(WHAT) \ 1056 static synctex_status_t _synctex_data_decode_##WHAT(synctex_node_p node) {\ 1057 if (_synctex_data_has_##WHAT(node)) {\ 1058 synctex_ss_s ss = _synctex_decode_string(node->class_->scanner);\ 1059 if (ss.status == SYNCTEX_STATUS_OK) {\ 1060 _synctex_data_set_##WHAT(node,ss.string);\ 1061 } \ 1062 return ss.status;\ 1063 }\ 1064 return SYNCTEX_STATUS_BAD_ARGUMENT;\ 1065 } 1066 #define DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(WHAT) \ 1067 DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \ 1068 DEFINE_SYNCTEX_DATA_INT_DECODE(WHAT) 1069 #define DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE_v(WHAT) \ 1070 DEFINE_SYNCTEX_DATA_INT_GETSET(WHAT) \ 1071 DEFINE_SYNCTEX_DATA_INT_DECODE_v(WHAT) 1072 #define DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(WHAT) \ 1073 DEFINE_SYNCTEX_DATA_STR_GETSET(WHAT) \ 1074 DEFINE_SYNCTEX_DATA_STR_DECODE(WHAT) 1075 1076 # ifdef SYNCTEX_NOTHING 1077 # pragma mark - 1078 # pragma mark OBJECTS, their creators and destructors. 1079 # endif 1080 1081 # ifdef SYNCTEX_NOTHING 1082 # pragma mark input. 1083 # endif 1084 1085 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(tag) 1086 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(line) 1087 DEFINE_SYNCTEX_DATA_STR_GETSET_DECODE(name) 1088 1089 /* Input nodes only know about their sibling, which is another input node. 1090 * The synctex information is the _synctex_data_tag and _synctex_data_name 1091 * note: the input owns its name. */ 1092 1093 # define SYNCTEX_INPUT_MARK "Input:" 1094 1095 static const synctex_tree_model_s synctex_tree_model_input = { 1096 synctex_tree_sibling_idx, /* sibling */ 1097 -1, /* parent */ 1098 -1, /* child */ 1099 -1, /* friend */ 1100 -1, /* last */ 1101 -1, /* next_hbox */ 1102 -1, /* arg_sibling */ 1103 -1, /* target */ 1104 synctex_tree_s_input_max 1105 }; 1106 static const synctex_data_model_s synctex_data_model_input = { 1107 synctex_data_input_tag_idx, /* tag */ 1108 synctex_data_input_line_idx,/* line */ 1109 -1, /* column */ 1110 -1, /* h */ 1111 -1, /* v */ 1112 -1, /* width */ 1113 -1, /* height */ 1114 -1, /* depth */ 1115 -1, /* mean_line */ 1116 -1, /* weight */ 1117 -1, /* h_V */ 1118 -1, /* v_V */ 1119 -1, /* width_V */ 1120 -1, /* height_V */ 1121 -1, /* depth_V */ 1122 synctex_data_input_name_idx, /* name */ 1123 -1, /* page */ 1124 synctex_data_input_tln_max 1125 }; 1126 1127 #define SYNCTEX_INSPECTOR_GETTER_F(WHAT)\ 1128 &_synctex_data_##WHAT, &_synctex_data_set_##WHAT 1129 1130 static synctex_node_p _synctex_new_input(synctex_scanner_p scanner); 1131 static void _synctex_free_input(synctex_node_p node); 1132 static void _synctex_log_input(synctex_node_p node); 1133 static char * _synctex_abstract_input(synctex_node_p node); 1134 static void _synctex_display_input(synctex_node_p node); 1135 1136 static const synctex_tlcpector_s synctex_tlcpector_input = { 1137 &_synctex_data_tag, /* tag */ 1138 &_synctex_int_none, /* line */ 1139 &_synctex_int_none, /* column */ 1140 }; 1141 1142 static synctex_class_s synctex_class_input = { 1143 NULL, /* No scanner yet */ 1144 synctex_node_type_input, /* Node type */ 1145 &_synctex_new_input, /* creator */ 1146 &_synctex_free_input, /* destructor */ 1147 &_synctex_log_input, /* log */ 1148 &_synctex_display_input, /* display */ 1149 &_synctex_abstract_input, /* abstract */ 1150 &synctex_tree_model_input, /* tree model */ 1151 &synctex_data_model_input, /* data model */ 1152 &synctex_tlcpector_input, /* inspector */ 1153 &synctex_inspector_none, /* inspector */ 1154 &synctex_vispector_none, /* vispector */ 1155 }; 1156 1157 typedef struct { 1158 SYNCTEX_DECLARE_CHARINDEX 1159 synctex_class_p class_; 1160 synctex_data_u data[synctex_tree_s_input_max+synctex_data_input_tln_max]; 1161 } synctex_input_s; 1162 1163 static synctex_node_p _synctex_new_input(synctex_scanner_p scanner) { 1164 if (scanner) { 1165 synctex_node_p node = _synctex_malloc(sizeof(synctex_input_s)); 1166 if (node) { 1167 node->class_ = scanner->class_+synctex_node_type_input; 1168 SYNCTEX_DID_NEW(node); 1169 SYNCTEX_IMPLEMENT_CHARINDEX(node,0); 1170 SYNCTEX_REGISTER_HANDLE_TO(node); 1171 } 1172 return node; 1173 } 1174 return NULL; 1175 } 1176 1177 static void _synctex_free_input(synctex_node_p node){ 1178 if (node) { 1179 SYNCTEX_SCANNER_REMOVE_HANDLE_TO(node); 1180 SYNCTEX_WILL_FREE(node); 1181 synctex_node_free(__synctex_tree_sibling(node)); 1182 _synctex_free(_synctex_data_name(node)); 1183 _synctex_free(node); 1184 } 1185 } 1186 1187 /* The sheet is a first level node. 1188 * It has no parent (the owner is the scanner itself) 1189 * Its sibling points to another sheet. 1190 * Its child points to its first child, in general a box. 1191 * A sheet node contains only one synctex information: the page. 1192 * This is the 1 based page index as given by TeX. 1193 */ 1194 1195 # ifdef SYNCTEX_NOTHING 1196 # pragma mark sheet. 1197 # endif 1198 /** 1199 * Every node has the same structure, but not the same size. 1200 */ 1201 1202 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(page) 1203 1204 typedef struct { 1205 SYNCTEX_DECLARE_CHARINDEX 1206 synctex_class_p class_; 1207 synctex_data_u data[synctex_tree_scn_sheet_max+synctex_data_p_sheet_max]; 1208 } synctex_node_sheet_s; 1209 1210 /* sheet node creator */ 1211 1212 #define DEFINE_synctex_new_scanned_NODE(NAME)\ 1213 static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner) {\ 1214 if (scanner) {\ 1215 ++SYNCTEX_CUR;\ 1216 synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));\ 1217 if (node) {\ 1218 node->class_ = scanner->class_+synctex_node_type_##NAME;\ 1219 SYNCTEX_DID_NEW(node); \ 1220 SYNCTEX_IMPLEMENT_CHARINDEX(node,-1);\ 1221 SYNCTEX_REGISTER_HANDLE_TO(node); \ 1222 }\ 1223 return node;\ 1224 }\ 1225 return NULL;\ 1226 } 1227 /* NB: -1 in SYNCTEX_IMPLEMENT_CHARINDEX above because 1228 * the first char of the line has been scanned 1229 */ 1230 DEFINE_synctex_new_scanned_NODE(sheet) 1231 static void _synctex_log_sheet(synctex_node_p node); 1232 static char * _synctex_abstract_sheet(synctex_node_p node); 1233 static void _synctex_display_sheet(synctex_node_p node); 1234 1235 static const synctex_tree_model_s synctex_tree_model_sheet = { 1236 synctex_tree_sibling_idx, /* sibling */ 1237 -1, /* parent */ 1238 synctex_tree_s_child_idx, /* child */ 1239 -1, /* friend */ 1240 -1, /* last */ 1241 synctex_tree_sc_next_hbox_idx, /* next_hbox */ 1242 -1, /* arg_sibling */ 1243 -1, /* target */ 1244 synctex_tree_scn_sheet_max 1245 }; 1246 static const synctex_data_model_s synctex_data_model_sheet = { 1247 -1, /* tag */ 1248 -1, /* line */ 1249 -1, /* column */ 1250 -1, /* h */ 1251 -1, /* v */ 1252 -1, /* width */ 1253 -1, /* height */ 1254 -1, /* depth */ 1255 -1, /* mean_line */ 1256 -1, /* weight */ 1257 -1, /* h_V */ 1258 -1, /* v_V */ 1259 -1, /* width_V */ 1260 -1, /* height_V */ 1261 -1, /* depth_V */ 1262 -1, /* name */ 1263 synctex_data_sheet_page_idx, /* page */ 1264 synctex_data_p_sheet_max 1265 }; 1266 static synctex_class_s synctex_class_sheet = { 1267 NULL, /* No scanner yet */ 1268 synctex_node_type_sheet, /* Node type */ 1269 &_synctex_new_sheet, /* creator */ 1270 &_synctex_free_node, /* destructor */ 1271 &_synctex_log_sheet, /* log */ 1272 &_synctex_display_sheet, /* display */ 1273 &_synctex_abstract_sheet, /* abstract */ 1274 &synctex_tree_model_sheet, /* tree model */ 1275 &synctex_data_model_sheet, /* data model */ 1276 &synctex_tlcpector_none, /* tlcpector */ 1277 &synctex_inspector_none, /* inspector */ 1278 &synctex_vispector_none, /* vispector */ 1279 }; 1280 1281 # ifdef SYNCTEX_NOTHING 1282 # pragma mark form. 1283 # endif 1284 /** 1285 * Every node has the same structure, but not the same size. 1286 */ 1287 typedef struct { 1288 SYNCTEX_DECLARE_CHARINDEX 1289 synctex_class_p class_; 1290 synctex_data_u data[synctex_tree_sct_form_max+synctex_data_t_form_max]; 1291 } synctex_node_form_s; 1292 1293 DEFINE_synctex_new_scanned_NODE(form) 1294 1295 static char * _synctex_abstract_form(synctex_node_p node); 1296 static void _synctex_display_form(synctex_node_p node); 1297 static void _synctex_log_form(synctex_node_p node); 1298 1299 static const synctex_tree_model_s synctex_tree_model_form = { 1300 synctex_tree_sibling_idx, /* sibling */ 1301 -1, /* parent */ 1302 synctex_tree_s_child_idx, /* child */ 1303 -1, /* friend */ 1304 -1, /* last */ 1305 -1, /* next_hbox */ 1306 -1, /* arg_sibling */ 1307 synctex_tree_sc_target_idx, /* target */ 1308 synctex_tree_sct_form_max 1309 }; 1310 static const synctex_data_model_s synctex_data_model_form = { 1311 synctex_data_form_tag_idx, /* tag */ 1312 -1, /* line */ 1313 -1, /* column */ 1314 -1, /* h */ 1315 -1, /* v */ 1316 -1, /* width */ 1317 -1, /* height */ 1318 -1, /* depth */ 1319 -1, /* mean_line */ 1320 -1, /* weight */ 1321 -1, /* h_V */ 1322 -1, /* v_V */ 1323 -1, /* width_V */ 1324 -1, /* height_V */ 1325 -1, /* depth_V */ 1326 -1, /* name */ 1327 -1, /* page */ 1328 synctex_data_t_form_max 1329 }; 1330 static synctex_class_s synctex_class_form = { 1331 NULL, /* No scanner yet */ 1332 synctex_node_type_form, /* Node type */ 1333 &_synctex_new_form, /* creator */ 1334 &_synctex_free_node, /* destructor */ 1335 &_synctex_log_form, /* log */ 1336 &_synctex_display_form, /* display */ 1337 &_synctex_abstract_form, /* abstract */ 1338 &synctex_tree_model_form, /* tree model */ 1339 &synctex_data_model_form, /* data model */ 1340 &synctex_tlcpector_none, /* tlcpector */ 1341 &synctex_inspector_none, /* inspector */ 1342 &synctex_vispector_none, /* vispector */ 1343 }; 1344 1345 # ifdef SYNCTEX_NOTHING 1346 # pragma mark vbox. 1347 # endif 1348 1349 /* A box node contains navigation and synctex information 1350 * There are different kinds of boxes. 1351 * Only horizontal boxes are treated differently because of their visible size. 1352 */ 1353 typedef struct { 1354 SYNCTEX_DECLARE_CHARINDEX 1355 synctex_class_p class_; 1356 synctex_data_u data[synctex_tree_spcfl_vbox_max+synctex_data_box_max]; 1357 } synctex_node_vbox_s; 1358 1359 /* vertical box node creator */ 1360 DEFINE_synctex_new_scanned_NODE(vbox) 1361 1362 static char * _synctex_abstract_vbox(synctex_node_p node); 1363 static void _synctex_display_vbox(synctex_node_p node); 1364 static void _synctex_log_vbox(synctex_node_p node); 1365 1366 static const synctex_tree_model_s synctex_tree_model_vbox = { 1367 synctex_tree_sibling_idx, /* sibling */ 1368 synctex_tree_s_parent_idx, /* parent */ 1369 synctex_tree_sp_child_idx, /* child */ 1370 synctex_tree_spc_friend_idx, /* friend */ 1371 synctex_tree_spcf_last_idx, /* last */ 1372 -1, /* next_hbox */ 1373 -1, /* arg_sibling */ 1374 -1, /* target */ 1375 synctex_tree_spcfl_vbox_max 1376 }; 1377 1378 #define SYNCTEX_DFLT_COLUMN -1 1379 1380 DEFINE_SYNCTEX_DATA_INT_GETSET(column) 1381 static synctex_status_t _synctex_data_decode_column(synctex_node_p node) { 1382 if (_synctex_data_has_column(node)) { 1383 synctex_is_s is = _synctex_decode_int_opt(node->class_->scanner, 1384 SYNCTEX_DFLT_COLUMN); 1385 if (is.status == SYNCTEX_STATUS_OK) { 1386 _synctex_data_set_column(node,is.integer); 1387 } 1388 return is.status; 1389 } 1390 return SYNCTEX_STATUS_BAD_ARGUMENT; 1391 } 1392 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(h) 1393 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE_v(v) 1394 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(width) 1395 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(height) 1396 DEFINE_SYNCTEX_DATA_INT_GETSET_DECODE(depth) 1397 1398 SYNCTEX_INLINE static void _synctex_data_set_tlc(synctex_node_p node, synctex_node_p model) { 1399 _synctex_data_set_tag(node, _synctex_data_tag(model)); 1400 _synctex_data_set_line(node, _synctex_data_line(model)); 1401 _synctex_data_set_column(node, _synctex_data_column(model)); 1402 } 1403 SYNCTEX_INLINE static void _synctex_data_set_tlchv(synctex_node_p node, synctex_node_p model) { 1404 _synctex_data_set_tlc(node,model); 1405 _synctex_data_set_h(node, _synctex_data_h(model)); 1406 _synctex_data_set_v(node, _synctex_data_v(model)); 1407 } 1408 1409 static const synctex_data_model_s synctex_data_model_box = { 1410 synctex_data_tag_idx, /* tag */ 1411 synctex_data_line_idx, /* line */ 1412 synctex_data_column_idx,/* column */ 1413 synctex_data_h_idx, /* h */ 1414 synctex_data_v_idx, /* v */ 1415 synctex_data_width_idx, /* width */ 1416 synctex_data_height_idx,/* height */ 1417 synctex_data_depth_idx, /* depth */ 1418 -1, /* mean_line */ 1419 -1, /* weight */ 1420 -1, /* h_V */ 1421 -1, /* v_V */ 1422 -1, /* width_V */ 1423 -1, /* height_V */ 1424 -1, /* depth_V */ 1425 -1, /* name */ 1426 -1, /* page */ 1427 synctex_data_box_max 1428 }; 1429 static const synctex_tlcpector_s synctex_tlcpector_default = { 1430 &_synctex_data_tag, /* tag */ 1431 &_synctex_data_line, /* line */ 1432 &_synctex_data_column, /* column */ 1433 }; 1434 static const synctex_inspector_s synctex_inspector_box = { 1435 &_synctex_data_h, 1436 &_synctex_data_v, 1437 &_synctex_data_width, 1438 &_synctex_data_height, 1439 &_synctex_data_depth, 1440 }; 1441 static float __synctex_node_visible_h(synctex_node_p node); 1442 static float __synctex_node_visible_v(synctex_node_p node); 1443 static float __synctex_node_visible_width(synctex_node_p node); 1444 static float __synctex_node_visible_height(synctex_node_p node); 1445 static float __synctex_node_visible_depth(synctex_node_p node); 1446 static synctex_vispector_s synctex_vispector_box = { 1447 &__synctex_node_visible_h, 1448 &__synctex_node_visible_v, 1449 &__synctex_node_visible_width, 1450 &__synctex_node_visible_height, 1451 &__synctex_node_visible_depth, 1452 }; 1453 /* These are static class objects, each scanner will make a copy of them and setup the scanner field. 1454 */ 1455 static synctex_class_s synctex_class_vbox = { 1456 NULL, /* No scanner yet */ 1457 synctex_node_type_vbox, /* Node type */ 1458 &_synctex_new_vbox, /* creator */ 1459 &_synctex_free_node, /* destructor */ 1460 &_synctex_log_vbox, /* log */ 1461 &_synctex_display_vbox, /* display */ 1462 &_synctex_abstract_vbox, /* abstract */ 1463 &synctex_tree_model_vbox, /* tree model */ 1464 &synctex_data_model_box, /* data model */ 1465 &synctex_tlcpector_default, /* tlcpector */ 1466 &synctex_inspector_box, /* inspector */ 1467 &synctex_vispector_box, /* vispector */ 1468 }; 1469 1470 # ifdef SYNCTEX_NOTHING 1471 # pragma mark hbox. 1472 # endif 1473 1474 /* Horizontal boxes must contain visible size, because 0 width does not mean emptiness. 1475 * They also contain an average of the line numbers of the containing nodes. */ 1476 1477 static const synctex_tree_model_s synctex_tree_model_hbox = { 1478 synctex_tree_sibling_idx, /* sibling */ 1479 synctex_tree_s_parent_idx, /* parent */ 1480 synctex_tree_sp_child_idx, /* child */ 1481 synctex_tree_spc_friend_idx, /* friend */ 1482 synctex_tree_spcf_last_idx, /* last */ 1483 synctex_tree_spcfl_next_hbox_idx, /* next_hbox */ 1484 -1, /* arg_sibling */ 1485 -1, /* target */ 1486 synctex_tree_spcfln_hbox_max 1487 }; 1488 1489 DEFINE_SYNCTEX_DATA_INT_GETSET(mean_line) 1490 DEFINE_SYNCTEX_DATA_INT_GETSET(weight) 1491 DEFINE_SYNCTEX_DATA_INT_GETSET(h_V) 1492 DEFINE_SYNCTEX_DATA_INT_GETSET(v_V) 1493 DEFINE_SYNCTEX_DATA_INT_GETSET(width_V) 1494 DEFINE_SYNCTEX_DATA_INT_GETSET(height_V) 1495 DEFINE_SYNCTEX_DATA_INT_GETSET(depth_V) 1496 1497 /** 1498 * The hbox model. 1499 * It contains V variants of geometrical information. 1500 * It happens that hboxes contain material that is not used to compute 1501 * the bounding box. Some letters may appear out of the box given by TeX. 1502 * In such a situation, the visible bounding box is bigger ence the V variant. 1503 * Only hboxes have such variant. It does not make sense for void boxes 1504 * and it is not used here for vboxes. 1505 * - author: JL 1506 */ 1507 1508 static const synctex_data_model_s synctex_data_model_hbox = { 1509 synctex_data_tag_idx, /* tag */ 1510 synctex_data_line_idx, /* line */ 1511 synctex_data_column_idx,/* column */ 1512 synctex_data_h_idx, /* h */ 1513 synctex_data_v_idx, /* v */ 1514 synctex_data_width_idx, /* width */ 1515 synctex_data_height_idx,/* height */ 1516 synctex_data_depth_idx, /* depth */ 1517 synctex_data_mean_line_idx, /* mean_line */ 1518 synctex_data_weight_idx, /* weight */ 1519 synctex_data_h_V_idx, /* h_V */ 1520 synctex_data_v_V_idx, /* v_V */ 1521 synctex_data_width_V_idx, /* width_V */ 1522 synctex_data_height_V_idx, /* height_V */ 1523 synctex_data_depth_V_idx, /* depth_V */ 1524 -1, /* name */ 1525 -1, /* page */ 1526 synctex_data_hbox_max 1527 }; 1528 1529 typedef struct { 1530 SYNCTEX_DECLARE_CHARINDEX 1531 synctex_class_p class_; 1532 synctex_data_u data[synctex_tree_spcfln_hbox_max+synctex_data_hbox_max]; 1533 } synctex_node_hbox_s; 1534 1535 /* horizontal box node creator */ 1536 DEFINE_synctex_new_scanned_NODE(hbox) 1537 1538 static void _synctex_log_hbox(synctex_node_p node); 1539 static char * _synctex_abstract_hbox(synctex_node_p node); 1540 static void _synctex_display_hbox(synctex_node_p node); 1541 1542 static synctex_class_s synctex_class_hbox = { 1543 NULL, /* No scanner yet */ 1544 synctex_node_type_hbox, /* Node type */ 1545 &_synctex_new_hbox, /* creator */ 1546 &_synctex_free_node, /* destructor */ 1547 &_synctex_log_hbox, /* log */ 1548 &_synctex_display_hbox, /* display */ 1549 &_synctex_abstract_hbox, /* abstract */ 1550 &synctex_tree_model_hbox, /* tree model */ 1551 &synctex_data_model_hbox, /* data model */ 1552 &synctex_tlcpector_default, /* tlcpector */ 1553 &synctex_inspector_box, /* inspector */ 1554 &synctex_vispector_box, /* vispector */ 1555 }; 1556 1557 # ifdef SYNCTEX_NOTHING 1558 # pragma mark void vbox. 1559 # endif 1560 1561 /* This void box node implementation is either horizontal or vertical 1562 * It does not contain a child field. 1563 */ 1564 static const synctex_tree_model_s synctex_tree_model_spf = { 1565 synctex_tree_sibling_idx, /* sibling */ 1566 synctex_tree_s_parent_idx, /* parent */ 1567 -1, /* child */ 1568 synctex_tree_sp_friend_idx, /* friend */ 1569 -1, /* last */ 1570 -1, /* next_hbox */ 1571 -1, /* arg_sibling */ 1572 -1, /* target */ 1573 synctex_tree_spf_max 1574 }; 1575 typedef struct { 1576 SYNCTEX_DECLARE_CHARINDEX 1577 synctex_class_p class_; 1578 synctex_data_u data[synctex_tree_spf_max+synctex_data_box_max]; 1579 } synctex_node_void_vbox_s; 1580 1581 /* vertical void box node creator */ 1582 DEFINE_synctex_new_scanned_NODE(void_vbox) 1583 1584 static void _synctex_log_void_box(synctex_node_p node); 1585 static char * _synctex_abstract_void_vbox(synctex_node_p node); 1586 static void _synctex_display_void_vbox(synctex_node_p node); 1587 1588 static synctex_class_s synctex_class_void_vbox = { 1589 NULL, /* No scanner yet */ 1590 synctex_node_type_void_vbox,/* Node type */ 1591 &_synctex_new_void_vbox, /* creator */ 1592 &_synctex_free_leaf, /* destructor */ 1593 &_synctex_log_void_box, /* log */ 1594 &_synctex_display_void_vbox,/* display */ 1595 &_synctex_abstract_void_vbox,/* abstract */ 1596 &synctex_tree_model_spf, /* tree model */ 1597 &synctex_data_model_box, /* data model */ 1598 &synctex_tlcpector_default, /* tlcpector */ 1599 &synctex_inspector_box, /* inspector */ 1600 &synctex_vispector_box, /* vispector */ 1601 }; 1602 1603 # ifdef SYNCTEX_NOTHING 1604 # pragma mark void hbox. 1605 # endif 1606 1607 typedef synctex_node_void_vbox_s synctex_node_void_hbox_s; 1608 1609 /* horizontal void box node creator */ 1610 DEFINE_synctex_new_scanned_NODE(void_hbox) 1611 1612 static char * _synctex_abstract_void_hbox(synctex_node_p node); 1613 static void _synctex_display_void_hbox(synctex_node_p node); 1614 1615 static synctex_class_s synctex_class_void_hbox = { 1616 NULL, /* No scanner yet */ 1617 synctex_node_type_void_hbox,/* Node type */ 1618 &_synctex_new_void_hbox, /* creator */ 1619 &_synctex_free_leaf, /* destructor */ 1620 &_synctex_log_void_box, /* log */ 1621 &_synctex_display_void_hbox,/* display */ 1622 &_synctex_abstract_void_hbox,/* abstract */ 1623 &synctex_tree_model_spf, /* tree model */ 1624 &synctex_data_model_box, /* data model */ 1625 &synctex_tlcpector_default, /* tlcpector */ 1626 &synctex_inspector_box, /* inspector */ 1627 &synctex_vispector_box, /* vispector */ 1628 }; 1629 1630 # ifdef SYNCTEX_NOTHING 1631 # pragma mark form ref. 1632 # endif 1633 1634 /* The form ref node. */ 1635 typedef struct { 1636 SYNCTEX_DECLARE_CHARINDEX 1637 synctex_class_p class_; 1638 synctex_data_u data[synctex_tree_spfa_max+synctex_data_ref_thv_max]; 1639 } synctex_node_ref_s; 1640 1641 /* form ref node creator */ 1642 DEFINE_synctex_new_scanned_NODE(ref) 1643 1644 static void _synctex_log_ref(synctex_node_p node); 1645 static char * _synctex_abstract_ref(synctex_node_p node); 1646 static void _synctex_display_ref(synctex_node_p node); 1647 1648 static const synctex_tree_model_s synctex_tree_model_spfa = { 1649 synctex_tree_sibling_idx, /* sibling */ 1650 synctex_tree_s_parent_idx, /* parent */ 1651 -1, /* child */ 1652 synctex_tree_sp_friend_idx, /* friend */ 1653 -1, /* last */ 1654 -1, /* next_hbox */ 1655 synctex_tree_spf_arg_sibling_idx, /* arg_sibling */ 1656 -1, /* target */ 1657 synctex_tree_spfa_max 1658 }; 1659 static const synctex_data_model_s synctex_data_model_ref = { 1660 synctex_data_tag_idx, /* tag */ 1661 -1, /* line */ 1662 -1, /* column */ 1663 synctex_data_ref_h_idx, /* h */ 1664 synctex_data_ref_v_idx, /* v */ 1665 -1, /* width */ 1666 -1, /* height */ 1667 -1, /* depth */ 1668 -1, /* mean_line */ 1669 -1, /* weight */ 1670 -1, /* h_V */ 1671 -1, /* v_V */ 1672 -1, /* width_V */ 1673 -1, /* height_V */ 1674 -1, /* depth_V */ 1675 -1, /* name */ 1676 -1, /* page */ 1677 synctex_data_ref_thv_max /* size */ 1678 }; 1679 static synctex_class_s synctex_class_ref = { 1680 NULL, /* No scanner yet */ 1681 synctex_node_type_ref, /* Node type */ 1682 &_synctex_new_ref, /* creator */ 1683 &_synctex_free_leaf, /* destructor */ 1684 &_synctex_log_ref, /* log */ 1685 &_synctex_display_ref, /* display */ 1686 &_synctex_abstract_ref, /* abstract */ 1687 &synctex_tree_model_spfa, /* navigator */ 1688 &synctex_data_model_ref, /* data model */ 1689 &synctex_tlcpector_none, /* tlcpector */ 1690 &synctex_inspector_none, /* inspector */ 1691 &synctex_vispector_none, /* vispector */ 1692 }; 1693 # ifdef SYNCTEX_NOTHING 1694 # pragma mark small node. 1695 # endif 1696 1697 /* The small nodes correspond to glue, penalty, math and boundary nodes. */ 1698 static const synctex_data_model_s synctex_data_model_tlchv = { 1699 synctex_data_tag_idx, /* tag */ 1700 synctex_data_line_idx, /* line */ 1701 synctex_data_column_idx, /* column */ 1702 synctex_data_h_idx, /* h */ 1703 synctex_data_v_idx, /* v */ 1704 -1, /* width */ 1705 -1, /* height */ 1706 -1, /* depth */ 1707 -1, /* mean_line */ 1708 -1, /* weight */ 1709 -1, /* h_V */ 1710 -1, /* v_V */ 1711 -1, /* width_V */ 1712 -1, /* height_V */ 1713 -1, /* depth_V */ 1714 -1, /* name */ 1715 -1, /* page */ 1716 synctex_data_tlchv_max 1717 }; 1718 1719 typedef struct { 1720 SYNCTEX_DECLARE_CHARINDEX 1721 synctex_class_p class_; 1722 synctex_data_u data[synctex_tree_spf_max+synctex_data_tlchv_max]; 1723 } synctex_node_tlchv_s; 1724 1725 static void _synctex_log_tlchv_node(synctex_node_p node); 1726 1727 # ifdef SYNCTEX_NOTHING 1728 # pragma mark math. 1729 # endif 1730 1731 typedef synctex_node_tlchv_s synctex_node_math_s; 1732 1733 /* math node creator */ 1734 DEFINE_synctex_new_scanned_NODE(math) 1735 1736 static char * _synctex_abstract_math(synctex_node_p node); 1737 static void _synctex_display_math(synctex_node_p node); 1738 static synctex_inspector_s synctex_inspector_hv = { 1739 &_synctex_data_h, 1740 &_synctex_data_v, 1741 &_synctex_int_none, 1742 &_synctex_int_none, 1743 &_synctex_int_none, 1744 }; 1745 static synctex_vispector_s synctex_vispector_hv = { 1746 &__synctex_node_visible_h, 1747 &__synctex_node_visible_v, 1748 &_synctex_float_none, 1749 &_synctex_float_none, 1750 &_synctex_float_none, 1751 }; 1752 1753 static synctex_class_s synctex_class_math = { 1754 NULL, /* No scanner yet */ 1755 synctex_node_type_math, /* Node type */ 1756 &_synctex_new_math, /* creator */ 1757 &_synctex_free_leaf, /* destructor */ 1758 &_synctex_log_tlchv_node, /* log */ 1759 &_synctex_display_math, /* display */ 1760 &_synctex_abstract_math, /* abstract */ 1761 &synctex_tree_model_spf, /* tree model */ 1762 &synctex_data_model_tlchv, /* data model */ 1763 &synctex_tlcpector_default, /* tlcpector */ 1764 &synctex_inspector_hv, /* inspector */ 1765 &synctex_vispector_hv, /* vispector */ 1766 }; 1767 1768 # ifdef SYNCTEX_NOTHING 1769 # pragma mark kern node. 1770 # endif 1771 1772 static const synctex_data_model_s synctex_data_model_tlchvw = { 1773 synctex_data_tag_idx, /* tag */ 1774 synctex_data_line_idx, /* line */ 1775 synctex_data_column_idx,/* column */ 1776 synctex_data_h_idx, /* h */ 1777 synctex_data_v_idx, /* v */ 1778 synctex_data_width_idx, /* width */ 1779 -1, /* height */ 1780 -1, /* depth */ 1781 -1, /* mean_line */ 1782 -1, /* weight */ 1783 -1, /* h_V */ 1784 -1, /* v_V */ 1785 -1, /* width_V */ 1786 -1, /* height_V */ 1787 -1, /* depth_V */ 1788 -1, /* name */ 1789 -1, /* page */ 1790 synctex_data_tlchvw_max 1791 }; 1792 typedef struct { 1793 SYNCTEX_DECLARE_CHARINDEX 1794 synctex_class_p class_; 1795 synctex_data_u data[synctex_tree_spf_max+synctex_data_tlchvw_max]; 1796 } synctex_node_kern_s; 1797 1798 /* kern node creator */ 1799 DEFINE_synctex_new_scanned_NODE(kern) 1800 1801 static void _synctex_log_kern_node(synctex_node_p node); 1802 static char * _synctex_abstract_kern(synctex_node_p node); 1803 static void _synctex_display_kern(synctex_node_p node); 1804 1805 static synctex_inspector_s synctex_inspector_kern = { 1806 &_synctex_data_h, 1807 &_synctex_data_v, 1808 &_synctex_data_width, 1809 &_synctex_int_none, 1810 &_synctex_int_none, 1811 }; 1812 static float __synctex_kern_visible_h(synctex_node_p node); 1813 static float __synctex_kern_visible_width(synctex_node_p node); 1814 static synctex_vispector_s synctex_vispector_kern = { 1815 &__synctex_kern_visible_h, 1816 &__synctex_node_visible_v, 1817 &__synctex_kern_visible_width, 1818 &_synctex_float_none, 1819 &_synctex_float_none, 1820 }; 1821 1822 static synctex_class_s synctex_class_kern = { 1823 NULL, /* No scanner yet */ 1824 synctex_node_type_kern, /* Node type */ 1825 &_synctex_new_kern, /* creator */ 1826 &_synctex_free_leaf, /* destructor */ 1827 &_synctex_log_kern_node, /* log */ 1828 &_synctex_display_kern, /* display */ 1829 &_synctex_abstract_kern, /* abstract */ 1830 &synctex_tree_model_spf, /* tree model */ 1831 &synctex_data_model_tlchvw, /* data model */ 1832 &synctex_tlcpector_default, /* tlcpector */ 1833 &synctex_inspector_kern, /* inspector */ 1834 &synctex_vispector_kern, /* vispector */ 1835 }; 1836 1837 # ifdef SYNCTEX_NOTHING 1838 # pragma mark glue. 1839 # endif 1840 1841 /* glue node creator */ 1842 typedef synctex_node_tlchv_s synctex_node_glue_s; 1843 DEFINE_synctex_new_scanned_NODE(glue) 1844 1845 static char * _synctex_abstract_glue(synctex_node_p node); 1846 static void _synctex_display_glue(synctex_node_p node); 1847 1848 static synctex_class_s synctex_class_glue = { 1849 NULL, /* No scanner yet */ 1850 synctex_node_type_glue, /* Node type */ 1851 &_synctex_new_glue, /* creator */ 1852 &_synctex_free_leaf, /* destructor */ 1853 &_synctex_log_tlchv_node, /* log */ 1854 &_synctex_display_glue, /* display */ 1855 &_synctex_abstract_glue, /* abstract */ 1856 &synctex_tree_model_spf, /* tree model */ 1857 &synctex_data_model_tlchv, /* data model */ 1858 &synctex_tlcpector_default, /* tlcpector */ 1859 &synctex_inspector_hv, /* inspector */ 1860 &synctex_vispector_hv, /* vispector */ 1861 }; 1862 1863 /* The small nodes correspond to glue and boundary nodes. */ 1864 1865 # ifdef SYNCTEX_NOTHING 1866 # pragma mark rule. 1867 # endif 1868 1869 typedef struct { 1870 SYNCTEX_DECLARE_CHARINDEX 1871 synctex_class_p class_; 1872 synctex_data_u data[synctex_tree_spf_max+synctex_data_box_max]; 1873 } synctex_node_rule_s; 1874 1875 DEFINE_synctex_new_scanned_NODE(rule) 1876 1877 static void _synctex_log_rule(synctex_node_p node); 1878 static char * _synctex_abstract_rule(synctex_node_p node); 1879 static void _synctex_display_rule(synctex_node_p node); 1880 1881 static float __synctex_rule_visible_h(synctex_node_p node); 1882 static float __synctex_rule_visible_v(synctex_node_p node); 1883 static float __synctex_rule_visible_width(synctex_node_p node); 1884 static float __synctex_rule_visible_height(synctex_node_p node); 1885 static float __synctex_rule_visible_depth(synctex_node_p node); 1886 static synctex_vispector_s synctex_vispector_rule = { 1887 &__synctex_rule_visible_h, 1888 &__synctex_rule_visible_v, 1889 &__synctex_rule_visible_width, 1890 &__synctex_rule_visible_height, 1891 &__synctex_rule_visible_depth, 1892 }; 1893 1894 static synctex_class_s synctex_class_rule = { 1895 NULL, /* No scanner yet */ 1896 synctex_node_type_rule, /* Node type */ 1897 &_synctex_new_rule, /* creator */ 1898 &_synctex_free_leaf, /* destructor */ 1899 &_synctex_log_rule, /* log */ 1900 &_synctex_display_rule, /* display */ 1901 &_synctex_abstract_rule, /* abstract */ 1902 &synctex_tree_model_spf, /* tree model */ 1903 &synctex_data_model_box, /* data model */ 1904 &synctex_tlcpector_default, /* tlcpector */ 1905 &synctex_inspector_box, /* inspector */ 1906 &synctex_vispector_rule, /* vispector */ 1907 }; 1908 1909 # ifdef SYNCTEX_NOTHING 1910 # pragma mark boundary. 1911 # endif 1912 1913 /* boundary node creator */ 1914 typedef synctex_node_tlchv_s synctex_node_boundary_s; 1915 DEFINE_synctex_new_scanned_NODE(boundary) 1916 1917 static char * _synctex_abstract_boundary(synctex_node_p node); 1918 static void _synctex_display_boundary(synctex_node_p node); 1919 1920 static synctex_class_s synctex_class_boundary = { 1921 NULL, /* No scanner yet */ 1922 synctex_node_type_boundary, /* Node type */ 1923 &_synctex_new_boundary, /* creator */ 1924 &_synctex_free_leaf, /* destructor */ 1925 &_synctex_log_tlchv_node, /* log */ 1926 &_synctex_display_boundary, /* display */ 1927 &_synctex_abstract_boundary,/* abstract */ 1928 &synctex_tree_model_spf, /* tree model */ 1929 &synctex_data_model_tlchv, /* data model */ 1930 &synctex_tlcpector_default, /* tlcpector */ 1931 &synctex_inspector_hv, /* inspector */ 1932 &synctex_vispector_hv, /* vispector */ 1933 }; 1934 1935 # ifdef SYNCTEX_NOTHING 1936 # pragma mark box boundary. 1937 # endif 1938 1939 typedef struct { 1940 SYNCTEX_DECLARE_CHARINDEX 1941 synctex_class_p class_; 1942 synctex_data_u data[synctex_tree_spfa_max+synctex_data_tlchv_max]; 1943 } synctex_node_box_bdry_s; 1944 1945 #define DEFINE_synctex_new_unscanned_NODE(NAME)\ 1946 SYNCTEX_INLINE static synctex_node_p _synctex_new_##NAME(synctex_scanner_p scanner) {\ 1947 if (scanner) {\ 1948 synctex_node_p node = _synctex_malloc(sizeof(synctex_node_##NAME##_s));\ 1949 if (node) {\ 1950 node->class_ = scanner->class_+synctex_node_type_##NAME;\ 1951 SYNCTEX_DID_NEW(node); \ 1952 }\ 1953 return node;\ 1954 }\ 1955 return NULL;\ 1956 } 1957 DEFINE_synctex_new_unscanned_NODE(box_bdry) 1958 1959 static char * _synctex_abstract_box_bdry(synctex_node_p node); 1960 static void _synctex_display_box_bdry(synctex_node_p node); 1961 1962 static synctex_class_s synctex_class_box_bdry = { 1963 NULL, /* No scanner yet */ 1964 synctex_node_type_box_bdry, /* Node type */ 1965 &_synctex_new_box_bdry, /* creator */ 1966 &_synctex_free_leaf, /* destructor */ 1967 &_synctex_log_tlchv_node, /* log */ 1968 &_synctex_display_box_bdry, /* display */ 1969 &_synctex_abstract_box_bdry,/* display */ 1970 &synctex_tree_model_spfa, /* tree model */ 1971 &synctex_data_model_tlchv, /* data model */ 1972 &synctex_tlcpector_default, /* tlcpector */ 1973 &synctex_inspector_hv, /* inspector */ 1974 &synctex_vispector_hv, /* vispector */ 1975 }; 1976 1977 # ifdef SYNCTEX_NOTHING 1978 # pragma mark hbox proxy. 1979 # endif 1980 1981 /** 1982 * Standard nodes refer to TeX nodes: math, kern, boxes... 1983 * Proxy nodes are used to support forms. 1984 * A form is parsed as a tree of standard nodes starting 1985 * at the top left position. 1986 * When a reference is used, the form is duplicated 1987 * to the location specified by the reference. 1988 * As the same form can be duplicated at different locations, 1989 * the geometrical information is relative to its own top left point. 1990 * As we need absolute locations, we use proxy nodes. 1991 * A proxy node records an offset and the target node. 1992 * The target partly acts as a delegate. 1993 * The h and v position of the proxy node is the h and v 1994 * position of the target shifted by the proxy's offset. 1995 * The width, height and depth are not sensitive to offsets. 1996 * When are proxies created ? 1997 * 1) when the synctex file has been parsed, all the form refs 1998 * are replaced by proxies to the content of a form. 1999 * This content is a node with siblings (actually none). 2000 * Those root proxies have the parent of the ref they replace, 2001 * so their parents exist and are no proxy. 2002 * Moreover, if they have no sibling, it means that their target have no 2003 * sibling as well. 2004 * Such nodes are called root proxies. 2005 * 2) On the fly, when a proxy is asked for its child 2006 * (or sibling) and has none, a proxy to its target's child 2007 * (or sibling) is created if any. There are only 2 possible situations: 2008 * either the newly created proxy is the child of a proxy, 2009 * or it is the sibling of a proxy created on the fly. 2010 * In both cases, the parent is a proxy with children. 2011 * Such nodes are called child proxies. 2012 * How to compute the offset of a proxy ? 2013 * The offset of root proxy objects is exactly 2014 * the offset of the ref they replace. 2015 * The offset of other proxies is their owner's, 2016 * except when pointing to a root proxy. 2017 * What happens for cascading forms ? 2018 * Here is an example diagram 2019 * 2020 * At parse time, the arrow means "owns": 2021 * sheet0 -> ref_to1 2022 * 2023 * target1 -> ref_to2 2024 * 2025 * target2 -> child22 2026 * 2027 * After replacing the refs: 2028 * sheet0 -> proxy00 -> proxy01 -> proxy02 2029 * | | | 2030 * target1 -> proxy11 -> proxy12 2031 * | | 2032 * target2 -> proxy22 2033 * 2034 * proxy00, proxy11 and proxy22 are root proxies. 2035 * Their offset is the one of the ref they replace 2036 * proxy01, proxy02 and proxy12 are child proxies. 2037 * Their proxy is the one of their parent. 2038 * Optimization. 2039 * After all the refs are replaced, there are only root nodes 2040 * targeting standard node. We make sure that each child proxy 2041 * also targets a standard node. 2042 * It is possible for a proxy to have a standard sibling 2043 * whereas its target has no sibling at all. Root proxies 2044 * are such nodes, and are the only ones. 2045 * The consequence is that proxies created on the fly 2046 * must take into account this situation. 2047 */ 2048 2049 /* A proxy to a hbox. 2050 * A proxy do have a target, which can be a proxy 2051 */ 2052 2053 static const synctex_tree_model_s synctex_tree_model_proxy_hbox = { 2054 synctex_tree_sibling_idx, /* sibling */ 2055 synctex_tree_s_parent_idx, /* parent */ 2056 synctex_tree_sp_child_idx, /* child */ 2057 synctex_tree_spc_friend_idx, /* friend */ 2058 synctex_tree_spcf_last_idx, /* last */ 2059 synctex_tree_spcfl_next_hbox_idx, /* next_hbox */ 2060 -1, /* arg_sibling */ 2061 synctex_tree_spcfln_target_idx, /* target */ 2062 synctex_tree_spcflnt_proxy_hbox_max 2063 }; 2064 static const synctex_data_model_s synctex_data_model_proxy = { 2065 -1, /* tag */ 2066 -1, /* line */ 2067 -1, /* column */ 2068 synctex_data_proxy_h_idx, /* h */ 2069 synctex_data_proxy_v_idx, /* v */ 2070 -1, /* width */ 2071 -1, /* height */ 2072 -1, /* depth */ 2073 -1, /* mean_line */ 2074 -1, /* weight */ 2075 -1, /* h_V */ 2076 -1, /* v_V */ 2077 -1, /* width_V */ 2078 -1, /* height_V */ 2079 -1, /* depth_V */ 2080 -1, /* name */ 2081 -1, /* page */ 2082 synctex_data_proxy_hv_max 2083 }; 2084 typedef struct { 2085 SYNCTEX_DECLARE_CHARINDEX 2086 synctex_class_p class_; 2087 synctex_data_u data[synctex_tree_spcflnt_proxy_hbox_max+synctex_data_proxy_hv_max]; 2088 } synctex_node_proxy_hbox_s; 2089 2090 /* box proxy node creator */ 2091 DEFINE_synctex_new_unscanned_NODE(proxy_hbox) 2092 2093 static void _synctex_log_proxy(synctex_node_p node); 2094 static char * _synctex_abstract_proxy_hbox(synctex_node_p node); 2095 static void _synctex_display_proxy_hbox(synctex_node_p node); 2096 2097 static int _synctex_proxy_tag(synctex_node_p); 2098 static int _synctex_proxy_line(synctex_node_p); 2099 static int _synctex_proxy_column(synctex_node_p); 2100 2101 static synctex_tlcpector_s synctex_tlcpector_proxy = { 2102 &_synctex_proxy_tag, 2103 &_synctex_proxy_line, 2104 &_synctex_proxy_column, 2105 }; 2106 static int _synctex_proxy_h(synctex_node_p); 2107 static int _synctex_proxy_v(synctex_node_p); 2108 static int _synctex_proxy_width(synctex_node_p); 2109 static int _synctex_proxy_height(synctex_node_p); 2110 static int _synctex_proxy_depth(synctex_node_p); 2111 static synctex_inspector_s synctex_inspector_proxy_box = { 2112 &_synctex_proxy_h, 2113 &_synctex_proxy_v, 2114 &_synctex_proxy_width, 2115 &_synctex_proxy_height, 2116 &_synctex_proxy_depth, 2117 }; 2118 2119 static float __synctex_proxy_visible_h(synctex_node_p); 2120 static float __synctex_proxy_visible_v(synctex_node_p); 2121 static float __synctex_proxy_visible_width(synctex_node_p); 2122 static float __synctex_proxy_visible_height(synctex_node_p); 2123 static float __synctex_proxy_visible_depth(synctex_node_p); 2124 2125 static synctex_vispector_s synctex_vispector_proxy_box = { 2126 &__synctex_proxy_visible_h, 2127 &__synctex_proxy_visible_v, 2128 &__synctex_proxy_visible_width, 2129 &__synctex_proxy_visible_height, 2130 &__synctex_proxy_visible_depth, 2131 }; 2132 2133 static synctex_class_s synctex_class_proxy_hbox = { 2134 NULL, /* No scanner yet */ 2135 synctex_node_type_proxy_hbox, /* Node type */ 2136 &_synctex_new_proxy_hbox, /* creator */ 2137 &_synctex_free_node, /* destructor */ 2138 &_synctex_log_proxy, /* log */ 2139 &_synctex_display_proxy_hbox, /* display */ 2140 &_synctex_abstract_proxy_hbox, /* abstract */ 2141 &synctex_tree_model_proxy_hbox, /* tree model */ 2142 &synctex_data_model_proxy, /* data model */ 2143 &synctex_tlcpector_proxy, /* tlcpector */ 2144 &synctex_inspector_proxy_box, /* inspector */ 2145 &synctex_vispector_proxy_box, /* vispector */ 2146 }; 2147 2148 # ifdef SYNCTEX_NOTHING 2149 # pragma mark vbox proxy. 2150 # endif 2151 2152 /* A proxy to a vbox. */ 2153 2154 static const synctex_tree_model_s synctex_tree_model_proxy_vbox = { 2155 synctex_tree_sibling_idx, /* sibling */ 2156 synctex_tree_s_parent_idx, /* parent */ 2157 synctex_tree_sp_child_idx, /* child */ 2158 synctex_tree_spc_friend_idx, /* friend */ 2159 synctex_tree_spcf_last_idx, /* last */ 2160 -1, /* next_hbox */ 2161 -1, /* arg_sibling */ 2162 synctex_tree_spcfl_target_idx, /* target */ 2163 synctex_tree_spcflt_proxy_vbox_max 2164 }; 2165 2166 typedef struct { 2167 SYNCTEX_DECLARE_CHARINDEX 2168 synctex_class_p class_; 2169 synctex_data_u data[synctex_tree_spcflt_proxy_vbox_max+synctex_data_proxy_hv_max]; 2170 } synctex_node_proxy_vbox_s; 2171 2172 /* box proxy node creator */ 2173 DEFINE_synctex_new_unscanned_NODE(proxy_vbox) 2174 2175 static void _synctex_log_proxy(synctex_node_p node); 2176 static char * _synctex_abstract_proxy_vbox(synctex_node_p node); 2177 static void _synctex_display_proxy_vbox(synctex_node_p node); 2178 2179 static synctex_class_s synctex_class_proxy_vbox = { 2180 NULL, /* No scanner yet */ 2181 synctex_node_type_proxy_vbox, /* Node type */ 2182 &_synctex_new_proxy_vbox, /* creator */ 2183 &_synctex_free_node, /* destructor */ 2184 &_synctex_log_proxy, /* log */ 2185 &_synctex_display_proxy_vbox, /* display */ 2186 &_synctex_abstract_proxy_vbox, /* abstract */ 2187 &synctex_tree_model_proxy_vbox, /* tree model */ 2188 &synctex_data_model_proxy, /* data model */ 2189 &synctex_tlcpector_proxy, /* tlcpector */ 2190 &synctex_inspector_proxy_box, /* inspector */ 2191 &synctex_vispector_proxy_box, /* vispector */ 2192 }; 2193 2194 # ifdef SYNCTEX_NOTHING 2195 # pragma mark proxy. 2196 # endif 2197 2198 /** 2199 * A proxy to a node but a box. 2200 */ 2201 2202 static const synctex_tree_model_s synctex_tree_model_proxy = { 2203 synctex_tree_sibling_idx, /* sibling */ 2204 synctex_tree_s_parent_idx, /* parent */ 2205 -1, /* child */ 2206 synctex_tree_sp_friend_idx, /* friend */ 2207 -1, /* last */ 2208 -1, /* next_hbox */ 2209 -1, /* arg_sibling */ 2210 synctex_tree_spf_target_idx,/* target */ 2211 synctex_tree_spft_proxy_max 2212 }; 2213 2214 typedef struct { 2215 SYNCTEX_DECLARE_CHARINDEX 2216 synctex_class_p class_; 2217 synctex_data_u data[synctex_tree_spft_proxy_max+synctex_data_proxy_hv_max]; 2218 } synctex_node_proxy_s; 2219 2220 /* proxy node creator */ 2221 DEFINE_synctex_new_unscanned_NODE(proxy) 2222 2223 static void _synctex_log_proxy(synctex_node_p node); 2224 static char * _synctex_abstract_proxy(synctex_node_p node); 2225 static void _synctex_display_proxy(synctex_node_p node); 2226 2227 static synctex_vispector_s synctex_vispector_proxy = { 2228 &__synctex_proxy_visible_h, 2229 &__synctex_proxy_visible_v, 2230 &__synctex_proxy_visible_width, 2231 &_synctex_float_none, 2232 &_synctex_float_none, 2233 }; 2234 2235 static synctex_class_s synctex_class_proxy = { 2236 NULL, /* No scanner yet */ 2237 synctex_node_type_proxy, /* Node type */ 2238 &_synctex_new_proxy, /* creator */ 2239 &_synctex_free_leaf, /* destructor */ 2240 &_synctex_log_proxy, /* log */ 2241 &_synctex_display_proxy, /* display */ 2242 &_synctex_abstract_proxy, /* abstract */ 2243 &synctex_tree_model_proxy, /* tree model */ 2244 &synctex_data_model_proxy, /* data model */ 2245 &synctex_tlcpector_proxy, /* tlcpector */ 2246 &synctex_inspector_proxy_box, /* inspector */ 2247 &synctex_vispector_proxy, /* vispector */ 2248 }; 2249 2250 # ifdef SYNCTEX_NOTHING 2251 # pragma mark last proxy. 2252 # endif 2253 2254 /** 2255 * A proxy to the last proxy/box boundary. 2256 */ 2257 2258 static const synctex_tree_model_s synctex_tree_model_proxy_last = { 2259 synctex_tree_sibling_idx, /* sibling */ 2260 synctex_tree_s_parent_idx, /* parent */ 2261 -1, /* child */ 2262 synctex_tree_sp_friend_idx, /* friend */ 2263 -1, /* last */ 2264 -1, /* next_hbox */ 2265 synctex_tree_spf_arg_sibling_idx, /* arg_sibling */ 2266 synctex_tree_spfa_target_idx, /* target */ 2267 synctex_tree_spfat_proxy_last_max 2268 }; 2269 2270 typedef struct { 2271 SYNCTEX_DECLARE_CHARINDEX 2272 synctex_class_p class_; 2273 synctex_data_u data[synctex_tree_spfat_proxy_last_max+synctex_data_proxy_hv_max]; 2274 } synctex_node_proxy_last_s; 2275 2276 /* proxy node creator */ 2277 DEFINE_synctex_new_unscanned_NODE(proxy_last) 2278 2279 static void _synctex_log_proxy(synctex_node_p node); 2280 static char * _synctex_abstract_proxy(synctex_node_p node); 2281 static void _synctex_display_proxy(synctex_node_p node); 2282 2283 static synctex_class_s synctex_class_proxy_last = { 2284 NULL, /* No scanner yet */ 2285 synctex_node_type_proxy_last, /* Node type */ 2286 &_synctex_new_proxy, /* creator */ 2287 &_synctex_free_leaf, /* destructor */ 2288 &_synctex_log_proxy, /* log */ 2289 &_synctex_display_proxy, /* display */ 2290 &_synctex_abstract_proxy, /* abstract */ 2291 &synctex_tree_model_proxy_last, /* tree model */ 2292 &synctex_data_model_proxy, /* data model */ 2293 &synctex_tlcpector_proxy, /* tlcpector */ 2294 &synctex_inspector_proxy_box, /* inspector */ 2295 &synctex_vispector_proxy, /* vispector */ 2296 }; 2297 2298 # ifdef SYNCTEX_NOTHING 2299 # pragma mark handle. 2300 # endif 2301 2302 /** 2303 * A handle node. 2304 * A handle is never the target of a proxy 2305 * or another handle. 2306 * The child of a handle is always a handle if any. 2307 * The sibling of a handle is always a handle if any. 2308 * The parent of a handle is always a handle if any. 2309 */ 2310 2311 static const synctex_tree_model_s synctex_tree_model_handle = { 2312 synctex_tree_sibling_idx, /* sibling */ 2313 synctex_tree_s_parent_idx, /* parent */ 2314 synctex_tree_sp_child_idx, /* child */ 2315 -1, /* friend */ 2316 -1, /* last */ 2317 -1, /* next_hbox */ 2318 -1, /* arg_sibling */ 2319 synctex_tree_spc_target_idx,/* target */ 2320 synctex_tree_spct_handle_max 2321 }; 2322 2323 static const synctex_data_model_s synctex_data_model_handle = { 2324 -1, /* tag */ 2325 -1, /* line */ 2326 -1, /* column */ 2327 -1, /* h */ 2328 -1, /* v */ 2329 -1, /* width */ 2330 -1, /* height */ 2331 -1, /* depth */ 2332 -1, /* mean_line */ 2333 synctex_data_handle_w_idx, /* weight */ 2334 -1, /* h_V */ 2335 -1, /* v_V */ 2336 -1, /* width_V */ 2337 -1, /* height_V */ 2338 -1, /* depth_V */ 2339 -1, /* name */ 2340 -1, /* page */ 2341 synctex_data_handle_w_max 2342 }; 2343 2344 typedef struct { 2345 SYNCTEX_DECLARE_CHARINDEX 2346 synctex_class_p class_; 2347 synctex_data_u data[synctex_tree_spct_handle_max+synctex_data_handle_w_max]; 2348 } synctex_node_handle_s; 2349 2350 /* handle node creator */ 2351 DEFINE_synctex_new_unscanned_NODE(handle) 2352 2353 static void _synctex_log_handle(synctex_node_p node); 2354 static char * _synctex_abstract_handle(synctex_node_p node); 2355 static void _synctex_display_handle(synctex_node_p node); 2356 2357 static synctex_class_s synctex_class_handle = { 2358 NULL, /* No scanner yet */ 2359 synctex_node_type_handle, /* Node type */ 2360 &_synctex_new_handle, /* creator */ 2361 &_synctex_free_handle, /* destructor */ 2362 &_synctex_log_handle, /* log */ 2363 &_synctex_display_handle, /* display */ 2364 &_synctex_abstract_handle, /* abstract */ 2365 &synctex_tree_model_handle, /* tree model */ 2366 &synctex_data_model_handle, /* data model */ 2367 &synctex_tlcpector_proxy, /* tlcpector */ 2368 &synctex_inspector_proxy_box, /* inspector */ 2369 &synctex_vispector_proxy_box, /* vispector */ 2370 }; 2371 2372 SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_target(synctex_node_p target) { 2373 if (target) { 2374 synctex_node_p result = _synctex_new_handle(target->class_->scanner); 2375 if (result) { 2376 _synctex_tree_set_target(result,target); 2377 return result; 2378 } 2379 } 2380 return NULL; 2381 } 2382 SYNCTEX_INLINE static synctex_node_p _synctex_new_handle_with_child(synctex_node_p child) { 2383 if (child) { 2384 synctex_node_p result = _synctex_new_handle(child->class_->scanner); 2385 if (result) { 2386 _synctex_tree_set_child(result,child); 2387 return result; 2388 } 2389 } 2390 return NULL; 2391 } 2392 2393 # ifdef SYNCTEX_NOTHING 2394 # pragma mark - 2395 # pragma mark Navigation 2396 # endif 2397 synctex_node_p synctex_node_parent(synctex_node_p node) 2398 { 2399 return _synctex_tree_parent(node); 2400 } 2401 synctex_node_p synctex_node_parent_sheet(synctex_node_p node) 2402 { 2403 while(node && synctex_node_type(node) != synctex_node_type_sheet) { 2404 node = _synctex_tree_parent(node); 2405 } 2406 /* exit the while loop either when node is NULL or node is a sheet */ 2407 return node; 2408 } 2409 synctex_node_p synctex_node_parent_form(synctex_node_p node) 2410 { 2411 while(node && synctex_node_type(node) != synctex_node_type_form) { 2412 node = _synctex_tree_parent(node); 2413 } 2414 /* exit the while loop either when node is NULL or node is a form */ 2415 return node; 2416 } 2417 2418 /** 2419 * The returned proxy will be the child or a sibling of source. 2420 * The returned proxy has no parent, child nor sibling. 2421 * Used only by __synctex_replace_ref. 2422 * argument to_node: a box, not a proxy nor anything else. 2423 */ 2424 SYNCTEX_INLINE static synctex_node_p __synctex_new_proxy_from_ref_to(synctex_node_p ref, synctex_node_p to_node) { 2425 synctex_node_p proxy = NULL; 2426 if (!ref || !to_node) { 2427 return NULL; 2428 } 2429 switch(synctex_node_type(to_node)) { 2430 case synctex_node_type_vbox: 2431 proxy = _synctex_new_proxy_vbox(ref->class_->scanner); 2432 break; 2433 case synctex_node_type_hbox: 2434 proxy = _synctex_new_proxy_hbox(ref->class_->scanner); 2435 break; 2436 default: 2437 _synctex_error("! __synctex_new_proxy_from_ref_to. Unexpected form child (%s). Please report.", synctex_node_isa(to_node)); 2438 return NULL; 2439 } 2440 if (!proxy) { 2441 _synctex_error("! __synctex_new_proxy_from_ref_to. Internal error. Please report."); 2442 return NULL; 2443 } 2444 _synctex_data_set_h(proxy, _synctex_data_h(ref)); 2445 _synctex_data_set_v(proxy, _synctex_data_v(ref)-_synctex_data_height(to_node)); 2446 _synctex_tree_set_target(proxy,to_node); 2447 # if defined(SYNCTEX_USE_CHARINDEX) 2448 proxy->line_index=to_node?to_node->line_index:0; 2449 proxy->char_index=to_node?to_node->char_index:0; 2450 # endif 2451 return proxy; 2452 } 2453 /** 2454 * The returned proxy will be the child or a sibling of owning_proxy. 2455 * The returned proxy has no parent, nor child. 2456 * Used only by synctex_node_child and synctex_node_sibling 2457 * to create proxies on the fly. 2458 * If the to_node has an already computed sibling, 2459 * then the returned proxy has itself a sibling 2460 * pointing to that already computed sibling. 2461 */ 2462 SYNCTEX_INLINE static synctex_node_p __synctex_new_child_proxy_to(synctex_node_p owner, synctex_node_p to_node) { 2463 synctex_node_p proxy = NULL; 2464 synctex_node_p target = to_node; 2465 if (!owner) { 2466 return NULL; 2467 } 2468 switch(synctex_node_type(target)) { 2469 case synctex_node_type_vbox: 2470 if ((proxy = _synctex_new_proxy_vbox(owner->class_->scanner))) { 2471 exit_standard: 2472 _synctex_data_set_h(proxy, _synctex_data_h(owner)); 2473 _synctex_data_set_v(proxy, _synctex_data_v(owner)); 2474 exit0: 2475 _synctex_tree_set_target(proxy,target); 2476 # if defined(SYNCTEX_USE_CHARINDEX) 2477 proxy->line_index=to_node?to_node->line_index:0; 2478 proxy->char_index=to_node?to_node->char_index:0; 2479 # endif 2480 return proxy; 2481 }; 2482 break; 2483 case synctex_node_type_proxy_vbox: 2484 if ((proxy = _synctex_new_proxy_vbox(owner->class_->scanner))) { 2485 exit_proxy: 2486 target = _synctex_tree_target(to_node); 2487 _synctex_data_set_h(proxy, _synctex_data_h(owner)+_synctex_data_h(to_node)); 2488 _synctex_data_set_v(proxy, _synctex_data_v(owner)+_synctex_data_v(to_node)); 2489 goto exit0; 2490 }; 2491 break; 2492 case synctex_node_type_hbox: 2493 if ((proxy = _synctex_new_proxy_hbox(owner->class_->scanner))) { 2494 goto exit_standard; 2495 }; 2496 break; 2497 case synctex_node_type_proxy_hbox: 2498 if ((proxy = _synctex_new_proxy_hbox(owner->class_->scanner))) { 2499 goto exit_proxy; 2500 }; 2501 break; 2502 case synctex_node_type_proxy: 2503 case synctex_node_type_proxy_last: 2504 if ((proxy = _synctex_new_proxy(owner->class_->scanner))) { 2505 goto exit_proxy; 2506 }; 2507 break; 2508 default: 2509 if ((proxy = _synctex_new_proxy(owner->class_->scanner))) { 2510 goto exit_standard; 2511 }; 2512 break; 2513 } 2514 _synctex_error("! __synctex_new_child_proxy_to. " 2515 "Internal error. " 2516 "Please report."); 2517 return NULL; 2518 } 2519 SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_sibling); 2520 typedef struct synctex_nns_t { 2521 synctex_node_p first; 2522 synctex_node_p last; 2523 synctex_status_t status; 2524 } synctex_nns_s; 2525 /** 2526 * Given a target node, create a list of proxies. 2527 * The first proxy points to the target node, 2528 * its sibling points to the target's sibling and so on. 2529 * Returns the first created proxy, the last one and 2530 * an error status. 2531 */ 2532 SYNCTEX_INLINE static synctex_nns_s _synctex_new_child_proxies_to(synctex_node_p owner, synctex_node_p to_node) { 2533 synctex_nns_s nns = {NULL,NULL,SYNCTEX_STATUS_OK}; 2534 if ((nns.first = nns.last = __synctex_new_child_proxy_to(owner,to_node))) { 2535 synctex_node_p to_next_sibling = __synctex_tree_sibling(to_node); 2536 synctex_node_p to_sibling; 2537 while ((to_sibling = to_next_sibling)) { 2538 synctex_node_p sibling; 2539 if ((to_next_sibling = __synctex_tree_sibling(to_sibling))) { 2540 /* This is not the last sibling */ 2541 if((sibling = __synctex_new_child_proxy_to(owner,to_sibling))) { 2542 _synctex_tree_set_sibling(nns.last,sibling); 2543 nns.last = sibling; 2544 continue; 2545 } else { 2546 _synctex_error("! _synctex_new_child_proxy_to. " 2547 "Internal error (1). " 2548 "Please report."); 2549 nns.status = SYNCTEX_STATUS_ERROR; 2550 } 2551 } else if((sibling = _synctex_new_proxy_last(owner->class_->scanner))) { 2552 _synctex_tree_set_sibling(nns.last,sibling); 2553 nns.last = sibling; 2554 _synctex_data_set_h(nns.last, _synctex_data_h(nns.first)); 2555 _synctex_data_set_v(nns.last, _synctex_data_v(nns.first)); 2556 _synctex_tree_set_target(nns.last,to_sibling); 2557 # if defined(SYNCTEX_USE_CHARINDEX) 2558 nns.last->line_index=to_sibling->line_index; 2559 nns.last->char_index=to_sibling->char_index; 2560 # endif 2561 } else { 2562 _synctex_error("! _synctex_new_child_proxy_to. " 2563 "Internal error (2). " 2564 "Please report."); 2565 nns.status = SYNCTEX_STATUS_ERROR; 2566 } 2567 break; 2568 } 2569 } 2570 return nns; 2571 } 2572 static char * _synctex_node_abstract(synctex_node_p node); 2573 SYNCTEX_INLINE static synctex_node_p synctex_tree_set_friend(synctex_node_p node,synctex_node_p new_friend) { 2574 #if SYNCTEX_DEBUG 2575 synctex_node_p F = new_friend; 2576 while (F) { 2577 if (node == F) { 2578 printf("THIS IS AN ERROR\n"); 2579 F = new_friend; 2580 while (F) { 2581 printf("%s\n",_synctex_node_abstract(F)); 2582 if (node == F) { 2583 return NULL; 2584 } 2585 F = _synctex_tree_friend(F); 2586 } 2587 return NULL; 2588 } 2589 F = _synctex_tree_friend(F); 2590 } 2591 #endif 2592 return new_friend?_synctex_tree_set_friend(node,new_friend):_synctex_tree_reset_friend(node); 2593 } 2594 /** 2595 * 2596 */ 2597 SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend(synctex_node_p node, int i) { 2598 synctex_node_p old = NULL; 2599 if (i>=0) { 2600 i = i%(node->class_->scanner->number_of_lists); 2601 old = synctex_tree_set_friend(node,(node->class_->scanner->lists_of_friends)[i]); 2602 (node->class_->scanner->lists_of_friends)[i] = node; 2603 #if SYNCTEX_DEBUG>500 2604 printf("tl(%i)=>",i); 2605 synctex_node_log(node); 2606 if (synctex_node_parent_form(node)) { 2607 printf("! ERROR. No registration expected!\n"); 2608 } 2609 #endif 2610 } 2611 return old; 2612 } 2613 /** 2614 * All proxies have tlc attributes, on behalf of their target. 2615 * The purpose is to register all af them. 2616 * - argument node: is the proxy, must not be NULL 2617 */ 2618 SYNCTEX_INLINE static synctex_node_p __synctex_proxy_make_friend_and_next_hbox(synctex_node_p node) { 2619 synctex_node_p old = NULL; 2620 synctex_node_p target = _synctex_tree_target(node); 2621 if (target) { 2622 int i = _synctex_data_tag(target)+_synctex_data_line(target); 2623 old = __synctex_node_make_friend(node,i); 2624 } else { 2625 old = __synctex_tree_reset_friend(node); 2626 } 2627 if (synctex_node_type(node) == synctex_node_type_proxy_hbox) { 2628 synctex_node_p sheet = synctex_node_parent_sheet(node); 2629 if (sheet) { 2630 _synctex_tree_set_next_hbox(node,_synctex_tree_next_hbox(sheet)); 2631 _synctex_tree_set_next_hbox(sheet,node); 2632 } 2633 } 2634 return old; 2635 } 2636 /** 2637 * Register a node which have tag, line and column. 2638 * - argument node: the node 2639 */ 2640 SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend_tlc(synctex_node_p node) { 2641 int i = synctex_node_tag(node)+synctex_node_line(node); 2642 return __synctex_node_make_friend(node,i); 2643 } 2644 /** 2645 * Register a node which have tag, line and column. 2646 * Does nothing if the argument is NULL. 2647 * Calls __synctex_node_make_friend_tlc. 2648 * - argument node: the node 2649 */ 2650 SYNCTEX_INLINE static void _synctex_node_make_friend_tlc(synctex_node_p node) { 2651 if (node) { 2652 __synctex_node_make_friend_tlc(node); 2653 } 2654 } 2655 static synctex_node_p _synctex_node_set_child(synctex_node_p node, synctex_node_p new_child); 2656 /** 2657 * The (first) child of the node, if any, NULL otherwise. 2658 * At parse time, non void box nodes have children. 2659 * All other nodes have no children. 2660 * In order to support pdf forms, proxies are created 2661 * to place form nodes at real locations. 2662 * Ref nodes are replaced by root proxies targeting 2663 * form contents. If root proxies have no children, 2664 * they are created on the fly as proxies to the 2665 * children of the targeted box. 2666 * As such, proxies created here are targeting a 2667 * node that belongs to a form. 2668 * This is the only place where child proxies are created. 2669 */ 2670 synctex_node_p synctex_node_child(synctex_node_p node) { 2671 synctex_node_p child = NULL; 2672 synctex_node_p target = NULL; 2673 if ((child = _synctex_tree_child(node))) { 2674 return child; 2675 } else if ((target = _synctex_tree_target(node))) { 2676 if ((child = synctex_node_child(target))) { 2677 /* This is a proxy with no child 2678 * which target does have a child. */ 2679 synctex_nns_s nns = _synctex_new_child_proxies_to(node, child); 2680 if (nns.first) { 2681 _synctex_node_set_child(node,nns.first); 2682 return nns.first; 2683 } else { 2684 _synctex_error("! synctex_node_child. Internal inconsistency. Please report."); 2685 } 2686 } 2687 } 2688 return NULL; 2689 } 2690 /* 2691 * Set the parent/child bound. 2692 * Things get complicated when new_child has siblings. 2693 * The caller is responsible for releasing the returned value. 2694 */ 2695 static synctex_node_p _synctex_node_set_child(synctex_node_p parent, synctex_node_p new_child) { 2696 if (parent) { 2697 synctex_node_p old = _synctex_tree_set_child(parent,new_child); 2698 synctex_node_p last_child = NULL; 2699 synctex_node_p child; 2700 if ((child = old)) { 2701 do { 2702 _synctex_tree_reset_parent(child); 2703 } while ((child = __synctex_tree_sibling(child))); 2704 } 2705 if ((child = new_child)) { 2706 do { 2707 _synctex_tree_set_parent(child,parent); 2708 last_child = child; 2709 } while ((child = __synctex_tree_sibling(child))); 2710 } 2711 _synctex_tree_set_last(parent,last_child); 2712 return old; 2713 } 2714 return NULL; 2715 } 2716 2717 /* The last child of the given node, or NULL. 2718 */ 2719 synctex_node_p synctex_node_last_child(synctex_node_p node) { 2720 return _synctex_tree_last(node); 2721 } 2722 /** 2723 * All nodes siblings are properly set up at parse time 2724 * except for non root proxies. 2725 */ 2726 synctex_node_p synctex_node_sibling(synctex_node_p node) { 2727 return node? __synctex_tree_sibling(node): NULL; 2728 } 2729 /** 2730 * All the _synctex_tree_... methods refer to the tree model. 2731 * __synctex_tree_... methods are low level. 2732 */ 2733 /** 2734 * Replace the sibling. 2735 * Connect to the arg_sibling of the new_sibling if relevant. 2736 * - returns the old sibling. 2737 * The caller is responsible for releasing the old sibling. 2738 * The bound to the parent is managed below. 2739 */ 2740 SYNCTEX_INLINE static synctex_node_p _synctex_tree_set_sibling(synctex_node_p node, synctex_node_p new_sibling) { 2741 if (node == new_sibling) { 2742 printf("BOF\n"); 2743 } 2744 synctex_node_p old = node? __synctex_tree_set_sibling(node,new_sibling): NULL; 2745 _synctex_tree_set_arg_sibling(new_sibling,node); 2746 return old; 2747 } 2748 /** 2749 * Replace the sibling. 2750 * Set the parent of the new sibling (and further siblings) 2751 * to the parent of the receiver. 2752 * Also set the last sibling of parent. 2753 * - argument new_sibling: must not be NULL. 2754 * - returns the old sibling. 2755 * The caller is responsible for releasing the old sibling. 2756 */ 2757 static synctex_node_p _synctex_node_set_sibling(synctex_node_p node, synctex_node_p new_sibling) { 2758 if (node && new_sibling) { 2759 synctex_node_p old = _synctex_tree_set_sibling(node,new_sibling); 2760 if (_synctex_tree_has_parent(node)) { 2761 synctex_node_p parent = __synctex_tree_parent(node); 2762 if (parent) { 2763 synctex_node_p N = new_sibling; 2764 while (synctex_YES) { 2765 if (_synctex_tree_has_parent(N)) { 2766 __synctex_tree_set_parent(N,parent); 2767 _synctex_tree_set_last(parent,N); 2768 N = __synctex_tree_sibling(N); 2769 continue; 2770 } else if (N) { 2771 _synctex_error("! synctex_node_sibling. " 2772 "Internal inconsistency. " 2773 "Please report."); 2774 } 2775 break; 2776 } 2777 } 2778 } 2779 return old; 2780 } 2781 return NULL; 2782 } 2783 /** 2784 * The last sibling of the given node, or NULL with node. 2785 */ 2786 synctex_node_p synctex_node_last_sibling(synctex_node_p node) { 2787 synctex_node_p sibling; 2788 do { 2789 sibling = node; 2790 } while((node = synctex_node_sibling(node))); 2791 return sibling; 2792 } 2793 /** 2794 * The next nodes corresponds to a deep first tree traversal. 2795 * Does not create child proxies as side effect contrary to 2796 * the synctex_node_next method above. 2797 * May loop infinitely many times if the tree 2798 * is not properly built (contains loops). 2799 */ 2800 SYNCTEX_INLINE static synctex_node_p _synctex_node_sibling_or_parents(synctex_node_p node) { 2801 while (node) { 2802 synctex_node_p N; 2803 if ((N = __synctex_tree_sibling(node))) { 2804 return N; 2805 } else if ((node = _synctex_tree_parent(node))) { 2806 if (synctex_node_type(node) == synctex_node_type_sheet) {/* EXC_BAD_ACCESS? */ 2807 return NULL; 2808 } else if (synctex_node_type(node) == synctex_node_type_form) { 2809 return NULL; 2810 } 2811 } else { 2812 return NULL; 2813 } 2814 } 2815 return NULL; 2816 } 2817 /** 2818 * The next nodes corresponds to a deep first tree traversal. 2819 * Creates child proxies as side effect. 2820 * May loop infinitely many times if the tree 2821 * is not properly built (contains loops). 2822 */ 2823 synctex_node_p synctex_node_next(synctex_node_p node) { 2824 synctex_node_p N = synctex_node_child(node); 2825 if (N) { 2826 return N; 2827 } 2828 return _synctex_node_sibling_or_parents(node); 2829 } 2830 /** 2831 * The next nodes corresponds to a deep first tree traversal. 2832 * Does not create child proxies as side effect contrary to 2833 * the synctex_node_next method above. 2834 * May loop infinitely many times if the tree 2835 * is not properly built (contains loops). 2836 */ 2837 synctex_node_p _synctex_node_next(synctex_node_p node) { 2838 synctex_node_p N = _synctex_tree_child(node); 2839 if (N) { 2840 return N; 2841 } 2842 return _synctex_node_sibling_or_parents(node); 2843 } 2844 /** 2845 * The node which argument is the sibling. 2846 * - return: NULL if the argument has no parent or 2847 * is the first child of its parent. 2848 * - Input nodes have no arg siblings 2849 */ 2850 synctex_node_p synctex_node_arg_sibling(synctex_node_p node) { 2851 #if 1 2852 return _synctex_tree_arg_sibling(node); 2853 #else 2854 synctex_node_p N = _synctex_tree_parent(node); 2855 if ((N = _synctex_tree_child(N))) { 2856 do { 2857 synctex_node_p NN = __synctex_tree_sibling(N); 2858 if (NN == node) { 2859 return N; 2860 } 2861 N = NN; 2862 } while (N); 2863 } 2864 return N; 2865 #endif 2866 } 2867 # ifdef SYNCTEX_NOTHING 2868 # pragma mark - 2869 # pragma mark CLASS 2870 # endif 2871 2872 /* Public node accessor: the type */ 2873 synctex_node_type_t synctex_node_type(synctex_node_p node) { 2874 return node? node->class_->type: synctex_node_type_none; 2875 } 2876 2877 /* Public node accessor: the type */ 2878 synctex_node_type_t synctex_node_target_type(synctex_node_p node) { 2879 synctex_node_p target = _synctex_tree_target(node); 2880 if (target) { 2881 return (((target)->class_))->type; 2882 } else if (node) { 2883 return (((node)->class_))->type; 2884 } 2885 return synctex_node_type_none; 2886 } 2887 2888 /* Public node accessor: the human readable type */ 2889 const char * synctex_node_isa(synctex_node_p node) { 2890 static const char * isa[synctex_node_number_of_types] = 2891 {"Not a node", 2892 "input", 2893 "sheet", 2894 "form", 2895 "ref", 2896 "vbox", 2897 "void vbox", 2898 "hbox", 2899 "void hbox", 2900 "kern", 2901 "glue", 2902 "rule", 2903 "math", 2904 "boundary", 2905 "box_bdry", 2906 "proxy", 2907 "last proxy", 2908 "vbox proxy", 2909 "hbox proxy", 2910 "handle"}; 2911 return isa[synctex_node_type(node)]; 2912 } 2913 2914 # ifdef SYNCTEX_NOTHING 2915 # pragma mark - 2916 # pragma mark LOG 2917 # endif 2918 2919 /* Public node logger */ 2920 void synctex_node_log(synctex_node_p node) { 2921 SYNCTEX_MSG_SEND(node,log); 2922 } 2923 2924 static void _synctex_log_input(synctex_node_p node) { 2925 if (node) { 2926 printf("%s:%i,%s(%i)\n",synctex_node_isa(node), 2927 _synctex_data_tag(node), 2928 _synctex_data_name(node), 2929 _synctex_data_line(node)); 2930 printf("SELF:%p\n",(void *)node); 2931 printf(" SIBLING:%p\n", 2932 (void *)__synctex_tree_sibling(node)); 2933 } 2934 } 2935 2936 static void _synctex_log_sheet(synctex_node_p node) { 2937 if (node) { 2938 printf("%s:%i",synctex_node_isa(node),_synctex_data_page(node)); 2939 SYNCTEX_PRINT_CHARINDEX_NL; 2940 printf("SELF:%p\n",(void *)node); 2941 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 2942 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 2943 printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); 2944 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 2945 printf(" NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node)); 2946 } 2947 } 2948 2949 static void _synctex_log_form(synctex_node_p node) { 2950 if (node) { 2951 printf("%s:%i",synctex_node_isa(node),_synctex_data_tag(node)); 2952 SYNCTEX_PRINT_CHARINDEX_NL; 2953 printf("SELF:%p\n",(void *)node); 2954 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 2955 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 2956 printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); 2957 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 2958 } 2959 } 2960 2961 static void _synctex_log_ref(synctex_node_p node) { 2962 if (node) { 2963 printf("%s:%i:%i,%i", 2964 synctex_node_isa(node), 2965 _synctex_data_tag(node), 2966 _synctex_data_h(node), 2967 _synctex_data_v(node)); 2968 SYNCTEX_PRINT_CHARINDEX_NL; 2969 printf("SELF:%p\n",(void *)node); 2970 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 2971 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 2972 } 2973 } 2974 2975 static void _synctex_log_tlchv_node(synctex_node_p node) { 2976 if (node) { 2977 printf("%s:%i,%i,%i:%i,%i", 2978 synctex_node_isa(node), 2979 _synctex_data_tag(node), 2980 _synctex_data_line(node), 2981 _synctex_data_column(node), 2982 _synctex_data_h(node), 2983 _synctex_data_v(node)); 2984 SYNCTEX_PRINT_CHARINDEX_NL; 2985 printf("SELF:%p\n",(void *)node); 2986 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 2987 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 2988 printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); 2989 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 2990 } 2991 } 2992 2993 static void _synctex_log_kern_node(synctex_node_p node) { 2994 if (node) { 2995 printf("%s:%i,%i,%i:%i,%i:%i", 2996 synctex_node_isa(node), 2997 _synctex_data_tag(node), 2998 _synctex_data_line(node), 2999 _synctex_data_column(node), 3000 _synctex_data_h(node), 3001 _synctex_data_v(node), 3002 _synctex_data_width(node)); 3003 SYNCTEX_PRINT_CHARINDEX_NL; 3004 printf("SELF:%p\n",(void *)node); 3005 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 3006 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 3007 printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); 3008 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 3009 } 3010 } 3011 3012 static void _synctex_log_rule(synctex_node_p node) { 3013 if (node) { 3014 printf("%s:%i,%i,%i:%i,%i", 3015 synctex_node_isa(node), 3016 _synctex_data_tag(node), 3017 _synctex_data_line(node), 3018 _synctex_data_column(node), 3019 _synctex_data_h(node), 3020 _synctex_data_v(node)); 3021 printf(":%i",_synctex_data_width(node)); 3022 printf(",%i",_synctex_data_height(node)); 3023 printf(",%i",_synctex_data_depth(node)); 3024 SYNCTEX_PRINT_CHARINDEX_NL; 3025 printf("SELF:%p\n",(void *)node); 3026 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 3027 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 3028 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 3029 } 3030 } 3031 3032 static void _synctex_log_void_box(synctex_node_p node) { 3033 if (node) { 3034 printf("%s",synctex_node_isa(node)); 3035 printf(":%i",_synctex_data_tag(node)); 3036 printf(",%i",_synctex_data_line(node)); 3037 printf(",%i",_synctex_data_column(node)); 3038 printf(":%i",_synctex_data_h(node)); 3039 printf(",%i",_synctex_data_v(node)); 3040 printf(":%i",_synctex_data_width(node)); 3041 printf(",%i",_synctex_data_height(node)); 3042 printf(",%i",_synctex_data_depth(node)); 3043 SYNCTEX_PRINT_CHARINDEX_NL; 3044 printf("SELF:%p\n",(void *)node); 3045 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 3046 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 3047 printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); 3048 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 3049 } 3050 } 3051 3052 static void _synctex_log_vbox(synctex_node_p node) { 3053 if (node) { 3054 printf("%s",synctex_node_isa(node)); 3055 printf(":%i",_synctex_data_tag(node)); 3056 printf(",%i",_synctex_data_line(node)); 3057 printf(",%i",_synctex_data_column(node)); 3058 printf(":%i",_synctex_data_h(node)); 3059 printf(",%i",_synctex_data_v(node)); 3060 printf(":%i",_synctex_data_width(node)); 3061 printf(",%i",_synctex_data_height(node)); 3062 printf(",%i",_synctex_data_depth(node)); 3063 SYNCTEX_PRINT_CHARINDEX_NL; 3064 printf("SELF:%p\n",(void *)node); 3065 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 3066 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 3067 printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); 3068 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 3069 printf(" NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node)); 3070 } 3071 } 3072 3073 static void _synctex_log_hbox(synctex_node_p node) { 3074 if (node) { 3075 printf("%s",synctex_node_isa(node)); 3076 printf(":%i",_synctex_data_tag(node)); 3077 printf(",%i~%i*%i",_synctex_data_line(node),_synctex_data_mean_line(node),_synctex_data_weight(node)); 3078 printf(",%i",_synctex_data_column(node)); 3079 printf(":%i",_synctex_data_h(node)); 3080 printf(",%i",_synctex_data_v(node)); 3081 printf(":%i",_synctex_data_width(node)); 3082 printf(",%i",_synctex_data_height(node)); 3083 printf(",%i",_synctex_data_depth(node)); 3084 printf("/%i",_synctex_data_h_V(node)); 3085 printf(",%i",_synctex_data_v_V(node)); 3086 printf(":%i",_synctex_data_width_V(node)); 3087 printf(",%i",_synctex_data_height_V(node)); 3088 printf(",%i",_synctex_data_depth_V(node)); 3089 SYNCTEX_PRINT_CHARINDEX_NL; 3090 printf("SELF:%p\n",(void *)node); 3091 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 3092 printf(" PARENT:%p\n",(void *)_synctex_tree_parent(node)); 3093 printf(" CHILD:%p\n",(void *)_synctex_tree_child(node)); 3094 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 3095 printf(" NEXT_hbox:%p\n",(void *)_synctex_tree_next_hbox(node)); 3096 } 3097 } 3098 static void _synctex_log_proxy(synctex_node_p node) { 3099 if (node) { 3100 synctex_node_p N = _synctex_tree_target(node); 3101 printf("%s",synctex_node_isa(node)); 3102 printf(":%i",_synctex_data_h(node)); 3103 printf(",%i",_synctex_data_v(node)); 3104 SYNCTEX_PRINT_CHARINDEX_NL; 3105 printf("SELF:%p\n",(void *)node); 3106 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 3107 printf(" LEFT:%p\n",(void *)_synctex_tree_friend(node)); 3108 printf(" ->%s\n",_synctex_node_abstract(N)); 3109 } 3110 } 3111 static void _synctex_log_handle(synctex_node_p node) { 3112 if (node) { 3113 synctex_node_p N = _synctex_tree_target(node); 3114 printf("%s",synctex_node_isa(node)); 3115 SYNCTEX_PRINT_CHARINDEX_NL; 3116 printf("SELF:%p\n",(void *)node); 3117 printf(" SIBLING:%p\n",(void *)__synctex_tree_sibling(node)); 3118 printf(" ->%s\n",_synctex_node_abstract(N)); 3119 } 3120 } 3121 3122 # ifdef SYNCTEX_NOTHING 3123 # pragma mark - 3124 # pragma mark SYNCTEX_DISPLAY 3125 # endif 3126 3127 int synctex_scanner_display_switcher(synctex_scanner_p scanR) { 3128 return scanR->display_switcher; 3129 } 3130 void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher) { 3131 scanR->display_switcher = switcher; 3132 } 3133 static const char * const _synctex_display_prompt = "................................"; 3134 3135 static char * _synctex_scanner_display_prompt_down(synctex_scanner_p scanR) { 3136 if (scanR->display_prompt>_synctex_display_prompt) { 3137 --scanR->display_prompt; 3138 } 3139 return scanR->display_prompt; 3140 } 3141 static char * _synctex_scanner_display_prompt_up(synctex_scanner_p scanR) { 3142 if (scanR->display_prompt+1<_synctex_display_prompt+strlen(_synctex_display_prompt)) { 3143 ++scanR->display_prompt; 3144 } 3145 return scanR->display_prompt; 3146 } 3147 3148 void synctex_node_display(synctex_node_p node) { 3149 if (node) { 3150 synctex_scanner_p scanR = node->class_->scanner; 3151 if (scanR) { 3152 if (scanR->display_switcher<0) { 3153 SYNCTEX_MSG_SEND(node, display); 3154 } else if (scanR->display_switcher>0 && --scanR->display_switcher>0) { 3155 SYNCTEX_MSG_SEND(node, display); 3156 } else if (scanR->display_switcher-->=0) { 3157 printf("%s Next display skipped. Reset display switcher.\n",node->class_->scanner->display_prompt); 3158 } 3159 } else { 3160 SYNCTEX_MSG_SEND(node, display); 3161 } 3162 } 3163 } 3164 static char * _synctex_node_abstract(synctex_node_p node) { 3165 SYNCTEX_PARAMETER_ASSERT(node || node->class_); 3166 return (node && node->class_->abstract)? node->class_->abstract(node):"none"; 3167 } 3168 3169 SYNCTEX_INLINE static void _synctex_display_child(synctex_node_p node) { 3170 synctex_node_p N = _synctex_tree_child(node); 3171 if (N) { 3172 _synctex_scanner_display_prompt_down(N->class_->scanner); 3173 synctex_node_display(N); 3174 _synctex_scanner_display_prompt_up(N->class_->scanner); 3175 } 3176 } 3177 3178 SYNCTEX_INLINE static void _synctex_display_sibling(synctex_node_p node) { 3179 synctex_node_display(__synctex_tree_sibling(node)); 3180 } 3181 #define SYNCTEX_ABSTRACT_MAX 128 3182 static char * _synctex_abstract_input(synctex_node_p node) { 3183 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3184 if (node) { 3185 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"Input:%i:%s(%i)" SYNCTEX_PRINT_CHARINDEX_FMT, 3186 _synctex_data_tag(node), 3187 _synctex_data_name(node), 3188 _synctex_data_line(node) 3189 SYNCTEX_PRINT_CHARINDEX_WHAT); 3190 } 3191 return abstract; 3192 } 3193 3194 static void _synctex_display_input(synctex_node_p node) { 3195 if (node) { 3196 printf("Input:%i:%s(%i)" 3197 SYNCTEX_PRINT_CHARINDEX_FMT 3198 "\n", 3199 _synctex_data_tag(node), 3200 _synctex_data_name(node), 3201 _synctex_data_line(node) 3202 SYNCTEX_PRINT_CHARINDEX_WHAT); 3203 synctex_node_display(__synctex_tree_sibling(node)); 3204 } 3205 } 3206 3207 static char * _synctex_abstract_sheet(synctex_node_p node) { 3208 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3209 if (node) { 3210 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"{%i...}" SYNCTEX_PRINT_CHARINDEX_FMT, 3211 _synctex_data_page(node) 3212 SYNCTEX_PRINT_CHARINDEX_WHAT); 3213 } 3214 return abstract; 3215 } 3216 3217 static void _synctex_display_sheet(synctex_node_p node) { 3218 if (node) { 3219 printf("%s{%i" 3220 SYNCTEX_PRINT_CHARINDEX_FMT 3221 "\n", 3222 node->class_->scanner->display_prompt, 3223 _synctex_data_page(node) 3224 SYNCTEX_PRINT_CHARINDEX_WHAT); 3225 _synctex_display_child(node); 3226 printf("%s}\n",node->class_->scanner->display_prompt); 3227 _synctex_display_sibling(node); 3228 } 3229 } 3230 3231 static char * _synctex_abstract_form(synctex_node_p node) { 3232 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3233 if (node) { 3234 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"<%i...>" SYNCTEX_PRINT_CHARINDEX_FMT, 3235 _synctex_data_tag(node) 3236 SYNCTEX_PRINT_CHARINDEX_WHAT); 3237 SYNCTEX_PRINT_CHARINDEX; 3238 } 3239 return abstract; 3240 } 3241 3242 static void _synctex_display_form(synctex_node_p node) { 3243 if (node) { 3244 printf("%s<%i" 3245 SYNCTEX_PRINT_CHARINDEX_FMT 3246 "\n", 3247 node->class_->scanner->display_prompt, 3248 _synctex_data_tag(node) 3249 SYNCTEX_PRINT_CHARINDEX_WHAT); 3250 _synctex_display_child(node); 3251 printf("%s>\n",node->class_->scanner->display_prompt); 3252 _synctex_display_sibling(node); 3253 } 3254 } 3255 3256 static char * _synctex_abstract_vbox(synctex_node_p node) { 3257 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3258 if (node) { 3259 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"[%i,%i:%i,%i:%i,%i,%i...]" 3260 SYNCTEX_PRINT_CHARINDEX_FMT, 3261 _synctex_data_tag(node), 3262 _synctex_data_line(node), 3263 _synctex_data_h(node), 3264 _synctex_data_v(node), 3265 _synctex_data_width(node), 3266 _synctex_data_height(node), 3267 _synctex_data_depth(node) 3268 SYNCTEX_PRINT_CHARINDEX_WHAT); 3269 } 3270 return abstract; 3271 } 3272 3273 static void _synctex_display_vbox(synctex_node_p node) { 3274 if (node) { 3275 printf("%s[%i,%i:%i,%i:%i,%i,%i" 3276 SYNCTEX_PRINT_CHARINDEX_FMT 3277 "\n", 3278 node->class_->scanner->display_prompt, 3279 _synctex_data_tag(node), 3280 _synctex_data_line(node), 3281 _synctex_data_h(node), 3282 _synctex_data_v(node), 3283 _synctex_data_width(node), 3284 _synctex_data_height(node), 3285 _synctex_data_depth(node) 3286 SYNCTEX_PRINT_CHARINDEX_WHAT); 3287 _synctex_display_child(node); 3288 printf("%s]\n%slast:%s\n", 3289 node->class_->scanner->display_prompt, 3290 node->class_->scanner->display_prompt, 3291 _synctex_node_abstract(_synctex_tree_last(node))); 3292 _synctex_display_sibling(node); 3293 } 3294 } 3295 3296 static char * _synctex_abstract_hbox(synctex_node_p node) { 3297 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3298 if (node) { 3299 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"(%i,%i~%i*%i:%i,%i:%i,%i,%i...)" 3300 SYNCTEX_PRINT_CHARINDEX_FMT, 3301 _synctex_data_tag(node), 3302 _synctex_data_line(node), 3303 _synctex_data_mean_line(node), 3304 _synctex_data_weight(node), 3305 _synctex_data_h(node), 3306 _synctex_data_v(node), 3307 _synctex_data_width(node), 3308 _synctex_data_height(node), 3309 _synctex_data_depth(node) 3310 SYNCTEX_PRINT_CHARINDEX_WHAT); 3311 } 3312 return abstract; 3313 } 3314 3315 static void _synctex_display_hbox(synctex_node_p node) { 3316 if (node) { 3317 printf("%s(%i,%i~%i*%i:%i,%i:%i,%i,%i" 3318 SYNCTEX_PRINT_CHARINDEX_FMT 3319 "\n", 3320 node->class_->scanner->display_prompt, 3321 _synctex_data_tag(node), 3322 _synctex_data_line(node), 3323 _synctex_data_mean_line(node), 3324 _synctex_data_weight(node), 3325 _synctex_data_h(node), 3326 _synctex_data_v(node), 3327 _synctex_data_width(node), 3328 _synctex_data_height(node), 3329 _synctex_data_depth(node) 3330 SYNCTEX_PRINT_CHARINDEX_WHAT); 3331 _synctex_display_child(node); 3332 printf("%s)\n%slast:%s\n", 3333 node->class_->scanner->display_prompt, 3334 node->class_->scanner->display_prompt, 3335 _synctex_node_abstract(_synctex_tree_last(node))); 3336 _synctex_display_sibling(node); 3337 } 3338 } 3339 3340 static char * _synctex_abstract_void_vbox(synctex_node_p node) { 3341 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3342 if (node) { 3343 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"v%i,%i;%i,%i:%i,%i,%i" 3344 SYNCTEX_PRINT_CHARINDEX_FMT 3345 "\n", 3346 _synctex_data_tag(node), 3347 _synctex_data_line(node), 3348 _synctex_data_h(node), 3349 _synctex_data_v(node), 3350 _synctex_data_width(node), 3351 _synctex_data_height(node), 3352 _synctex_data_depth(node) 3353 SYNCTEX_PRINT_CHARINDEX_WHAT); 3354 } 3355 return abstract; 3356 } 3357 3358 static void _synctex_display_void_vbox(synctex_node_p node) { 3359 if (node) { 3360 printf("%sv%i,%i;%i,%i:%i,%i,%i" 3361 SYNCTEX_PRINT_CHARINDEX_FMT 3362 "\n", 3363 node->class_->scanner->display_prompt, 3364 _synctex_data_tag(node), 3365 _synctex_data_line(node), 3366 _synctex_data_h(node), 3367 _synctex_data_v(node), 3368 _synctex_data_width(node), 3369 _synctex_data_height(node), 3370 _synctex_data_depth(node) 3371 SYNCTEX_PRINT_CHARINDEX_WHAT); 3372 _synctex_display_sibling(node); 3373 } 3374 } 3375 3376 static char * _synctex_abstract_void_hbox(synctex_node_p node) { 3377 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3378 if (node) { 3379 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"h%i,%i:%i,%i:%i,%i,%i" 3380 SYNCTEX_PRINT_CHARINDEX_FMT, 3381 _synctex_data_tag(node), 3382 _synctex_data_line(node), 3383 _synctex_data_h(node), 3384 _synctex_data_v(node), 3385 _synctex_data_width(node), 3386 _synctex_data_height(node), 3387 _synctex_data_depth(node) 3388 SYNCTEX_PRINT_CHARINDEX_WHAT); 3389 } 3390 return abstract; 3391 } 3392 3393 static void _synctex_display_void_hbox(synctex_node_p node) { 3394 if (node) { 3395 printf("%sh%i,%i:%i,%i:%i,%i,%i" 3396 SYNCTEX_PRINT_CHARINDEX_FMT 3397 "\n", 3398 node->class_->scanner->display_prompt, 3399 _synctex_data_tag(node), 3400 _synctex_data_line(node), 3401 _synctex_data_h(node), 3402 _synctex_data_v(node), 3403 _synctex_data_width(node), 3404 _synctex_data_height(node), 3405 _synctex_data_depth(node) 3406 SYNCTEX_PRINT_CHARINDEX_WHAT); 3407 _synctex_display_sibling(node); 3408 } 3409 } 3410 3411 static char * _synctex_abstract_glue(synctex_node_p node) { 3412 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3413 if (node) { 3414 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"glue:%i,%i:%i,%i" 3415 SYNCTEX_PRINT_CHARINDEX_FMT, 3416 _synctex_data_tag(node), 3417 _synctex_data_line(node), 3418 _synctex_data_h(node), 3419 _synctex_data_v(node) 3420 SYNCTEX_PRINT_CHARINDEX_WHAT); 3421 } 3422 return abstract; 3423 } 3424 3425 static void _synctex_display_glue(synctex_node_p node) { 3426 if (node) { 3427 printf("%sglue:%i,%i:%i,%i" 3428 SYNCTEX_PRINT_CHARINDEX_FMT 3429 "\n", 3430 node->class_->scanner->display_prompt, 3431 _synctex_data_tag(node), 3432 _synctex_data_line(node), 3433 _synctex_data_h(node), 3434 _synctex_data_v(node) 3435 SYNCTEX_PRINT_CHARINDEX_WHAT); 3436 _synctex_display_sibling(node); 3437 } 3438 } 3439 3440 static char * _synctex_abstract_rule(synctex_node_p node) { 3441 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3442 if (node) { 3443 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"rule:%i,%i:%i,%i:%i,%i,%i" 3444 SYNCTEX_PRINT_CHARINDEX_FMT, 3445 _synctex_data_tag(node), 3446 _synctex_data_line(node), 3447 _synctex_data_h(node), 3448 _synctex_data_v(node), 3449 _synctex_data_width(node), 3450 _synctex_data_height(node), 3451 _synctex_data_depth(node) 3452 SYNCTEX_PRINT_CHARINDEX_WHAT); 3453 } 3454 return abstract; 3455 } 3456 3457 static void _synctex_display_rule(synctex_node_p node) { 3458 if (node) { 3459 printf("%srule:%i,%i:%i,%i:%i,%i,%i" 3460 SYNCTEX_PRINT_CHARINDEX_FMT 3461 "\n", 3462 node->class_->scanner->display_prompt, 3463 _synctex_data_tag(node), 3464 _synctex_data_line(node), 3465 _synctex_data_h(node), 3466 _synctex_data_v(node), 3467 _synctex_data_width(node), 3468 _synctex_data_height(node), 3469 _synctex_data_depth(node) 3470 SYNCTEX_PRINT_CHARINDEX_WHAT); 3471 _synctex_display_sibling(node); 3472 } 3473 } 3474 3475 static char * _synctex_abstract_math(synctex_node_p node) { 3476 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3477 if (node) { 3478 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"math:%i,%i:%i,%i" 3479 SYNCTEX_PRINT_CHARINDEX_FMT, 3480 _synctex_data_tag(node), 3481 _synctex_data_line(node), 3482 _synctex_data_h(node), 3483 _synctex_data_v(node) 3484 SYNCTEX_PRINT_CHARINDEX_WHAT); 3485 } 3486 return abstract; 3487 } 3488 3489 static void _synctex_display_math(synctex_node_p node) { 3490 if (node) { 3491 printf("%smath:%i,%i:%i,%i" 3492 SYNCTEX_PRINT_CHARINDEX_FMT 3493 "\n", 3494 node->class_->scanner->display_prompt, 3495 _synctex_data_tag(node), 3496 _synctex_data_line(node), 3497 _synctex_data_h(node), 3498 _synctex_data_v(node) 3499 SYNCTEX_PRINT_CHARINDEX_WHAT); 3500 _synctex_display_sibling(node); 3501 } 3502 } 3503 3504 static char * _synctex_abstract_kern(synctex_node_p node) { 3505 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3506 if (node) { 3507 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"kern:%i,%i:%i,%i:%i" 3508 SYNCTEX_PRINT_CHARINDEX_FMT, 3509 _synctex_data_tag(node), 3510 _synctex_data_line(node), 3511 _synctex_data_h(node), 3512 _synctex_data_v(node), 3513 _synctex_data_width(node) 3514 SYNCTEX_PRINT_CHARINDEX_WHAT); 3515 } 3516 return abstract; 3517 } 3518 3519 static void _synctex_display_kern(synctex_node_p node) { 3520 if (node) { 3521 printf("%skern:%i,%i:%i,%i:%i" 3522 SYNCTEX_PRINT_CHARINDEX_FMT 3523 "\n", 3524 node->class_->scanner->display_prompt, 3525 _synctex_data_tag(node), 3526 _synctex_data_line(node), 3527 _synctex_data_h(node), 3528 _synctex_data_v(node), 3529 _synctex_data_width(node) 3530 SYNCTEX_PRINT_CHARINDEX_WHAT); 3531 _synctex_display_sibling(node); 3532 } 3533 } 3534 3535 static char * _synctex_abstract_boundary(synctex_node_p node) { 3536 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3537 if (node) { 3538 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"boundary:%i,%i:%i,%i" 3539 SYNCTEX_PRINT_CHARINDEX_FMT, 3540 _synctex_data_tag(node), 3541 _synctex_data_line(node), 3542 _synctex_data_h(node), 3543 _synctex_data_v(node) 3544 SYNCTEX_PRINT_CHARINDEX_WHAT); 3545 } 3546 return abstract; 3547 } 3548 3549 static void _synctex_display_boundary(synctex_node_p node) { 3550 if (node) { 3551 printf("%sboundary:%i,%i:%i,%i" 3552 SYNCTEX_PRINT_CHARINDEX_FMT 3553 "\n", 3554 node->class_->scanner->display_prompt, 3555 _synctex_data_tag(node), 3556 _synctex_data_line(node), 3557 _synctex_data_h(node), 3558 _synctex_data_v(node) 3559 SYNCTEX_PRINT_CHARINDEX_WHAT); 3560 _synctex_display_sibling(node); 3561 } 3562 } 3563 3564 static char * _synctex_abstract_box_bdry(synctex_node_p node) { 3565 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3566 if (node) { 3567 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"box bdry:%i,%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, 3568 _synctex_data_tag(node), 3569 _synctex_data_line(node), 3570 _synctex_data_h(node), 3571 _synctex_data_v(node) 3572 SYNCTEX_PRINT_CHARINDEX_WHAT); 3573 } 3574 return abstract; 3575 } 3576 3577 static void _synctex_display_box_bdry(synctex_node_p node) { 3578 if (node) { 3579 printf("%sbox bdry:%i,%i:%i,%i", 3580 node->class_->scanner->display_prompt, 3581 _synctex_data_tag(node), 3582 _synctex_data_line(node), 3583 _synctex_data_h(node), 3584 _synctex_data_v(node)); 3585 SYNCTEX_PRINT_CHARINDEX_NL; 3586 _synctex_display_sibling(node); 3587 } 3588 } 3589 3590 static char * _synctex_abstract_ref(synctex_node_p node) { 3591 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3592 if (node) { 3593 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"form ref:%i:%i,%i" SYNCTEX_PRINT_CHARINDEX_FMT, 3594 _synctex_data_tag(node), 3595 _synctex_data_h(node), 3596 _synctex_data_v(node) 3597 SYNCTEX_PRINT_CHARINDEX_WHAT); 3598 } 3599 return abstract; 3600 } 3601 3602 static void _synctex_display_ref(synctex_node_p node) { 3603 if (node) { 3604 printf("%sform ref:%i:%i,%i", 3605 node->class_->scanner->display_prompt, 3606 _synctex_data_tag(node), 3607 _synctex_data_h(node), 3608 _synctex_data_v(node)); 3609 SYNCTEX_PRINT_CHARINDEX_NL; 3610 _synctex_display_sibling(node); 3611 } 3612 } 3613 static char * _synctex_abstract_proxy(synctex_node_p node) { 3614 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3615 if (node) { 3616 synctex_node_p N = _synctex_tree_target(node); 3617 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%i,%i:%i,%i/%p%s", 3618 synctex_node_isa(node), 3619 synctex_node_tag(node), 3620 synctex_node_line(node), 3621 _synctex_data_h(node), 3622 _synctex_data_v(node), 3623 node, 3624 _synctex_node_abstract(N)); 3625 } 3626 return abstract; 3627 } 3628 static void _synctex_display_proxy(synctex_node_p node) { 3629 if (node) { 3630 synctex_node_p N = _synctex_tree_target(node); 3631 printf("%s%s:%i,%i:%i,%i", 3632 node->class_->scanner->display_prompt, 3633 synctex_node_isa(node), 3634 synctex_node_tag(node), 3635 synctex_node_line(node), 3636 _synctex_data_h(node), 3637 _synctex_data_v(node)); 3638 if (N) { 3639 printf("=%i,%i:%i,%i,%i->%s", 3640 synctex_node_h(node), 3641 synctex_node_v(node), 3642 synctex_node_width(node), 3643 synctex_node_height(node), 3644 synctex_node_depth(node), 3645 _synctex_node_abstract(N)); 3646 } 3647 printf("\n"); 3648 _synctex_display_child(node); 3649 _synctex_display_sibling(node); 3650 } 3651 } 3652 static char * _synctex_abstract_proxy_vbox(synctex_node_p node) { 3653 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3654 if (node) { 3655 snprintf(abstract,SYNCTEX_ABSTRACT_MAX, 3656 "[*%i,%i:%i,%i:%i,%i,%i...*]" 3657 SYNCTEX_PRINT_CHARINDEX_FMT, 3658 synctex_node_tag(node), 3659 synctex_node_line(node), 3660 synctex_node_h(node), 3661 synctex_node_v(node), 3662 synctex_node_width(node), 3663 synctex_node_height(node), 3664 synctex_node_depth(node) 3665 SYNCTEX_PRINT_CHARINDEX_WHAT); 3666 } 3667 return abstract; 3668 } 3669 3670 static void _synctex_display_proxy_vbox(synctex_node_p node) { 3671 if (node) { 3672 printf("%s[*%i,%i:%i,%i:%i,%i,%i" 3673 SYNCTEX_PRINT_CHARINDEX_FMT 3674 "\n", 3675 node->class_->scanner->display_prompt, 3676 synctex_node_tag(node), 3677 synctex_node_line(node), 3678 synctex_node_h(node), 3679 synctex_node_v(node), 3680 synctex_node_width(node), 3681 synctex_node_height(node), 3682 synctex_node_depth(node) 3683 SYNCTEX_PRINT_CHARINDEX_WHAT); 3684 _synctex_display_child(node); 3685 printf("%s*]\n%slast:%s\n", 3686 node->class_->scanner->display_prompt, 3687 node->class_->scanner->display_prompt, 3688 _synctex_node_abstract(_synctex_tree_last(node))); 3689 _synctex_display_sibling(node); 3690 } 3691 } 3692 3693 static char * _synctex_abstract_proxy_hbox(synctex_node_p node) { 3694 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3695 if (node) { 3696 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"(*%i,%i~%i*%i:%i,%i:%i,%i,%i...*)/%p" 3697 SYNCTEX_PRINT_CHARINDEX_FMT, 3698 synctex_node_tag(node), 3699 synctex_node_line(node), 3700 synctex_node_mean_line(node), 3701 synctex_node_weight(node), 3702 synctex_node_h(node), 3703 synctex_node_v(node), 3704 synctex_node_width(node), 3705 synctex_node_height(node), 3706 synctex_node_depth(node), 3707 node 3708 SYNCTEX_PRINT_CHARINDEX_WHAT); 3709 } 3710 return abstract; 3711 } 3712 3713 static void _synctex_display_proxy_hbox(synctex_node_p node) { 3714 if (node) { 3715 printf("%s(*%i,%i~%i*%i:%i,%i:%i,%i,%i" 3716 SYNCTEX_PRINT_CHARINDEX_FMT 3717 "\n", 3718 node->class_->scanner->display_prompt, 3719 synctex_node_tag(node), 3720 synctex_node_line(node), 3721 synctex_node_mean_line(node), 3722 synctex_node_weight(node), 3723 synctex_node_h(node), 3724 synctex_node_v(node), 3725 synctex_node_width(node), 3726 synctex_node_height(node), 3727 synctex_node_depth(node) 3728 SYNCTEX_PRINT_CHARINDEX_WHAT); 3729 _synctex_display_child(node); 3730 printf("%s*)\n%slast:%s\n", 3731 node->class_->scanner->display_prompt, 3732 node->class_->scanner->display_prompt, 3733 _synctex_node_abstract(_synctex_tree_last(node))); 3734 _synctex_display_sibling(node); 3735 } 3736 } 3737 3738 static char * _synctex_abstract_handle(synctex_node_p node) { 3739 static char abstract[SYNCTEX_ABSTRACT_MAX] = "none"; 3740 if (node) { 3741 synctex_node_p N = _synctex_tree_target(node); 3742 if (N && !N->class_) { 3743 exit(1); 3744 } 3745 snprintf(abstract,SYNCTEX_ABSTRACT_MAX,"%s:%s", 3746 synctex_node_isa(node), 3747 (N?_synctex_node_abstract(N):"")); 3748 } 3749 return abstract; 3750 } 3751 static void _synctex_display_handle(synctex_node_p node) { 3752 if (node) { 3753 synctex_node_p N = _synctex_tree_target(node); 3754 printf("%s%s(%i):->%s\n", 3755 node->class_->scanner->display_prompt, 3756 synctex_node_isa(node), 3757 _synctex_data_weight(N), 3758 _synctex_node_abstract(N)); 3759 _synctex_display_child(node); 3760 _synctex_display_sibling(node); 3761 } 3762 } 3763 # ifdef SYNCTEX_NOTHING 3764 # pragma mark - 3765 # pragma mark STATUS 3766 # endif 3767 3768 # ifdef SYNCTEX_NOTHING 3769 # pragma mark - 3770 # pragma mark Prototypes 3771 # endif 3772 typedef struct { 3773 size_t size; 3774 synctex_status_t status; 3775 } synctex_zs_s; 3776 static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t size); 3777 static synctex_status_t _synctex_next_line(synctex_scanner_p scanner); 3778 static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char * the_string); 3779 3780 typedef struct synctex_ns_t { 3781 synctex_node_p node; 3782 synctex_status_t status; 3783 } synctex_ns_s; 3784 static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner); 3785 static synctex_status_t _synctex_scan_preamble(synctex_scanner_p scanner); 3786 typedef struct { 3787 float value; 3788 synctex_status_t status; 3789 } synctex_fs_s; 3790 static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner); 3791 static synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_p scanner); 3792 static synctex_status_t _synctex_scan_postamble(synctex_scanner_p scanner); 3793 static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box); 3794 static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner); 3795 int synctex_scanner_pre_x_offset(synctex_scanner_p scanner); 3796 int synctex_scanner_pre_y_offset(synctex_scanner_p scanner); 3797 const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner); 3798 3799 # ifdef SYNCTEX_NOTHING 3800 # pragma mark - 3801 # pragma mark SCANNER UTILITIES 3802 # endif 3803 3804 # define SYNCTEX_FILE (scanner->reader->file) 3805 3806 /** 3807 * Try to ensure that the buffer contains at least size bytes. 3808 * Passing a huge size argument means the whole buffer length. 3809 * Passing a 0 size argument means return the available buffer length, without reading the file. 3810 * In that case, the return status is always SYNCTEX_STATUS_OK unless the given scanner is NULL. 3811 * The size_t value returned is the number of bytes now available in the buffer. This is a nonnegative integer, it may take the value 0. 3812 * It is the responsibility of the caller to test whether this size is conforming to its needs. 3813 * Negative values may return in case of error, actually 3814 * when there was an error reading the synctex file. 3815 * - parameter scanner: The owning scanner. When NULL, returns SYNCTEX_STATUS_BAD_ARGUMENT. 3816 * - parameter expected: expected number of bytes. 3817 * - returns: a size and a status. 3818 */ 3819 static synctex_zs_s _synctex_buffer_get_available_size(synctex_scanner_p scanner, size_t expected) { 3820 size_t size = 0; 3821 if (NULL == scanner) { 3822 return (synctex_zs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT}; 3823 } 3824 if (expected>scanner->reader->size){ 3825 expected = scanner->reader->size; 3826 } 3827 size = SYNCTEX_END - SYNCTEX_CUR; /* available is the number of unparsed chars in the buffer */ 3828 if (expected<=size) { 3829 /* There are already sufficiently many characters in the buffer */ 3830 return (synctex_zs_s){size,SYNCTEX_STATUS_OK}; 3831 } 3832 if (SYNCTEX_FILE) { 3833 /* Copy the remaining part of the buffer to the beginning, 3834 * then read the next part of the file */ 3835 int already_read = 0; 3836 # if defined(SYNCTEX_USE_CHARINDEX) 3837 scanner->reader->charindex_offset += SYNCTEX_CUR - SYNCTEX_START; 3838 # endif 3839 if (size) { 3840 memmove(SYNCTEX_START, SYNCTEX_CUR, size); 3841 } 3842 SYNCTEX_CUR = SYNCTEX_START + size; /* the next character after the move, will change. */ 3843 /* Fill the buffer up to its end */ 3844 already_read = gzread(SYNCTEX_FILE,(void *)SYNCTEX_CUR,(int)(SYNCTEX_BUFFER_SIZE - size)); 3845 if (already_read>0) { 3846 /* We assume that 0<already_read<=SYNCTEX_BUFFER_SIZE - size, such that 3847 * SYNCTEX_CUR + already_read = SYNCTEX_START + size + already_read <= SYNCTEX_START + SYNCTEX_BUFFER_SIZE */ 3848 SYNCTEX_END = SYNCTEX_CUR + already_read; 3849 /* If the end of the file was reached, all the required SYNCTEX_BUFFER_SIZE - available 3850 * may not be filled with values from the file. 3851 * In that case, the buffer should stop properly after already_read characters. */ 3852 * SYNCTEX_END = '\0'; /* there is enough room */ 3853 SYNCTEX_CUR = SYNCTEX_START; 3854 /* May be available is less than size, the caller will have to test. */ 3855 return (synctex_zs_s){SYNCTEX_END - SYNCTEX_CUR,SYNCTEX_STATUS_OK}; 3856 } else if (0>already_read) { 3857 /* There is a possible error in reading the file */ 3858 int errnum = 0; 3859 const char * error_string = gzerror(SYNCTEX_FILE, &errnum); 3860 if (Z_ERRNO == errnum) { 3861 /* There is an error in zlib caused by the file system */ 3862 _synctex_error("gzread error from the file system (%i)",errno); 3863 return (synctex_zs_s){0,SYNCTEX_STATUS_ERROR}; 3864 } else if (errnum) { 3865 _synctex_error("gzread error (%i:%i,%s)",already_read,errnum,error_string); 3866 return (synctex_zs_s){0,SYNCTEX_STATUS_ERROR}; 3867 } 3868 } 3869 /* Nothing was read, we are at the end of the file. */ 3870 gzclose(SYNCTEX_FILE); 3871 SYNCTEX_FILE = NULL; 3872 SYNCTEX_END = SYNCTEX_CUR; 3873 SYNCTEX_CUR = SYNCTEX_START; 3874 * SYNCTEX_END = '\0';/* Terminate the string properly.*/ 3875 /* there might be a bit of text left */ 3876 return (synctex_zs_s){SYNCTEX_END - SYNCTEX_CUR,SYNCTEX_STATUS_EOF}; 3877 } 3878 /* We cannot enlarge the buffer because the end of the file was reached. */ 3879 return (synctex_zs_s){size,SYNCTEX_STATUS_EOF}; 3880 } 3881 3882 /* Used when parsing the synctex file. 3883 * Advance to the next character starting a line. 3884 * Actually, only '\n' is recognized as end of line marker. 3885 * On normal completion, the returned value is the number of unparsed characters available in the buffer. 3886 * In general, it is a positive value, 0 meaning that the end of file was reached. 3887 * -1 is returned in case of error, actually because there was an error while feeding the buffer. 3888 * When the function returns with no error, SYNCTEX_CUR points to the first character of the next line, if any. 3889 * J. Laurens: Sat May 10 07:52:31 UTC 2008 3890 */ 3891 static synctex_status_t _synctex_next_line(synctex_scanner_p scanner) { 3892 synctex_status_t status = SYNCTEX_STATUS_OK; 3893 if (NULL == scanner) { 3894 return SYNCTEX_STATUS_BAD_ARGUMENT; 3895 } 3896 infinite_loop: 3897 while(SYNCTEX_CUR<SYNCTEX_END) { 3898 if (*SYNCTEX_CUR == '\n') { 3899 ++SYNCTEX_CUR; 3900 ++scanner->reader->line_number; 3901 return _synctex_buffer_get_available_size(scanner, 1).status; 3902 } 3903 ++SYNCTEX_CUR; 3904 } 3905 /* Here, we have SYNCTEX_CUR == SYNCTEX_END, such that the next call to _synctex_buffer_get_available_size 3906 * will read another bunch of synctex file. Little by little, we advance to the end of the file. */ 3907 status = _synctex_buffer_get_available_size(scanner, 1).status; 3908 if (status<=SYNCTEX_STATUS_EOF) { 3909 return status; 3910 } 3911 goto infinite_loop; 3912 } 3913 3914 /* Scan the given string. 3915 * Both scanner and the_string must not be NULL, and the_string must not be 0 length. 3916 * SYNCTEX_STATUS_OK is returned if the string is found, 3917 * SYNCTEX_STATUS_EOF is returned when the EOF is reached, 3918 * SYNCTEX_STATUS_NOT_OK is returned is the string is not found, 3919 * an error status is returned otherwise. 3920 * This is a critical method because buffering renders things more difficult. 3921 * The given string might be as long as the maximum size_t value. 3922 * As side effect, the buffer state may have changed if the given argument string can't fit into the buffer. 3923 */ 3924 static synctex_status_t _synctex_match_string(synctex_scanner_p scanner, const char * the_string) { 3925 size_t tested_len = 0; /* the number of characters at the beginning of the_string that match */ 3926 size_t remaining_len = 0; /* the number of remaining characters of the_string that should match */ 3927 size_t available = 0; 3928 synctex_zs_s zs = {0,0}; 3929 if (NULL == scanner || NULL == the_string) { 3930 return SYNCTEX_STATUS_BAD_ARGUMENT; 3931 } 3932 remaining_len = strlen(the_string); /* All the_string should match */ 3933 if (0 == remaining_len) { 3934 return SYNCTEX_STATUS_BAD_ARGUMENT; 3935 } 3936 /* How many characters available in the buffer? */ 3937 zs = _synctex_buffer_get_available_size(scanner,remaining_len); 3938 if (zs.status<SYNCTEX_STATUS_EOF) { 3939 return zs.status; 3940 } 3941 /* Maybe we have less characters than expected because the buffer is too small. */ 3942 if (zs.size>=remaining_len) { 3943 /* The buffer is sufficiently big to hold the expected number of characters. */ 3944 if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) { 3945 return SYNCTEX_STATUS_NOT_OK; 3946 } 3947 return_OK: 3948 /* Advance SYNCTEX_CUR to the next character after the_string. */ 3949 SYNCTEX_CUR += remaining_len; 3950 return SYNCTEX_STATUS_OK; 3951 } else if (strncmp((char *)SYNCTEX_CUR,the_string,zs.size)) { 3952 /* No need to go further, this is not the expected string in the buffer. */ 3953 return SYNCTEX_STATUS_NOT_OK; 3954 } else if (SYNCTEX_FILE) { 3955 /* The buffer was too small to contain remaining_len characters. 3956 * We have to cut the string into pieces. */ 3957 z_off_t offset = 0L; 3958 /* the first part of the string is found, advance the_string to the next untested character. */ 3959 the_string += zs.size; 3960 /* update the remaining length and the parsed length. */ 3961 remaining_len -= zs.size; 3962 tested_len += zs.size; 3963 SYNCTEX_CUR += zs.size; /* We validate the tested characters. */ 3964 if (0 == remaining_len) { 3965 /* Nothing left to test, we have found the given string. */ 3966 return SYNCTEX_STATUS_OK; 3967 } 3968 /* We also have to record the current state of the file cursor because 3969 * if the_string does not match, all this should be a totally blank operation, 3970 * for which the file and buffer states should not be modified at all. 3971 * In fact, the states of the buffer before and after this function are in general different 3972 * but they are totally equivalent as long as the values of the buffer before SYNCTEX_CUR 3973 * can be safely discarded. */ 3974 offset = gztell(SYNCTEX_FILE); 3975 /* offset now corresponds to the first character of the file that was not buffered. */ 3976 /* SYNCTEX_CUR - SYNCTEX_START is the number of chars that where already buffered and 3977 * that match the head of the_string. If in fine the_string does not match, all these chars must be recovered 3978 * because the whole buffer contents is replaced in _synctex_buffer_get_available_size. 3979 * They were buffered from offset-len location in the file. */ 3980 offset -= SYNCTEX_CUR - SYNCTEX_START; 3981 more_characters: 3982 /* There is still some work to be done, so read another bunch of file. 3983 * This is the second call to _synctex_buffer_get_available_size, 3984 * which means that the actual contents of the buffer will be discarded. 3985 * We will definitely have to recover the previous state in case we do not find the expected string. */ 3986 zs = _synctex_buffer_get_available_size(scanner,remaining_len); 3987 if (zs.status<SYNCTEX_STATUS_EOF) { 3988 return zs.status; /* This is an error, no need to go further. */ 3989 } 3990 if (zs.size==0) { 3991 /* Missing characters: recover the initial state of the file and return. */ 3992 return_NOT_OK: 3993 if (offset != gzseek(SYNCTEX_FILE,offset,SEEK_SET)) { 3994 /* This is a critical error, we could not recover the previous state. */ 3995 _synctex_error("Can't seek file"); 3996 return SYNCTEX_STATUS_ERROR; 3997 } 3998 /* Next time we are asked to fill the buffer, 3999 * we will read a complete bunch of text from the file. */ 4000 SYNCTEX_CUR = SYNCTEX_END; 4001 return SYNCTEX_STATUS_NOT_OK; 4002 } 4003 if (zs.size<remaining_len) { 4004 /* We'll have to loop one more time. */ 4005 if (strncmp((char *)SYNCTEX_CUR,the_string,zs.size)) { 4006 /* This is not the expected string, recover the previous state and return. */ 4007 goto return_NOT_OK; 4008 } 4009 /* Advance the_string to the first untested character. */ 4010 the_string += available; 4011 /* update the remaining length and the parsed length. */ 4012 remaining_len -= zs.size; 4013 tested_len += zs.size; 4014 SYNCTEX_CUR += zs.size; /* We validate the tested characters. */ 4015 goto more_characters; 4016 } 4017 /* This is the last step. */ 4018 if (strncmp((char *)SYNCTEX_CUR,the_string,remaining_len)) { 4019 /* This is not the expected string, recover the previous state and return. */ 4020 goto return_NOT_OK; 4021 } 4022 goto return_OK; 4023 } else { 4024 /* The buffer can't contain the given string argument, and the EOF was reached */ 4025 return SYNCTEX_STATUS_EOF; 4026 } 4027 } 4028 4029 /* Used when parsing the synctex file. 4030 * Decode an integer. 4031 * First, field separators, namely ':' and ',' characters are skipped 4032 * The returned value is negative if there is an unrecoverable error. 4033 * It is SYNCTEX_STATUS_NOT_OK if an integer could not be parsed, for example 4034 * if the characters at the current cursor position are not digits or 4035 * if the end of the file has been reached. 4036 * It is SYNCTEX_STATUS_OK if an int has been successfully parsed. 4037 * The given scanner argument must not be NULL, on the contrary, value_ref may be NULL. 4038 */ 4039 static synctex_is_s _synctex_decode_int(synctex_scanner_p scanner) { 4040 char * ptr = NULL; 4041 char * end = NULL; 4042 synctex_zs_s zs = {0,0}; 4043 int result; 4044 if (NULL == scanner) { 4045 return (synctex_is_s){0, SYNCTEX_STATUS_BAD_ARGUMENT}; 4046 } 4047 zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE); 4048 if (zs.status<SYNCTEX_STATUS_EOF) { 4049 return (synctex_is_s){0,zs.status}; 4050 } 4051 if (zs.size==0) { 4052 return (synctex_is_s){0,SYNCTEX_STATUS_NOT_OK}; 4053 } 4054 ptr = SYNCTEX_CUR; 4055 /* Optionally parse the separator */ 4056 if (*ptr==':' || *ptr==',') { 4057 ++ptr; 4058 --zs.size; 4059 if (zs.size==0) { 4060 return (synctex_is_s){0,SYNCTEX_STATUS_NOT_OK}; 4061 } 4062 } 4063 result = (int)strtol(ptr, &end, 10); 4064 if (end>ptr) { 4065 SYNCTEX_CUR = end; 4066 return (synctex_is_s){result,SYNCTEX_STATUS_OK}; 4067 } 4068 return (synctex_is_s){result,SYNCTEX_STATUS_NOT_OK}; 4069 } 4070 static synctex_is_s _synctex_decode_int_opt(synctex_scanner_p scanner, int default_value) { 4071 char * ptr = NULL; 4072 char * end = NULL; 4073 synctex_zs_s zs = {0, 0}; 4074 if (NULL == scanner) { 4075 return (synctex_is_s){default_value, SYNCTEX_STATUS_BAD_ARGUMENT}; 4076 } 4077 zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE); 4078 if (zs.status<SYNCTEX_STATUS_EOF) { 4079 return (synctex_is_s){default_value,zs.status}; 4080 } 4081 if (zs.size==0) { 4082 return (synctex_is_s){default_value,SYNCTEX_STATUS_OK}; 4083 } 4084 ptr = SYNCTEX_CUR; 4085 /* Comma separator required */ 4086 if (*ptr==',') { 4087 int result; 4088 ++ptr; 4089 --zs.size; 4090 if (zs.size==0) { 4091 return (synctex_is_s){default_value,SYNCTEX_STATUS_NOT_OK}; 4092 } 4093 result = (int)strtol(ptr, &end, 10); 4094 if (end>ptr) { 4095 SYNCTEX_CUR = end; 4096 return (synctex_is_s){result,SYNCTEX_STATUS_OK}; 4097 } 4098 return (synctex_is_s){default_value,SYNCTEX_STATUS_NOT_OK}; 4099 } 4100 return (synctex_is_s){default_value,SYNCTEX_STATUS_OK}; 4101 } 4102 /* Used when parsing the synctex file. 4103 * Decode an integer for a v field. 4104 * Try the _synctex_decode_int version and set the last v field scanned. 4105 * If it does not succeed, tries to match an '=' sign, 4106 * which is a shortcut for the last v field scanned. 4107 */ 4108 # define SYNCTEX_INPUT_COMEQUALS ",=" 4109 static synctex_is_s _synctex_decode_int_v(synctex_scanner_p scanner) { 4110 synctex_is_s is = _synctex_decode_int(scanner); 4111 if (SYNCTEX_STATUS_OK == is.status) { 4112 scanner->reader->lastv = is.integer; 4113 return is; 4114 } 4115 is.status = _synctex_match_string(scanner,SYNCTEX_INPUT_COMEQUALS); 4116 if (is.status<SYNCTEX_STATUS_OK) { 4117 return is; 4118 } 4119 is.integer = scanner->reader->lastv; 4120 return is; 4121 } 4122 4123 /* The purpose of this function is to read a string. 4124 * A string is an array of characters from the current parser location 4125 * and before the next '\n' character. 4126 * If a string was properly decoded, it is returned in value_ref and 4127 * the cursor points to the new line marker. 4128 * The returned string was allocated on the heap, the caller is the owner and 4129 * is responsible to free it in due time, 4130 * unless it transfers the ownership to another object. 4131 * If no string is parsed, * value_ref is undefined. 4132 * The maximum length of a string that a scanner can decode is platform dependent, namely UINT_MAX. 4133 * If you just want to blindly parse the file up to the end of the current line, 4134 * use _synctex_next_line instead. 4135 * On return, the scanner cursor is unchanged if a string could not be scanned or 4136 * points to the terminating '\n' character otherwise. As a consequence, 4137 * _synctex_next_line is necessary after. 4138 * If either scanner or value_ref is NULL, it is considered as an error and 4139 * SYNCTEX_STATUS_BAD_ARGUMENT is returned. 4140 */ 4141 static synctex_ss_s _synctex_decode_string(synctex_scanner_p scanner) { 4142 char * end = NULL; 4143 size_t len = 0;/* The number of bytes to copy */ 4144 size_t already_len = 0; 4145 synctex_zs_s zs = {0,0}; 4146 char * string = NULL; 4147 if (NULL == scanner) { 4148 return (synctex_ss_s){NULL,SYNCTEX_STATUS_BAD_ARGUMENT}; 4149 } 4150 /* The buffer must at least contain one character: the '\n' end of line marker */ 4151 if (SYNCTEX_CUR>=SYNCTEX_END) { 4152 more_characters: 4153 zs = _synctex_buffer_get_available_size(scanner,1); 4154 if (zs.status < SYNCTEX_STATUS_EOF) { 4155 return (synctex_ss_s){NULL,zs.status}; 4156 } else if (0 == zs.size) { 4157 return (synctex_ss_s){NULL,SYNCTEX_STATUS_EOF}; 4158 } 4159 } 4160 /* Now we are sure that there is at least one available character, either because 4161 * SYNCTEX_CUR was already < SYNCTEX_END, or because the buffer has been properly filled. */ 4162 /* end will point to the next unparsed '\n' character in the file, when mapped to the buffer. */ 4163 end = SYNCTEX_CUR; 4164 /* We scan all the characters up to the next '\n' */ 4165 while (end<SYNCTEX_END && *end != '\n') { 4166 ++end; 4167 } 4168 /* OK, we found where to stop: 4169 * either end == SYNCTEX_END 4170 * or *end == '\n' */ 4171 len = end - SYNCTEX_CUR; 4172 if (len<UINT_MAX-already_len) { 4173 if ((string = realloc(string,len+already_len+1)) != NULL) { 4174 if (memcpy(string+already_len,SYNCTEX_CUR,len)) { 4175 already_len += len; 4176 string[already_len]='\0'; /* Terminate the string */ 4177 SYNCTEX_CUR += len;/* Eventually advance to the terminating '\n' */ 4178 if (SYNCTEX_CUR==SYNCTEX_END) { 4179 /* No \n found*/ 4180 goto more_characters; 4181 } 4182 /* trim the trailing whites */ 4183 len = already_len; 4184 while (len>0) { 4185 already_len = len--; 4186 if (string[len]!=' ') { 4187 break; 4188 } 4189 } 4190 string[already_len] = '\0'; 4191 return (synctex_ss_s){string,SYNCTEX_STATUS_OK}; 4192 } 4193 free(string); 4194 _synctex_error("could not copy memory (1)."); 4195 return (synctex_ss_s){NULL,SYNCTEX_STATUS_ERROR}; 4196 } 4197 } 4198 _synctex_error("could not (re)allocate memory (1)."); 4199 return (synctex_ss_s){NULL,SYNCTEX_STATUS_ERROR}; 4200 } 4201 4202 /* Used when parsing the synctex file. 4203 * Read an Input record. 4204 * - parameter scanner: non NULL scanner 4205 * - returns SYNCTEX_STATUS_OK on successful completions, others values otherwise. 4206 */ 4207 static synctex_ns_s __synctex_parse_new_input(synctex_scanner_p scanner) { 4208 synctex_node_p input = NULL; 4209 synctex_status_t status = SYNCTEX_STATUS_BAD_ARGUMENT; 4210 synctex_zs_s zs = {0,0}; 4211 if (NULL == scanner) { 4212 return (synctex_ns_s){NULL,status}; 4213 } 4214 if ((status=_synctex_match_string(scanner,SYNCTEX_INPUT_MARK))<SYNCTEX_STATUS_OK) { 4215 return (synctex_ns_s){NULL,status}; 4216 } 4217 /* Create a node */ 4218 if (NULL == (input = _synctex_new_input(scanner))) { 4219 _synctex_error("Could not create an input node."); 4220 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4221 } 4222 /* Decode the tag */ 4223 if ((status=_synctex_data_decode_tag(input))<SYNCTEX_STATUS_OK) { 4224 _synctex_error("Bad format of input node."); 4225 synctex_node_free(input); 4226 return (synctex_ns_s){NULL,status}; 4227 } 4228 /* The next character is a field separator, we expect one character in the buffer. */ 4229 zs = _synctex_buffer_get_available_size(scanner, 1); 4230 if (zs.status<=SYNCTEX_STATUS_ERROR) { 4231 return (synctex_ns_s){NULL,status}; 4232 } 4233 if (0 == zs.size) { 4234 return (synctex_ns_s){NULL,SYNCTEX_STATUS_EOF}; 4235 } 4236 /* We can now safely advance to the next character, stepping over the field separator. */ 4237 ++SYNCTEX_CUR; 4238 --zs.size; 4239 /* Then we scan the file name */ 4240 if ((status=_synctex_data_decode_name(input))<SYNCTEX_STATUS_OK) { 4241 synctex_node_free(input); 4242 _synctex_next_line(scanner);/* Ignore this whole line */ 4243 return (synctex_ns_s){NULL,status}; 4244 } 4245 /* Prepend this input node to the input linked list of the scanner */ 4246 __synctex_tree_set_sibling(input,scanner->input);/* input has no parent */ 4247 scanner->input = input; 4248 # if SYNCTEX_VERBOSE 4249 synctex_node_log(input); 4250 # endif 4251 return (synctex_ns_s){input,_synctex_next_line(scanner)};/* read the line termination character, if any */ 4252 } 4253 4254 typedef synctex_is_s (*synctex_decoder_t)(synctex_scanner_p); 4255 4256 /* Used when parsing the synctex file. 4257 * Read one of the settings. 4258 * On normal completion, returns SYNCTEX_STATUS_OK. 4259 * On error, returns SYNCTEX_STATUS_ERROR. 4260 * Both arguments must not be NULL. 4261 * On return, the scanner points to the next character after the decoded object whatever it is. 4262 * It is the responsibility of the caller to prepare the scanner for the next line. 4263 */ 4264 static synctex_status_t _synctex_scan_named(synctex_scanner_p scanner,const char * name) { 4265 synctex_status_t status = 0; 4266 if (NULL == scanner || NULL == name) { 4267 return SYNCTEX_STATUS_BAD_ARGUMENT; 4268 } 4269 not_found: 4270 status = _synctex_match_string(scanner,name); 4271 if (status<SYNCTEX_STATUS_NOT_OK) { 4272 return status; 4273 } else if (status == SYNCTEX_STATUS_NOT_OK) { 4274 status = _synctex_next_line(scanner); 4275 if (status<SYNCTEX_STATUS_OK) { 4276 return status; 4277 } 4278 goto not_found; 4279 } 4280 return SYNCTEX_STATUS_OK; 4281 } 4282 4283 /* Used when parsing the synctex file. 4284 * Read the preamble. 4285 */ 4286 static synctex_status_t _synctex_scan_preamble(synctex_scanner_p scanner) { 4287 synctex_status_t status = 0; 4288 synctex_is_s is = {0,0}; 4289 synctex_ss_s ss = {NULL,0}; 4290 if (NULL == scanner) { 4291 return SYNCTEX_STATUS_BAD_ARGUMENT; 4292 } 4293 status = _synctex_scan_named(scanner,"SyncTeX Version:"); 4294 if (status<SYNCTEX_STATUS_OK) { 4295 return status; 4296 } 4297 is = _synctex_decode_int(scanner); 4298 if (is.status<SYNCTEX_STATUS_OK) { 4299 return is.status; 4300 } 4301 status = _synctex_next_line(scanner); 4302 if (status<SYNCTEX_STATUS_OK) { 4303 return status; 4304 } 4305 scanner->version = is.integer; 4306 /* Read all the input records */ 4307 do { 4308 status = __synctex_parse_new_input(scanner).status; 4309 if (status<SYNCTEX_STATUS_NOT_OK) { 4310 return status; 4311 } 4312 } while(status == SYNCTEX_STATUS_OK); 4313 /* the loop exits when status == SYNCTEX_STATUS_NOT_OK */ 4314 /* Now read all the required settings. */ 4315 if ((status=_synctex_scan_named(scanner,"Output:"))<SYNCTEX_STATUS_OK) { 4316 return status; 4317 } 4318 if ((ss=_synctex_decode_string(scanner)).status<SYNCTEX_STATUS_OK) { 4319 return is.status; 4320 } 4321 if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) { 4322 return status; 4323 } 4324 scanner->output_fmt = ss.string; 4325 if ((status=_synctex_scan_named(scanner,"Magnification:"))<SYNCTEX_STATUS_OK) { 4326 return status; 4327 } 4328 if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) { 4329 return is.status; 4330 } 4331 if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) { 4332 return status; 4333 } 4334 scanner->pre_magnification = is.integer; 4335 if ((status=_synctex_scan_named(scanner,"Unit:"))<SYNCTEX_STATUS_OK) { 4336 return status; 4337 } 4338 if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) { 4339 return is.status; 4340 } 4341 if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) { 4342 return status; 4343 } 4344 scanner->pre_unit = is.integer; 4345 if ((status=_synctex_scan_named(scanner,"X Offset:"))<SYNCTEX_STATUS_OK) { 4346 return status; 4347 } 4348 if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) { 4349 return is.status; 4350 } 4351 if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) { 4352 return status; 4353 } 4354 scanner->pre_x_offset = is.integer; 4355 if ((status=_synctex_scan_named(scanner,"Y Offset:"))<SYNCTEX_STATUS_OK) { 4356 return status; 4357 } 4358 if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) { 4359 return is.status; 4360 } 4361 if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) { 4362 return status; 4363 } 4364 scanner->pre_y_offset = is.integer; 4365 return SYNCTEX_STATUS_OK; 4366 } 4367 4368 /* parse a float with a dimension */ 4369 static synctex_fs_s _synctex_scan_float_and_dimension(synctex_scanner_p scanner) { 4370 synctex_fs_s fs = {0,0}; 4371 synctex_zs_s zs = {0,0}; 4372 char * endptr = NULL; 4373 #ifdef HAVE_SETLOCALE 4374 char * loc = setlocale(LC_NUMERIC, NULL); 4375 #endif 4376 if (NULL == scanner) { 4377 return (synctex_fs_s){0,SYNCTEX_STATUS_BAD_ARGUMENT}; 4378 } 4379 zs = _synctex_buffer_get_available_size(scanner, SYNCTEX_BUFFER_MIN_SIZE); 4380 if (zs.status<SYNCTEX_STATUS_EOF) { 4381 _synctex_error("Problem with float."); 4382 return (synctex_fs_s){0,zs.status}; 4383 } 4384 #ifdef HAVE_SETLOCALE 4385 setlocale(LC_NUMERIC, "C"); 4386 #endif 4387 fs.value = strtod(SYNCTEX_CUR,&endptr); 4388 #ifdef HAVE_SETLOCALE 4389 setlocale(LC_NUMERIC, loc); 4390 #endif 4391 if (endptr == SYNCTEX_CUR) { 4392 _synctex_error("A float was expected."); 4393 return (synctex_fs_s){0,SYNCTEX_STATUS_ERROR}; 4394 } 4395 SYNCTEX_CUR = endptr; 4396 if ((fs.status = _synctex_match_string(scanner,"in")) >= SYNCTEX_STATUS_OK) { 4397 fs.value *= 72.27f*65536; 4398 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4399 report_unit_error: 4400 _synctex_error("problem with unit."); 4401 return fs; 4402 } else if ((fs.status = _synctex_match_string(scanner,"cm")) >= SYNCTEX_STATUS_OK) { 4403 fs.value *= 72.27f*65536/2.54f; 4404 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4405 goto report_unit_error; 4406 } else if ((fs.status = _synctex_match_string(scanner,"mm")) >= SYNCTEX_STATUS_OK) { 4407 fs.value *= 72.27f*65536/25.4f; 4408 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4409 goto report_unit_error; 4410 } else if ((fs.status = _synctex_match_string(scanner,"pt")) >= SYNCTEX_STATUS_OK) { 4411 fs.value *= 65536.0f; 4412 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4413 goto report_unit_error; 4414 } else if ((fs.status = _synctex_match_string(scanner,"bp")) >= SYNCTEX_STATUS_OK) { 4415 fs.value *= 72.27f/72*65536.0f; 4416 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4417 goto report_unit_error; 4418 } else if ((fs.status = _synctex_match_string(scanner,"pc")) >= SYNCTEX_STATUS_OK) { 4419 fs.value *= 12.0*65536.0f; 4420 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4421 goto report_unit_error; 4422 } else if ((fs.status = _synctex_match_string(scanner,"sp")) >= SYNCTEX_STATUS_OK) { 4423 fs.value *= 1.0f; 4424 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4425 goto report_unit_error; 4426 } else if ((fs.status = _synctex_match_string(scanner,"dd")) >= SYNCTEX_STATUS_OK) { 4427 fs.value *= 1238.0f/1157*65536.0f; 4428 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4429 goto report_unit_error; 4430 } else if ((fs.status = _synctex_match_string(scanner,"cc")) >= SYNCTEX_STATUS_OK) { 4431 fs.value *= 14856.0f/1157*65536; 4432 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4433 goto report_unit_error; 4434 } else if ((fs.status = _synctex_match_string(scanner,"nd")) >= SYNCTEX_STATUS_OK) { 4435 fs.value *= 685.0f/642*65536; 4436 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4437 goto report_unit_error; 4438 } else if ((fs.status = _synctex_match_string(scanner,"nc")) >= SYNCTEX_STATUS_OK) { 4439 fs.value *= 1370.0f/107*65536; 4440 } else if (fs.status<SYNCTEX_STATUS_EOF) { 4441 goto report_unit_error; 4442 } 4443 return fs; 4444 } 4445 4446 /* parse the post scriptum 4447 * SYNCTEX_STATUS_OK is returned on completion 4448 * a negative error is returned otherwise */ 4449 static synctex_status_t _synctex_scan_post_scriptum(synctex_scanner_p scanner) { 4450 synctex_status_t status = 0; 4451 synctex_fs_s fs = {0,0}; 4452 char * endptr = NULL; 4453 #ifdef HAVE_SETLOCALE 4454 char * loc = setlocale(LC_NUMERIC, NULL); 4455 #endif 4456 if (NULL == scanner) { 4457 return SYNCTEX_STATUS_BAD_ARGUMENT; 4458 } 4459 /* Scan the file until a post scriptum line is found */ 4460 post_scriptum_not_found: 4461 status = _synctex_match_string(scanner,"Post scriptum:"); 4462 if (status<SYNCTEX_STATUS_NOT_OK) { 4463 return status; 4464 } 4465 if (status == SYNCTEX_STATUS_NOT_OK) { 4466 status = _synctex_next_line(scanner); 4467 if (status<SYNCTEX_STATUS_EOF) { 4468 return status; 4469 } else if (status<SYNCTEX_STATUS_OK) { 4470 return SYNCTEX_STATUS_OK;/* The EOF is found, we have properly scanned the file */ 4471 } 4472 goto post_scriptum_not_found; 4473 } 4474 /* We found the name, advance to the next line. */ 4475 next_line: 4476 status = _synctex_next_line(scanner); 4477 if (status<SYNCTEX_STATUS_EOF) { 4478 return status; 4479 } else if (status<SYNCTEX_STATUS_OK) { 4480 return SYNCTEX_STATUS_OK;/* The EOF is found, we have properly scanned the file */ 4481 } 4482 /* Scanning the information */ 4483 status = _synctex_match_string(scanner,"Magnification:"); 4484 if (status == SYNCTEX_STATUS_OK ) { 4485 #ifdef HAVE_SETLOCALE 4486 setlocale(LC_NUMERIC, "C"); 4487 #endif 4488 scanner->unit = strtod(SYNCTEX_CUR,&endptr); 4489 #ifdef HAVE_SETLOCALE 4490 setlocale(LC_NUMERIC, loc); 4491 #endif 4492 if (endptr == SYNCTEX_CUR) { 4493 _synctex_error("bad magnification in the post scriptum, a float was expected."); 4494 return SYNCTEX_STATUS_ERROR; 4495 } 4496 if (scanner->unit<=0) { 4497 _synctex_error("bad magnification in the post scriptum, a positive float was expected."); 4498 return SYNCTEX_STATUS_ERROR; 4499 } 4500 SYNCTEX_CUR = endptr; 4501 goto next_line; 4502 } 4503 if (status<SYNCTEX_STATUS_EOF){ 4504 report_record_problem: 4505 _synctex_error("Problem reading the Post Scriptum records"); 4506 return status; /* echo the error. */ 4507 } 4508 status = _synctex_match_string(scanner,"X Offset:"); 4509 if (status == SYNCTEX_STATUS_OK) { 4510 fs = _synctex_scan_float_and_dimension(scanner); 4511 if (fs.status<SYNCTEX_STATUS_OK) { 4512 _synctex_error("Problem with X offset in the Post Scriptum."); 4513 return fs.status; 4514 } 4515 scanner->x_offset = fs.value; 4516 goto next_line; 4517 } else if (status<SYNCTEX_STATUS_EOF){ 4518 goto report_record_problem; 4519 } 4520 status = _synctex_match_string(scanner,"Y Offset:"); 4521 if (status==SYNCTEX_STATUS_OK) { 4522 fs = _synctex_scan_float_and_dimension(scanner); 4523 if (fs.status<SYNCTEX_STATUS_OK) { 4524 _synctex_error("Problem with Y offset in the Post Scriptum."); 4525 return fs.status; 4526 } 4527 scanner->x_offset = fs.value; 4528 goto next_line; 4529 } else if (status<SYNCTEX_STATUS_EOF){ 4530 goto report_record_problem; 4531 } 4532 goto next_line; 4533 } 4534 4535 /* SYNCTEX_STATUS_OK is returned if the postamble is read 4536 * SYNCTEX_STATUS_NOT_OK is returned if the postamble is not at the current location 4537 * a negative error otherwise 4538 * The postamble comprises the post scriptum section. 4539 */ 4540 static synctex_status_t _synctex_scan_postamble(synctex_scanner_p scanner) { 4541 synctex_status_t status = 0; 4542 synctex_is_s is = {0,0}; 4543 if (NULL == scanner) { 4544 return SYNCTEX_STATUS_BAD_ARGUMENT; 4545 } 4546 if (!scanner->flags.postamble && (status=_synctex_match_string(scanner,"Postamble:"))<SYNCTEX_STATUS_OK) { 4547 return status; 4548 } 4549 count_again: 4550 if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) { 4551 return status; 4552 } 4553 if ((status=_synctex_scan_named(scanner,"Count:"))< SYNCTEX_STATUS_EOF) { 4554 return status; /* forward the error */ 4555 } else if (status < SYNCTEX_STATUS_OK) { /* No Count record found */ 4556 goto count_again; 4557 } 4558 if ((is=_synctex_decode_int(scanner)).status<SYNCTEX_STATUS_OK) { 4559 return is.status; 4560 } 4561 if ((status=_synctex_next_line(scanner))<SYNCTEX_STATUS_OK) { 4562 return status; 4563 } 4564 scanner->count = is.integer; 4565 /* Now we scan the last part of the SyncTeX file: the Post Scriptum section. */ 4566 return _synctex_scan_post_scriptum(scanner); 4567 } 4568 4569 /* Horizontal boxes also have visible size. 4570 * Visible size are bigger than real size. 4571 * For example 0 width boxes may contain text. 4572 * At creation time, the visible size is set to the values of the real size. 4573 */ 4574 static synctex_status_t _synctex_setup_visible_hbox(synctex_node_p box) { 4575 if (box) { 4576 switch(synctex_node_type(box)) { 4577 case synctex_node_type_hbox: 4578 _synctex_data_set_h_V(box,_synctex_data_h(box)); 4579 _synctex_data_set_v_V(box,_synctex_data_v(box)); 4580 _synctex_data_set_width_V(box,_synctex_data_width(box)); 4581 _synctex_data_set_height_V(box,_synctex_data_height(box)); 4582 _synctex_data_set_depth_V(box,_synctex_data_depth(box)); 4583 return SYNCTEX_STATUS_OK; 4584 default: 4585 break; 4586 } 4587 } 4588 return SYNCTEX_STATUS_BAD_ARGUMENT; 4589 } 4590 4591 /* This method is sent to an horizontal box to setup the visible size 4592 * Some box have 0 width but do contain text material. 4593 * With this method, one can enlarge the box to contain the given point (h,v). 4594 */ 4595 static synctex_status_t _synctex_make_hbox_contain_point(synctex_node_p node,synctex_point_s point) { 4596 int min, max, n; 4597 if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) { 4598 return SYNCTEX_STATUS_BAD_ARGUMENT; 4599 } 4600 if ((n = _synctex_data_width_V(node))<0) { 4601 max = _synctex_data_h_V(node); 4602 min = max+n; 4603 if (point.h<min) { 4604 _synctex_data_set_width_V(node,point.h-max); 4605 } else if (point.h>max) { 4606 _synctex_data_set_h_V(node,point.h); 4607 _synctex_data_set_width_V(node,min-point.h); 4608 } 4609 } else { 4610 min = _synctex_data_h_V(node); 4611 max = min+n; 4612 if (point.h<min) { 4613 _synctex_data_set_h_V(node,point.h); 4614 _synctex_data_set_width_V(node,max - point.h); 4615 } else if (point.h>max) { 4616 _synctex_data_set_width_V(node,point.h - min); 4617 } 4618 } 4619 n = _synctex_data_v_V(node); 4620 min = n - _synctex_data_height_V(node); 4621 max = n + _synctex_data_depth_V(node); 4622 if (point.v<min) { 4623 _synctex_data_set_height_V(node,n-point.v); 4624 } else if (point.v>max) { 4625 _synctex_data_set_depth_V(node,point.v-n); 4626 } 4627 return SYNCTEX_STATUS_OK; 4628 } 4629 static synctex_status_t _synctex_make_hbox_contain_box(synctex_node_p node,synctex_box_s box) { 4630 int min, max, n; 4631 if (NULL == node || synctex_node_type(node) != synctex_node_type_hbox) { 4632 return SYNCTEX_STATUS_BAD_ARGUMENT; 4633 } 4634 if ((n = _synctex_data_width_V(node))<0) { 4635 max = _synctex_data_h_V(node); 4636 min = max+n; 4637 if (box.min.h <min) { 4638 _synctex_data_set_width_V(node,box.min.h-max); 4639 } else if (box.max.h>max) { 4640 _synctex_data_set_h_V(node,box.max.h); 4641 _synctex_data_set_width_V(node,min-box.max.h); 4642 } 4643 } else { 4644 min = _synctex_data_h_V(node); 4645 max = min+n; 4646 if (box.min.h<min) { 4647 _synctex_data_set_h_V(node,box.min.h); 4648 _synctex_data_set_width_V(node,max - box.min.h); 4649 } else if (box.max.h>max) { 4650 _synctex_data_set_width_V(node,box.max.h - min); 4651 } 4652 } 4653 n = _synctex_data_v_V(node); 4654 min = n - _synctex_data_height_V(node); 4655 max = n + _synctex_data_depth_V(node); 4656 if (box.min.v<min) { 4657 _synctex_data_set_height_V(node,n-box.min.v); 4658 } else if (box.max.v>max) { 4659 _synctex_data_set_depth_V(node,box.max.v-n); 4660 } 4661 return SYNCTEX_STATUS_OK; 4662 } 4663 # ifdef SYNCTEX_NOTHING 4664 # pragma mark - 4665 # pragma mark SPECIAL CHARACTERS 4666 # endif 4667 4668 4669 /* Here are the control characters that start each line of the synctex output file. 4670 * Their values define the meaning of the line. 4671 */ 4672 # define SYNCTEX_CHAR_BEGIN_SHEET '{' 4673 # define SYNCTEX_CHAR_END_SHEET '}' 4674 # define SYNCTEX_CHAR_BEGIN_FORM '<' 4675 # define SYNCTEX_CHAR_END_FORM '>' 4676 # define SYNCTEX_CHAR_BEGIN_VBOX '[' 4677 # define SYNCTEX_CHAR_END_VBOX ']' 4678 # define SYNCTEX_CHAR_BEGIN_HBOX '(' 4679 # define SYNCTEX_CHAR_END_HBOX ')' 4680 # define SYNCTEX_CHAR_ANCHOR '!' 4681 # define SYNCTEX_CHAR_VOID_VBOX 'v' 4682 # define SYNCTEX_CHAR_VOID_HBOX 'h' 4683 # define SYNCTEX_CHAR_KERN 'k' 4684 # define SYNCTEX_CHAR_GLUE 'g' 4685 # define SYNCTEX_CHAR_RULE 'r' 4686 # define SYNCTEX_CHAR_MATH '$' 4687 # define SYNCTEX_CHAR_FORM_REF 'f' 4688 # define SYNCTEX_CHAR_BOUNDARY 'x' 4689 # define SYNCTEX_CHAR_CHARACTER 'c' 4690 # define SYNCTEX_CHAR_COMMENT '%' 4691 4692 # ifdef SYNCTEX_NOTHING 4693 # pragma mark - 4694 # pragma mark SCANNERS & PARSERS 4695 # endif 4696 4697 # define SYNCTEX_DECODE_FAILED(NODE,WHAT) \ 4698 (_synctex_data_decode_##WHAT(NODE)<SYNCTEX_STATUS_OK) 4699 # define SYNCTEX_DECODE_FAILED_V(NODE,WHAT) \ 4700 (_synctex_data_decode_##WHAT##_v(NODE)<SYNCTEX_STATUS_OK) 4701 4702 #define SYNCTEX_NS_NULL (synctex_ns_s){NULL,SYNCTEX_STATUS_NOT_OK} 4703 static synctex_ns_s _synctex_parse_new_sheet(synctex_scanner_p scanner) { 4704 synctex_node_p node; 4705 if ((node = _synctex_new_sheet(scanner))) { 4706 if ( 4707 SYNCTEX_DECODE_FAILED(node,page)) { 4708 _synctex_error("Bad sheet record."); 4709 } else if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4710 _synctex_error("Missing end of sheet."); 4711 } else { 4712 /* Now set the owner */ 4713 if (scanner->sheet) { 4714 synctex_node_p last_sheet = scanner->sheet; 4715 synctex_node_p next_sheet = NULL; 4716 while ((next_sheet = __synctex_tree_sibling(last_sheet))) { 4717 last_sheet = next_sheet; 4718 } 4719 /* sheets have no parent */ 4720 __synctex_tree_set_sibling(last_sheet,node); 4721 } else { 4722 scanner->sheet = node; 4723 } 4724 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4725 } 4726 _synctex_free_node(node); 4727 } 4728 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4729 } 4730 /** 4731 * - requirement: scanner != NULL 4732 */ 4733 static synctex_ns_s _synctex_parse_new_form(synctex_scanner_p scanner) { 4734 synctex_node_p node; 4735 if ((node = _synctex_new_form(scanner))) { 4736 if ( 4737 SYNCTEX_DECODE_FAILED(node,tag)) { 4738 _synctex_error("Bad sheet record."); 4739 } else if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4740 _synctex_error("Missing end of form."); 4741 } else { 4742 /* Now set the owner */ 4743 if (scanner->form) { 4744 synctex_node_p last_form = scanner->form; 4745 synctex_node_p next_form = NULL; 4746 while ((next_form = __synctex_tree_sibling(last_form))) { 4747 last_form = next_form; 4748 } 4749 __synctex_tree_set_sibling(last_form,node); 4750 } else { 4751 scanner->form = node; 4752 } 4753 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4754 } 4755 _synctex_free_node(node); 4756 } 4757 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4758 } 4759 # define SYNCTEX_SHOULD_DECODE_FAILED(NODE,WHAT) \ 4760 (_synctex_data_has_##WHAT(NODE) &&(_synctex_data_decode_##WHAT(NODE)<SYNCTEX_STATUS_OK)) 4761 # define SYNCTEX_SHOULD_DECODE_FAILED_V(NODE,WHAT) \ 4762 (_synctex_data_has_##WHAT(NODE) &&(_synctex_data_decode_##WHAT##_v(NODE)<SYNCTEX_STATUS_OK)) 4763 4764 static synctex_status_t _synctex_data_decode_tlchvwhd(synctex_node_p node) { 4765 return SYNCTEX_SHOULD_DECODE_FAILED(node,tag) 4766 || SYNCTEX_SHOULD_DECODE_FAILED(node,line) 4767 || SYNCTEX_SHOULD_DECODE_FAILED(node,column) 4768 || SYNCTEX_SHOULD_DECODE_FAILED(node,h) 4769 || SYNCTEX_SHOULD_DECODE_FAILED_V(node,v) 4770 || SYNCTEX_SHOULD_DECODE_FAILED(node,width) 4771 || SYNCTEX_SHOULD_DECODE_FAILED(node,height) 4772 || SYNCTEX_SHOULD_DECODE_FAILED(node,depth); 4773 } 4774 static synctex_ns_s _synctex_parse_new_vbox(synctex_scanner_p scanner) { 4775 synctex_node_p node; 4776 if ((node = _synctex_new_vbox(scanner))) { 4777 if (_synctex_data_decode_tlchvwhd(node)) { 4778 _synctex_error("Bad vbox record."); 4779 _synctex_next_line(scanner); 4780 out: 4781 _synctex_free_node(node); 4782 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4783 } 4784 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4785 _synctex_error("Missing end of vbox."); 4786 goto out; 4787 } 4788 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4789 } 4790 _synctex_next_line(scanner); 4791 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4792 } 4793 SYNCTEX_INLINE static synctex_node_p __synctex_node_make_friend_tlc(synctex_node_p node); 4794 static synctex_ns_s _synctex_parse_new_hbox(synctex_scanner_p scanner) { 4795 synctex_node_p node; 4796 if ((node = _synctex_new_hbox(scanner))) { 4797 if (_synctex_data_decode_tlchvwhd(node)) { 4798 _synctex_error("Bad hbox record."); 4799 _synctex_next_line(scanner); 4800 out: 4801 _synctex_free_node(node); 4802 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4803 } 4804 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4805 _synctex_error("Missing end of hbox."); 4806 goto out; 4807 } 4808 if (_synctex_setup_visible_hbox(node)<SYNCTEX_STATUS_OK) { 4809 _synctex_error("Unexpected error (_synctex_parse_new_hbox)."); 4810 goto out; 4811 } 4812 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4813 } 4814 _synctex_next_line(scanner); 4815 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4816 } 4817 static synctex_ns_s _synctex_parse_new_void_vbox(synctex_scanner_p scanner) { 4818 synctex_node_p node; 4819 if ((node = _synctex_new_void_vbox(scanner))) { 4820 if (_synctex_data_decode_tlchvwhd(node)) { 4821 _synctex_error("Bad void vbox record."); 4822 _synctex_next_line(scanner); 4823 out: 4824 _synctex_free_node(node); 4825 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4826 } 4827 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4828 _synctex_error("Missing end of container."); 4829 goto out; 4830 } 4831 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4832 } 4833 _synctex_next_line(scanner); 4834 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4835 } 4836 static synctex_ns_s _synctex_parse_new_void_hbox(synctex_scanner_p scanner) { 4837 synctex_node_p node; 4838 if ((node = _synctex_new_void_hbox(scanner))) { 4839 if (_synctex_data_decode_tlchvwhd(node)) { 4840 _synctex_error("Bad void hbox record."); 4841 _synctex_next_line(scanner); 4842 out: 4843 _synctex_free_node(node); 4844 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4845 } 4846 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4847 _synctex_error("Missing end of container."); 4848 goto out; 4849 } 4850 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4851 } 4852 _synctex_next_line(scanner); 4853 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4854 } 4855 static synctex_ns_s _synctex_parse_new_kern(synctex_scanner_p scanner) { 4856 synctex_node_p node; 4857 if ((node = _synctex_new_kern(scanner))) { 4858 if (_synctex_data_decode_tlchvwhd(node)) { 4859 _synctex_error("Bad kern record."); 4860 _synctex_next_line(scanner); 4861 out: 4862 _synctex_free_node(node); 4863 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4864 } 4865 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4866 _synctex_error("Missing end of container."); 4867 goto out; 4868 } 4869 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4870 } 4871 _synctex_next_line(scanner); 4872 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4873 } 4874 static synctex_ns_s _synctex_parse_new_glue(synctex_scanner_p scanner) { 4875 synctex_node_p node; 4876 if ((node = _synctex_new_glue(scanner))) { 4877 if (_synctex_data_decode_tlchvwhd(node)) { 4878 _synctex_error("Bad glue record."); 4879 _synctex_next_line(scanner); 4880 out: 4881 _synctex_free_node(node); 4882 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4883 } 4884 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4885 _synctex_error("Missing end of container."); 4886 goto out; 4887 } 4888 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4889 } 4890 _synctex_next_line(scanner); 4891 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4892 } 4893 static synctex_ns_s _synctex_parse_new_rule(synctex_scanner_p scanner) { 4894 synctex_node_p node; 4895 if ((node = _synctex_new_rule(scanner))) { 4896 if (_synctex_data_decode_tlchvwhd(node)) { 4897 _synctex_error("Bad rule record."); 4898 _synctex_next_line(scanner); 4899 out: 4900 _synctex_free_node(node); 4901 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4902 } 4903 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4904 _synctex_error("Missing end of container."); 4905 goto out; 4906 } 4907 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4908 } 4909 _synctex_next_line(scanner); 4910 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4911 } 4912 static synctex_ns_s _synctex_parse_new_math(synctex_scanner_p scanner) { 4913 synctex_node_p node; 4914 if ((node = _synctex_new_math(scanner))) { 4915 if (_synctex_data_decode_tlchvwhd(node)) { 4916 _synctex_error("Bad math record."); 4917 _synctex_next_line(scanner); 4918 out: 4919 _synctex_free_node(node); 4920 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4921 } 4922 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4923 _synctex_error("Missing end of container."); 4924 goto out; 4925 } 4926 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4927 } 4928 _synctex_next_line(scanner); 4929 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4930 } 4931 static synctex_ns_s _synctex_parse_new_boundary(synctex_scanner_p scanner) { 4932 synctex_node_p node; 4933 if ((node = _synctex_new_boundary(scanner))) { 4934 if (_synctex_data_decode_tlchvwhd(node)) { 4935 _synctex_error("Bad boundary record."); 4936 _synctex_next_line(scanner); 4937 out: 4938 _synctex_free_node(node); 4939 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4940 } 4941 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4942 _synctex_error("Missing end of container."); 4943 goto out; 4944 } 4945 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4946 } 4947 _synctex_next_line(scanner); 4948 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4949 } 4950 SYNCTEX_INLINE static synctex_ns_s _synctex_parse_new_ref(synctex_scanner_p scanner) { 4951 synctex_node_p node; 4952 if ((node = _synctex_new_ref(scanner))) { 4953 if (SYNCTEX_DECODE_FAILED(node,tag) 4954 || SYNCTEX_DECODE_FAILED(node,h) 4955 || SYNCTEX_DECODE_FAILED_V(node,v)) { 4956 _synctex_error("Bad form ref record."); 4957 _synctex_next_line(scanner); 4958 out: 4959 _synctex_free_node(node); 4960 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4961 } 4962 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 4963 _synctex_error("Missing end of container."); 4964 goto out; 4965 } 4966 return (synctex_ns_s){node,SYNCTEX_STATUS_OK}; 4967 } 4968 _synctex_next_line(scanner); 4969 return (synctex_ns_s){NULL,SYNCTEX_STATUS_ERROR}; 4970 } 4971 # undef SYNCTEX_DECODE_FAILED 4972 # undef SYNCTEX_DECODE_FAILED_V 4973 4974 SYNCTEX_INLINE static synctex_point_s _synctex_data_point(synctex_node_p node); 4975 SYNCTEX_INLINE static synctex_point_s _synctex_data_point_V(synctex_node_p node); 4976 SYNCTEX_INLINE static synctex_point_s _synctex_data_set_point(synctex_node_p node, synctex_point_s point); 4977 SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node); 4978 SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node); 4979 SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node); 4980 4981 SYNCTEX_INLINE static synctex_node_p _synctex_input_register_line(synctex_node_p input,synctex_node_p node) { 4982 if (node && _synctex_data_tag(input) != _synctex_data_tag(node)) { 4983 input = synctex_scanner_input_with_tag(node->class_->scanner,_synctex_data_tag(node)); 4984 } 4985 if (_synctex_data_line(node)>_synctex_data_line(input)) { 4986 _synctex_data_set_line(input,_synctex_data_line(node)); 4987 } 4988 return input; 4989 } 4990 /** 4991 * Free node and its siblings and return its detached child. 4992 */ 4993 SYNCTEX_INLINE static synctex_node_p _synctex_handle_pop_child(synctex_node_p handle) { 4994 synctex_node_p child = _synctex_tree_reset_child(handle); 4995 synctex_node_free(handle); 4996 return child; 4997 } 4998 /** 4999 * Set the tlc of all the x nodes that are targets of 5000 * x_handle and its sibling. 5001 * Reset the target of x_handle and deletes its siblings. 5002 * child is a node that has just been parsed and is not a boundary node. 5003 */ 5004 SYNCTEX_INLINE static void _synctex_handle_set_tlc(synctex_node_p x_handle, synctex_node_p child, synctex_bool_t make_friend) { 5005 if (x_handle) { 5006 synctex_node_p sibling = x_handle; 5007 if (child) { 5008 synctex_node_p target; 5009 while ((target = synctex_node_target(sibling))) { 5010 _synctex_data_set_tlc(target,child); 5011 if (make_friend) { 5012 _synctex_node_make_friend_tlc(target); 5013 } 5014 if ((sibling = __synctex_tree_sibling(sibling))) { 5015 continue; 5016 } else { 5017 break; 5018 } 5019 } 5020 } 5021 _synctex_tree_reset_target(x_handle); 5022 sibling = __synctex_tree_reset_sibling(x_handle); 5023 synctex_node_free(sibling); 5024 } 5025 } 5026 /** 5027 * When we have parsed a box, we must register 5028 * all the contained heading boundary nodes 5029 * that have not yet been registered. 5030 * Those handles will be deleted when popping. 5031 */ 5032 SYNCTEX_INLINE static void _synctex_handle_make_friend_tlc(synctex_node_p node) { 5033 while (node) { 5034 synctex_node_p target = _synctex_tree_reset_target(node); 5035 _synctex_node_make_friend_tlc(target); 5036 node = __synctex_tree_sibling(node); 5037 } 5038 } 5039 /** 5040 * Scan sheets, forms and input records. 5041 * - parameter scanner: owning scanner 5042 * - returns: status 5043 */ 5044 static synctex_status_t __synctex_parse_sfi(synctex_scanner_p scanner) { 5045 synctex_status_t status = SYNCTEX_STATUS_OK; 5046 synctex_zs_s zs = {0,0}; 5047 synctex_ns_s input = SYNCTEX_NS_NULL; 5048 synctex_node_p sheet = NULL; 5049 synctex_node_p form = NULL; 5050 synctex_node_p parent = NULL; 5051 synctex_node_p child = NULL; 5052 /* 5053 * Experimentations lead to the forthcoming conclusion: 5054 * Sometimes, the first nodes of a box have the wrong line number. 5055 * These are only boundary (x) nodes. 5056 * We observed that boundary nodes do have the proper line number 5057 * if they follow a node with a different type. 5058 * We keep track of these leading x nodes in a handle tree. 5059 */ 5060 synctex_node_p x_handle = NULL; 5061 # define SYNCTEX_RETURN(STATUS) \ 5062 synctex_node_free(x_handle);\ 5063 return STATUS 5064 synctex_node_p last_k = NULL; 5065 synctex_node_p last_g = NULL; 5066 synctex_ns_s ns = SYNCTEX_NS_NULL; 5067 int form_depth = 0; 5068 int ignored_form_depth = 0; 5069 synctex_bool_t try_input = synctex_YES; 5070 if (!(x_handle = _synctex_new_handle(scanner))) { 5071 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5072 } 5073 # ifdef SYNCTEX_NOTHING 5074 # pragma mark MAIN LOOP 5075 # endif 5076 main_loop: 5077 status = SYNCTEX_STATUS_OK; 5078 sheet = form = parent = child = NULL; 5079 # define SYNCTEX_START_SCAN(WHAT)\ 5080 (*SYNCTEX_CUR == SYNCTEX_CHAR_##WHAT) 5081 if (SYNCTEX_CUR<SYNCTEX_END) { 5082 if (SYNCTEX_START_SCAN(BEGIN_FORM)) { 5083 # ifdef SYNCTEX_NOTHING 5084 # pragma mark + SCAN FORM 5085 # endif 5086 scan_form: 5087 ns = _synctex_parse_new_form(scanner); 5088 if (ns.status == SYNCTEX_STATUS_OK) { 5089 ++form_depth; 5090 if (_synctex_tree_parent(form)) { 5091 /* This form is already being parsed */ 5092 ++ignored_form_depth; 5093 goto ignore_loop; 5094 } 5095 _synctex_tree_set_parent(ns.node,form); 5096 form = ns.node; 5097 parent = form; 5098 child = NULL; 5099 last_k = last_g = NULL; 5100 goto content_loop; 5101 } 5102 if (form || sheet) { 5103 last_k = last_g = NULL; 5104 goto content_loop; 5105 } 5106 try_input = synctex_YES; 5107 goto main_loop; 5108 } else if (SYNCTEX_START_SCAN(BEGIN_SHEET)) { 5109 # ifdef SYNCTEX_NOTHING 5110 # pragma mark + SCAN SHEET 5111 # endif 5112 try_input = synctex_YES; 5113 ns = _synctex_parse_new_sheet(scanner); 5114 if (ns.status == SYNCTEX_STATUS_OK) { 5115 sheet = ns.node; 5116 parent = sheet; 5117 last_k = last_g = NULL; 5118 goto content_loop; 5119 } 5120 goto main_loop; 5121 } else if (SYNCTEX_START_SCAN(ANCHOR)) { 5122 # ifdef SYNCTEX_NOTHING 5123 # pragma mark + SCAN ANCHOR 5124 # endif 5125 scan_anchor: 5126 ++SYNCTEX_CUR; 5127 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 5128 _synctex_error("Missing anchor."); 5129 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5130 } 5131 if (form || sheet) { 5132 last_k = last_g = NULL; 5133 goto content_loop; 5134 } 5135 try_input = synctex_YES; 5136 goto main_loop; 5137 } else if (SYNCTEX_START_SCAN(ANCHOR)) { 5138 # ifdef SYNCTEX_NOTHING 5139 # pragma mark + SCAN COMMENT 5140 # endif 5141 ++SYNCTEX_CUR; 5142 _synctex_next_line(scanner); 5143 try_input = synctex_YES; 5144 goto main_loop; 5145 } else if (try_input) { 5146 # ifdef SYNCTEX_NOTHING 5147 # pragma mark + SCAN INPUT 5148 # endif 5149 try_input = synctex_NO; 5150 do { 5151 input = __synctex_parse_new_input(scanner); 5152 } while (input.status == SYNCTEX_STATUS_OK); 5153 goto main_loop; 5154 } 5155 status = _synctex_match_string(scanner,"Postamble:"); 5156 if (status==SYNCTEX_STATUS_OK) { 5157 scanner->flags.postamble = 1; 5158 SYNCTEX_RETURN(status); 5159 } 5160 status = _synctex_next_line(scanner); 5161 if (status<SYNCTEX_STATUS_OK) { 5162 SYNCTEX_RETURN(status); 5163 } 5164 } 5165 /* At least 1 more character */ 5166 zs = _synctex_buffer_get_available_size(scanner,1); 5167 if (zs.size == 0){ 5168 _synctex_error("Incomplete synctex file, postamble missing."); 5169 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5170 } 5171 goto main_loop; 5172 /* Unreachable. */ 5173 # ifdef SYNCTEX_NOTHING 5174 # pragma mark IGNORE LOOP 5175 # endif 5176 ignore_loop: 5177 ns = SYNCTEX_NS_NULL; 5178 if (SYNCTEX_CUR<SYNCTEX_END) { 5179 if (SYNCTEX_START_SCAN(BEGIN_FORM)) { 5180 ++ignored_form_depth; 5181 } else if (SYNCTEX_START_SCAN(END_FORM)) { 5182 --ignored_form_depth; 5183 } 5184 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 5185 _synctex_error("Incomplete container."); 5186 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5187 } 5188 } else { 5189 zs = _synctex_buffer_get_available_size(scanner,1); 5190 if (zs.size == 0){ 5191 _synctex_error("Incomplete synctex file, postamble missing."); 5192 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5193 } 5194 } 5195 if (ignored_form_depth) { 5196 goto ignore_loop; 5197 } else { 5198 last_k = last_g = NULL; 5199 goto content_loop; 5200 } 5201 5202 # ifdef SYNCTEX_NOTHING 5203 # pragma mark CONTENT LOOP 5204 # endif 5205 content_loop: 5206 /* Either in a form, a sheet or a box. 5207 * - in a sheet, "{" is not possible, only boxes and "}" at top level. 5208 * - in a form, "{" is not possible, only boxes, "<" and ">" at top level. 5209 * - in a box, the unique possibility is '<', '[', '(' or ">". 5210 * We still keep the '(' for a sheet, because that dos not cost too much. 5211 * We must also consider void boxes as children. 5212 */ 5213 /* forms are everywhere */ 5214 ns = SYNCTEX_NS_NULL; 5215 #if SYNCTEX_VERBOSE 5216 synctex_scanner_set_display_switcher(scanner,-1); 5217 printf("NEW CONTENT LOOP\n"); 5218 #if SYNCTEX_DEBUG>500 5219 synctex_node_display(sheet); 5220 #endif 5221 #endif 5222 if (SYNCTEX_CUR<SYNCTEX_END) { 5223 if (SYNCTEX_START_SCAN(BEGIN_FORM)) { 5224 goto scan_form; 5225 } else if (SYNCTEX_START_SCAN(BEGIN_VBOX)) { 5226 # ifdef SYNCTEX_NOTHING 5227 # pragma mark + SCAN VBOX 5228 # endif 5229 ns = _synctex_parse_new_vbox(scanner); 5230 if (ns.status == SYNCTEX_STATUS_OK) { 5231 x_handle = _synctex_new_handle_with_child(x_handle); 5232 if (child) { 5233 _synctex_node_set_sibling(child,ns.node); 5234 } else { 5235 _synctex_node_set_child(parent,ns.node); 5236 } 5237 parent = ns.node; 5238 child = _synctex_tree_last(parent); 5239 # if SYNCTEX_VERBOSE 5240 synctex_node_log(parent); 5241 # endif 5242 input.node = _synctex_input_register_line(input.node,parent); 5243 last_k = last_g = NULL; 5244 goto content_loop; 5245 } 5246 } else if (SYNCTEX_START_SCAN(END_VBOX)) { 5247 if (synctex_node_type(parent) == synctex_node_type_vbox) { 5248 # ifdef SYNCTEX_NOTHING 5249 # pragma mark + SCAN XOBV 5250 # endif 5251 ++SYNCTEX_CUR; 5252 if (NULL == _synctex_tree_child(parent) && !form) { 5253 /* only void v boxes are friends */ 5254 _synctex_node_make_friend_tlc(parent); 5255 } 5256 child = parent; 5257 parent = _synctex_tree_parent(child); 5258 if (!form) { 5259 _synctex_handle_make_friend_tlc(x_handle); 5260 } 5261 x_handle = _synctex_handle_pop_child(x_handle); 5262 _synctex_handle_set_tlc(x_handle,child,!form); 5263 # if SYNCTEX_VERBOSE 5264 synctex_node_log(child); 5265 # endif 5266 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 5267 _synctex_error("Incomplete container."); 5268 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5269 } 5270 last_k = last_g = NULL; 5271 goto content_loop; 5272 } 5273 } else if (SYNCTEX_START_SCAN(BEGIN_HBOX)) { 5274 # ifdef SYNCTEX_NOTHING 5275 # pragma mark + SCAN HBOX 5276 # endif 5277 # if defined(SYNCTEX_USE_CHARINDEX) 5278 synctex_charindex_t char_index = (synctex_charindex_t)(scanner->reader->charindex_offset+SYNCTEX_CUR-SYNCTEX_START); 5279 synctex_lineindex_t line_index = scanner->reader->line_number; 5280 # endif 5281 ns = _synctex_parse_new_hbox(scanner); 5282 if (ns.status == SYNCTEX_STATUS_OK) { 5283 x_handle = _synctex_new_handle_with_child(x_handle); 5284 if (child) { 5285 _synctex_node_set_sibling(child,ns.node); 5286 } else { 5287 _synctex_node_set_child(parent,ns.node); 5288 } 5289 parent = ns.node; 5290 /* add a box boundary node at the start */ 5291 if ((child = _synctex_new_box_bdry(scanner))) { 5292 # if defined(SYNCTEX_USE_CHARINDEX) 5293 child->line_index=line_index; 5294 child->char_index=char_index; 5295 # endif 5296 _synctex_node_set_child(parent,child); 5297 _synctex_data_set_tlchv(child,parent); 5298 if (!form) { 5299 __synctex_node_make_friend_tlc(child); 5300 } 5301 } else { 5302 _synctex_error("Can't create box bdry record."); 5303 } 5304 # if SYNCTEX_VERBOSE 5305 synctex_node_log(parent); 5306 # endif 5307 input.node = _synctex_input_register_line(input.node,parent); 5308 last_k = last_g = NULL; 5309 goto content_loop; 5310 } 5311 } else if (SYNCTEX_START_SCAN(END_HBOX)) { 5312 if (synctex_node_type(parent) == synctex_node_type_hbox) { 5313 # ifdef SYNCTEX_NOTHING 5314 # pragma mark + SCAN XOBH 5315 # endif 5316 ++SYNCTEX_CUR; 5317 /* setting the next horizontal box at the end ensures 5318 * that a child is recorded before any of its ancestors. 5319 */ 5320 if (form == NULL /* && sheet != NULL*/ ) { 5321 _synctex_tree_set_next_hbox(parent,_synctex_tree_next_hbox(sheet)); 5322 _synctex_tree_set_next_hbox(sheet,parent); 5323 } 5324 { 5325 /* Update the mean line number */ 5326 synctex_node_p node = _synctex_tree_child(parent); 5327 synctex_node_p sibling = NULL; 5328 /* Ignore the first node (a box_bdry) */ 5329 if (node && (sibling = __synctex_tree_sibling(node))) { 5330 unsigned int node_weight = 0; 5331 unsigned int cumulated_line_numbers = 0; 5332 _synctex_data_set_line(node, _synctex_data_line(sibling)); 5333 node = sibling; 5334 do { 5335 if (synctex_node_type(node)==synctex_node_type_hbox) { 5336 if (_synctex_data_weight(node)) { 5337 node_weight += _synctex_data_weight(node); 5338 cumulated_line_numbers += _synctex_data_mean_line(node)*_synctex_data_weight(node); 5339 } else { 5340 ++node_weight; 5341 cumulated_line_numbers += _synctex_data_mean_line(node); 5342 } 5343 } else { 5344 ++node_weight; 5345 cumulated_line_numbers += synctex_node_line(node); 5346 } 5347 } while ((node = __synctex_tree_sibling(node))); 5348 _synctex_data_set_mean_line(parent,(cumulated_line_numbers + node_weight/2)/node_weight); 5349 _synctex_data_set_weight(parent,node_weight); 5350 } else { 5351 _synctex_data_set_mean_line(parent,_synctex_data_line(parent)); 5352 _synctex_data_set_weight(parent,1); 5353 } 5354 if ((sibling = _synctex_new_box_bdry(scanner))) { 5355 # if defined(SYNCTEX_USE_CHARINDEX) 5356 sibling->line_index=child->line_index; 5357 sibling->char_index=child->char_index; 5358 # endif 5359 _synctex_node_set_sibling(child,sibling); 5360 { 5361 synctex_node_p N = child; 5362 while (synctex_node_type(N) == synctex_node_type_ref) { 5363 N = _synctex_tree_arg_sibling(N); 5364 } 5365 _synctex_data_set_tlc(sibling,N); 5366 } 5367 _synctex_data_set_h(sibling,_synctex_data_h_V(parent)+_synctex_data_width_V(parent)); 5368 _synctex_data_set_v(sibling,_synctex_data_v_V(parent)); 5369 child = sibling; 5370 } else { 5371 _synctex_error("Can't create box bdry record."); 5372 } 5373 sibling = _synctex_tree_child(parent); 5374 _synctex_data_set_point(sibling,_synctex_data_point_V(parent)); 5375 if (last_k && last_g && (child = synctex_node_child(parent))) { 5376 /* Find the node preceding last_k */ 5377 synctex_node_p next; 5378 while ((next = __synctex_tree_sibling(child))) { 5379 if (next == last_k) { 5380 _synctex_data_set_tlc(last_k,child); 5381 _synctex_data_set_tlc(last_g,child); 5382 break; 5383 } 5384 child = next; 5385 } 5386 } 5387 child = parent; 5388 parent = _synctex_tree_parent(child); 5389 if (!form) { 5390 _synctex_handle_make_friend_tlc(x_handle); 5391 } 5392 x_handle = _synctex_handle_pop_child(x_handle); 5393 _synctex_handle_set_tlc(x_handle,child,!form); 5394 _synctex_make_hbox_contain_box(parent, _synctex_data_box_V(child)); 5395 # if SYNCTEX_VERBOSE 5396 synctex_node_log(child); 5397 # endif 5398 } 5399 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 5400 _synctex_error("Incomplete container."); 5401 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5402 } 5403 last_k = last_g = NULL; 5404 goto content_loop; 5405 } 5406 } else if (SYNCTEX_START_SCAN(VOID_VBOX)) { 5407 # ifdef SYNCTEX_NOTHING 5408 # pragma mark + SCAN VOID VBOX 5409 # endif 5410 ns = _synctex_parse_new_void_vbox(scanner); 5411 if (ns.status == SYNCTEX_STATUS_OK) { 5412 if (child) { 5413 _synctex_node_set_sibling(child,ns.node); 5414 } else { 5415 _synctex_node_set_child(parent,ns.node); 5416 } 5417 child = ns.node; 5418 _synctex_handle_set_tlc(x_handle, child,!form); 5419 # if SYNCTEX_VERBOSE 5420 synctex_node_log(child); 5421 # endif 5422 input.node = _synctex_input_register_line(input.node,child); 5423 last_k = last_g = NULL; 5424 goto content_loop; 5425 } 5426 } else if (SYNCTEX_START_SCAN(VOID_HBOX)) { 5427 # ifdef SYNCTEX_NOTHING 5428 # pragma mark + SCAN VOID HBOX 5429 # endif 5430 ns = _synctex_parse_new_void_hbox(scanner); 5431 if (ns.status == SYNCTEX_STATUS_OK) { 5432 if (_synctex_data_width(ns.node)<0) { 5433 printf("Negative width\n"); 5434 } 5435 if (child) { 5436 _synctex_node_set_sibling(child,ns.node); 5437 } else { 5438 _synctex_node_set_child(parent,ns.node); 5439 } 5440 child = ns.node; 5441 _synctex_handle_set_tlc(x_handle, child,!form); 5442 _synctex_make_hbox_contain_box(parent,_synctex_data_box(child)); 5443 # if SYNCTEX_VERBOSE 5444 synctex_node_log(child); 5445 # endif 5446 input.node = _synctex_input_register_line(input.node,child); 5447 last_k = last_g = NULL; 5448 goto content_loop; 5449 } 5450 } else if (SYNCTEX_START_SCAN(KERN)) { 5451 # ifdef SYNCTEX_NOTHING 5452 # pragma mark + SCAN KERN 5453 # endif 5454 ns = _synctex_parse_new_kern(scanner); 5455 continue_scan: 5456 if (ns.status == SYNCTEX_STATUS_OK) { 5457 if (child) { 5458 _synctex_node_set_sibling(child,ns.node); 5459 } else { 5460 _synctex_node_set_child(parent,ns.node); 5461 } 5462 child = ns.node; 5463 if (!form) { 5464 __synctex_node_make_friend_tlc(child); 5465 } 5466 _synctex_handle_set_tlc(x_handle, child,!form); 5467 _synctex_make_hbox_contain_box(parent,_synctex_data_xob(child)); 5468 # if SYNCTEX_VERBOSE 5469 synctex_node_log(child); 5470 # endif 5471 input.node = _synctex_input_register_line(input.node,child); 5472 last_k = child; 5473 last_g = NULL; 5474 goto content_loop; 5475 } 5476 } else if (SYNCTEX_START_SCAN(GLUE)) { 5477 # ifdef SYNCTEX_NOTHING 5478 # pragma mark + SCAN GLUE 5479 # endif 5480 ns = _synctex_parse_new_glue(scanner); 5481 if (ns.status == SYNCTEX_STATUS_OK) { 5482 if (child) { 5483 _synctex_node_set_sibling(child,ns.node); 5484 } else { 5485 _synctex_node_set_child(parent,ns.node); 5486 } 5487 child = ns.node; 5488 if (!form) { 5489 __synctex_node_make_friend_tlc(child); 5490 } 5491 _synctex_handle_set_tlc(x_handle, child,!form); 5492 _synctex_make_hbox_contain_point(parent,_synctex_data_point(child)); 5493 # if SYNCTEX_VERBOSE 5494 synctex_node_log(child); 5495 # endif 5496 input.node = _synctex_input_register_line(input.node,child); 5497 if (last_k) { 5498 last_g = child; 5499 } else { 5500 last_k = last_g = NULL; 5501 } 5502 goto content_loop; 5503 } 5504 } else if (SYNCTEX_START_SCAN(RULE)) { 5505 # ifdef SYNCTEX_NOTHING 5506 # pragma mark + SCAN RULE 5507 # endif 5508 ns = _synctex_parse_new_rule(scanner); 5509 if (ns.status == SYNCTEX_STATUS_OK) { 5510 if (child) { 5511 _synctex_node_set_sibling(child,ns.node); 5512 } else { 5513 _synctex_node_set_child(parent,ns.node); 5514 } 5515 child = ns.node; 5516 if (!form) { 5517 __synctex_node_make_friend_tlc(child); 5518 } 5519 _synctex_handle_set_tlc(x_handle, child,!form); 5520 /* Rules are sometimes far too big 5521 _synctex_make_hbox_contain_box(parent,_synctex_data_box(child)); 5522 */ 5523 # if SYNCTEX_VERBOSE 5524 synctex_node_log(child); 5525 # endif 5526 input.node = _synctex_input_register_line(input.node,child); 5527 last_k = last_g = NULL; 5528 goto content_loop; 5529 } 5530 } else if (SYNCTEX_START_SCAN(MATH)) { 5531 # ifdef SYNCTEX_NOTHING 5532 # pragma mark + SCAN MATH 5533 # endif 5534 ns = _synctex_parse_new_math(scanner); 5535 if (ns.status == SYNCTEX_STATUS_OK) { 5536 if (child) { 5537 _synctex_node_set_sibling(child,ns.node); 5538 } else { 5539 _synctex_node_set_child(parent,ns.node); 5540 } 5541 child = ns.node; 5542 if (!form) { 5543 __synctex_node_make_friend_tlc(child); 5544 } 5545 _synctex_handle_set_tlc(x_handle, child,!form); 5546 _synctex_make_hbox_contain_point(parent,_synctex_data_point(child)); 5547 # if SYNCTEX_VERBOSE 5548 synctex_node_log(child); 5549 # endif 5550 input.node = _synctex_input_register_line(input.node,child); 5551 last_k = last_g = NULL; 5552 goto content_loop; 5553 } 5554 } else if (SYNCTEX_START_SCAN(FORM_REF)) { 5555 # ifdef SYNCTEX_NOTHING 5556 # pragma mark + SCAN FORM REF 5557 # endif 5558 #if SYNCTEX_DEBUG>500 5559 synctex_node_display(parent); 5560 synctex_node_display(child); 5561 #endif 5562 ns = _synctex_parse_new_ref(scanner); 5563 if (ns.status == SYNCTEX_STATUS_OK) { 5564 if (child) { 5565 _synctex_node_set_sibling(child,ns.node); 5566 } else { 5567 _synctex_node_set_child(parent,ns.node); 5568 } 5569 child = ns.node; 5570 if (form) { 5571 if (scanner->ref_in_form) { 5572 synctex_tree_set_friend(child,scanner->ref_in_form); 5573 } 5574 scanner->ref_in_form = child; 5575 } else { 5576 if (scanner->ref_in_sheet) { 5577 synctex_tree_set_friend(child,scanner->ref_in_sheet); 5578 } 5579 scanner->ref_in_sheet = child; 5580 } 5581 # if SYNCTEX_VERBOSE 5582 synctex_node_log(child); 5583 # endif 5584 last_k = last_g = NULL; 5585 goto content_loop; 5586 } 5587 } else if (SYNCTEX_START_SCAN(BOUNDARY)) { 5588 # ifdef SYNCTEX_NOTHING 5589 # pragma mark + SCAN BOUNDARY 5590 # endif 5591 ns = _synctex_parse_new_boundary(scanner); 5592 if (ns.status == SYNCTEX_STATUS_OK) { 5593 if (child) { 5594 _synctex_node_set_sibling(child,ns.node); 5595 } else { 5596 _synctex_node_set_child(parent,ns.node); 5597 } 5598 if (synctex_node_type(child)==synctex_node_type_box_bdry 5599 || _synctex_tree_target(x_handle)) { 5600 child = _synctex_tree_reset_child(x_handle); 5601 child = _synctex_new_handle_with_child(child); 5602 __synctex_tree_set_sibling(child, x_handle); 5603 x_handle = child; 5604 _synctex_tree_set_target(x_handle,ns.node); 5605 } else if (!form) { 5606 __synctex_node_make_friend_tlc(ns.node); 5607 } 5608 child = ns.node; 5609 _synctex_make_hbox_contain_point(parent,_synctex_data_point(child)); 5610 # if SYNCTEX_VERBOSE 5611 synctex_node_log(child); 5612 # endif 5613 input.node = _synctex_input_register_line(input.node,child); 5614 last_k = last_g = NULL; 5615 goto content_loop; 5616 } 5617 } else if (SYNCTEX_START_SCAN(CHARACTER)) { 5618 # ifdef SYNCTEX_NOTHING 5619 # pragma mark + SCAN CHARACTER 5620 # endif 5621 ++SYNCTEX_CUR; 5622 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 5623 _synctex_error("Missing end of container."); 5624 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5625 } 5626 last_k = last_g = NULL; 5627 goto content_loop; 5628 } else if (SYNCTEX_START_SCAN(ANCHOR)) { 5629 # ifdef SYNCTEX_NOTHING 5630 # pragma mark + SCAN ANCHOR 5631 # endif 5632 goto scan_anchor; 5633 } else if (SYNCTEX_START_SCAN(END_SHEET)) { 5634 if (sheet && parent == sheet) { 5635 # ifdef SYNCTEX_NOTHING 5636 # pragma mark + SCAN TEEHS 5637 # endif 5638 ++SYNCTEX_CUR; 5639 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 5640 _synctex_error("Missing anchor."); 5641 } 5642 parent = sheet = NULL; 5643 goto main_loop; 5644 } 5645 } else if (SYNCTEX_START_SCAN(END_FORM)) { 5646 if (parent == form && form_depth > 0) { 5647 # ifdef SYNCTEX_NOTHING 5648 # pragma mark + SCAN MROF 5649 # endif 5650 ++SYNCTEX_CUR; 5651 --form_depth; 5652 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK 5653 && (form_depth || sheet)) { 5654 _synctex_error("Missing end of container."); 5655 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5656 } 5657 if ((parent = _synctex_tree_parent(form))) { 5658 _synctex_tree_reset_parent(form); 5659 child = form; 5660 form = parent; 5661 goto content_loop; 5662 } else if (sheet) { 5663 form = NULL; 5664 parent = sheet; 5665 child = synctex_node_last_sibling(child); 5666 goto content_loop; 5667 } 5668 goto main_loop; 5669 } 5670 } 5671 _synctex_error("Ignored record <%.20s...>(line %i)\n",SYNCTEX_CUR, scanner->reader->line_number+1); 5672 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 5673 _synctex_error("Missing end of sheet/form."); 5674 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5675 } 5676 last_k = last_g = NULL; 5677 goto content_loop; 5678 } 5679 zs = _synctex_buffer_get_available_size(scanner,1); 5680 if (zs.size == 0){ 5681 _synctex_error("Incomplete synctex file, postamble missing."); 5682 SYNCTEX_RETURN(SYNCTEX_STATUS_ERROR); 5683 } 5684 last_k = last_g = NULL; 5685 goto content_loop; 5686 } 5687 #undef SYNCTEX_RETURN 5688 /** 5689 * Replace ref in its tree hierarchy by a single box 5690 * proxy to the contents of the associated form. 5691 * - argument ref: a ref node with no friend 5692 * - return the proxy created. 5693 * - note: Does nothing if ref is not owned. 5694 * - note: On return, ref will have no parent nor sibling. 5695 * The caller is responsible for releasing ref. 5696 * - note: this is where root proxies are created. 5697 * - note: the target of the root proxy is the content 5698 * of a form. 5699 */ 5700 SYNCTEX_INLINE static synctex_ns_s __synctex_replace_ref(synctex_node_p ref) { 5701 synctex_ns_s ns = {NULL,SYNCTEX_STATUS_OK}; 5702 synctex_node_p parent; 5703 if ((parent = _synctex_tree_parent(ref))) { 5704 synctex_node_p sibling = __synctex_tree_reset_sibling(ref); 5705 synctex_node_p arg_sibling = synctex_node_arg_sibling(ref); 5706 /* arg_sibling != NULL because the child of a box 5707 * is always a box boundary, not a ref. */ 5708 synctex_node_p target = synctex_form_content(ref->class_->scanner, _synctex_data_tag(ref)); 5709 /* The target is a single node (box) 5710 * with children and no siblings. */ 5711 if ((ns.node = __synctex_new_proxy_from_ref_to(ref, target))) { 5712 /* Insert this proxy instead of ref. */ 5713 _synctex_node_set_sibling(arg_sibling,ns.node); 5714 /* Then append the original sibling of ref. */ 5715 _synctex_node_set_sibling(ns.node,sibling); 5716 # if defined(SYNCTEX_USE_CHARINDEX) 5717 if (synctex_node_type(sibling) == synctex_node_type_box_bdry) { 5718 /* The sibling is the last box boundary 5719 * which may have a less accurate information */ 5720 sibling->char_index = arg_sibling->char_index; 5721 sibling->line_index = arg_sibling->line_index; 5722 } 5723 #endif 5724 #if SYNCTEX_DEBUG>500 5725 printf("! Ref replacement:\n"); 5726 synctex_node_log(ref); 5727 synctex_node_display(synctex_node_sibling(ref)); 5728 #endif 5729 } else /* simply remove ref */ { 5730 _synctex_tree_set_sibling(arg_sibling,sibling); 5731 } 5732 __synctex_tree_reset_parent(ref); 5733 } else { 5734 _synctex_error("! Missing parent in __synctex_replace_ref. " 5735 "Please report."); 5736 ns.status = SYNCTEX_STATUS_BAD_ARGUMENT; 5737 } 5738 return ns; 5739 } 5740 /** 5741 * - argument ref: is the starting point of a linked list 5742 * of refs. The link is made through the friend field. 5743 * - returns: the status and the list of all the proxies 5744 * created. The link is made through the friend field. 5745 * - note: All refs are freed 5746 */ 5747 SYNCTEX_INLINE static synctex_ns_s _synctex_post_process_ref(synctex_node_p ref) { 5748 synctex_ns_s ns = {NULL, SYNCTEX_STATUS_OK}; 5749 while (ref) { 5750 synctex_node_p next_ref = _synctex_tree_reset_friend(ref); 5751 synctex_ns_s sub_ns = __synctex_replace_ref(ref); 5752 if (sub_ns.status < ns.status) { 5753 ns.status = sub_ns.status; 5754 } else { 5755 /* Insert all the created proxies in the list 5756 * sub_ns.node is the last friend, 5757 */ 5758 synctex_tree_set_friend(sub_ns.node,ns.node); 5759 ns.node = sub_ns.node; 5760 } 5761 synctex_node_free(ref); 5762 ref = next_ref; 5763 } 5764 return ns; 5765 } 5766 typedef synctex_node_p (* synctex_processor_f)(synctex_node_p node); 5767 /** 5768 * Apply the processor f to the tree hierarchy rooted at proxy. 5769 * proxy has replaced a form ref, no children yet. 5770 * As a side effect all the hierarchy of nodes will be created. 5771 */ 5772 SYNCTEX_INLINE static synctex_status_t _synctex_post_process_proxy(synctex_node_p proxy, synctex_processor_f f) { 5773 while(proxy) { 5774 synctex_node_p next_proxy = _synctex_tree_friend(proxy); 5775 synctex_node_p halt = __synctex_tree_sibling(proxy); 5776 /* if proxy is the last sibling, halt is NULL. 5777 * Find what should be a next node, 5778 * without creating new nodes. */ 5779 if (!halt) { 5780 synctex_node_p parent = _synctex_tree_parent(proxy); 5781 halt = __synctex_tree_sibling(parent); 5782 while (!halt && parent) { 5783 parent = _synctex_tree_parent(parent); 5784 halt = __synctex_tree_sibling(parent); 5785 } 5786 } 5787 do { 5788 #if SYNCTEX_DEBUG>500 5789 printf("POST PROCESSING %s\n",_synctex_node_abstract(proxy)); 5790 { 5791 int i,j = 0; 5792 for (i=0;i<proxy->class_->scanner->number_of_lists;++i) { 5793 synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; 5794 do { 5795 if (N==proxy) { 5796 ++j; 5797 printf("%s",_synctex_node_abstract(N)); 5798 } 5799 } while ((N = _synctex_tree_friend(N))); 5800 } 5801 if (j) { 5802 printf("\nBeforehand %i match\n",j); 5803 } 5804 } 5805 #endif 5806 f(proxy); 5807 #if SYNCTEX_DEBUG>500 5808 { 5809 int i,j = 0; 5810 for (i=0;i<proxy->class_->scanner->number_of_lists;++i) { 5811 synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; 5812 do { 5813 if (N==proxy) { 5814 ++j; 5815 printf("%s",_synctex_node_abstract(N)); 5816 } 5817 } while ((N = _synctex_tree_friend(N))); 5818 } 5819 if (j) { 5820 printf("\n%i match\n",j); 5821 } 5822 } 5823 #endif 5824 /* Side effect: create the hierarchy on the fly */ 5825 proxy = synctex_node_next(proxy); /* Change is here */ 5826 #if SYNCTEX_DEBUG>500 5827 if (proxy) { 5828 int i,j = 0; 5829 for (i=0;i<proxy->class_->scanner->number_of_lists;++i) { 5830 synctex_node_p N = proxy->class_->scanner->lists_of_friends[i]; 5831 do { 5832 if (N==proxy) { 5833 ++j; 5834 printf("%s",_synctex_node_abstract(N)); 5835 } 5836 } while ((N = _synctex_tree_friend(N))); 5837 } 5838 if (j) { 5839 printf("\nnext %i match\n",j); 5840 } 5841 } 5842 #endif 5843 } while (proxy && proxy != halt); 5844 proxy = next_proxy; 5845 } 5846 return SYNCTEX_STATUS_OK; 5847 } 5848 /** 5849 * Replace all the form refs by root box proxies. 5850 * Create the node hierarchy and update the friends. 5851 * On entry, the refs are collected as a friend list 5852 * in either a form or a sheet 5853 * - parameter: the owning scanner 5854 */ 5855 SYNCTEX_INLINE static synctex_status_t _synctex_post_process(synctex_scanner_p scanner) { 5856 synctex_status_t status = SYNCTEX_STATUS_OK; 5857 synctex_ns_s ns = {NULL,SYNCTEX_STATUS_NOT_OK}; 5858 #if SYNCTEX_DEBUG>500 5859 printf("! entering _synctex_post_process.\n"); 5860 synctex_node_display(scanner->sheet); 5861 synctex_node_display(scanner->form); 5862 #endif 5863 /* replace form refs inside forms by box proxies */ 5864 ns = _synctex_post_process_ref(scanner->ref_in_form); 5865 scanner->ref_in_form = NULL;/* it was just released */ 5866 if (ns.status<status) { 5867 status = ns.status; 5868 } 5869 #if SYNCTEX_DEBUG>500 5870 printf("! ref replaced in form _synctex_post_process.\n"); 5871 synctex_node_display(scanner->form); 5872 #endif 5873 /* Create all the form proxy nodes on the fly. 5874 * ns.node is the root of the list of 5875 * newly created proxies. 5876 * There might be a problem with cascading proxies. 5877 * In order to be properly managed, the data must 5878 * be organized in the right way. 5879 * The inserted form must be defined before 5880 * the inserting one. *TeX will take care of that. */ 5881 ns.status = _synctex_post_process_proxy(ns.node,&_synctex_tree_reset_friend); 5882 if (ns.status<status) { 5883 status = ns.status; 5884 } 5885 /* replace form refs inside sheets by box proxies */ 5886 ns = _synctex_post_process_ref(scanner->ref_in_sheet); 5887 if (ns.status<status) { 5888 status = ns.status; 5889 } 5890 scanner->ref_in_sheet = NULL; 5891 #if SYNCTEX_DEBUG>500 5892 printf("! ref replaced in sheet _synctex_post_process.\n"); 5893 synctex_node_display(scanner->sheet); 5894 #endif 5895 #if 0 5896 { 5897 int i; 5898 for (i=0;i<scanner->number_of_lists;++i) { 5899 synctex_node_p P = ns.node; 5900 do { 5901 synctex_node_p N = scanner->lists_of_friends[i]; 5902 do { 5903 if (P == N) { 5904 printf("Already registered.\n"); 5905 synctex_node_display(N); 5906 break; 5907 } 5908 } while ((N = _synctex_tree_friend(N))); 5909 } while((P = _synctex_tree_friend(P))); 5910 } 5911 } 5912 #endif 5913 #if SYNCTEX_DEBUG>10000 5914 { 5915 int i; 5916 for (i=0;i<scanner->number_of_lists;++i) { 5917 synctex_node_p P = scanner->lists_of_friends[i]; 5918 int j = 0; 5919 while (P) { 5920 ++j; 5921 synctex_node_log(P); 5922 P = _synctex_tree_friend(P); 5923 } 5924 if (j) { 5925 printf("friends %i -> # %i\n",i,j); 5926 } 5927 } 5928 } 5929 #endif 5930 ns.status = _synctex_post_process_proxy(ns.node,&__synctex_proxy_make_friend_and_next_hbox); 5931 if (ns.status<status) { 5932 status = ns.status; 5933 } 5934 #if SYNCTEX_DEBUG>500 5935 printf("! exiting _synctex_post_process.\n"); 5936 synctex_node_display(scanner->sheet); 5937 synctex_node_display(scanner->form); 5938 printf("! display all.\n"); 5939 synctex_node_display(scanner->sheet); 5940 synctex_node_display(scanner->form); 5941 #endif 5942 return status; 5943 } 5944 /* Used when parsing the synctex file 5945 */ 5946 static synctex_status_t _synctex_scan_content(synctex_scanner_p scanner) { 5947 scanner->reader->lastv = -1; 5948 synctex_status_t status = 0; 5949 if (NULL == scanner) { 5950 return SYNCTEX_STATUS_BAD_ARGUMENT; 5951 } 5952 /* Find where this section starts */ 5953 content_not_found: 5954 status = _synctex_match_string(scanner,"Content:"); 5955 if (status<SYNCTEX_STATUS_EOF) { 5956 return status; 5957 } 5958 if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) { 5959 _synctex_error("Incomplete Content."); 5960 return SYNCTEX_STATUS_ERROR; 5961 } 5962 if (status == SYNCTEX_STATUS_NOT_OK) { 5963 goto content_not_found; 5964 } 5965 status = __synctex_parse_sfi(scanner); 5966 if (status == SYNCTEX_STATUS_OK) { 5967 status = _synctex_post_process(scanner); 5968 } 5969 return status; 5970 } 5971 synctex_scanner_p synctex_scanner_new() { 5972 synctex_scanner_p scanner =(synctex_scanner_p)_synctex_malloc(sizeof(synctex_scanner_s)); 5973 if (scanner) { 5974 if (!(scanner->reader = _synctex_malloc(sizeof(synctex_reader_s)))) { 5975 _synctex_free(scanner); 5976 return NULL; 5977 } 5978 # ifdef SYNCTEX_NOTHING 5979 # pragma mark - 5980 # endif 5981 # define DEFINE_synctex_scanner_class(NAME)\ 5982 scanner->class_[synctex_node_type_##NAME] = synctex_class_##NAME;\ 5983 (scanner->class_[synctex_node_type_##NAME]).scanner = scanner 5984 DEFINE_synctex_scanner_class(input); 5985 DEFINE_synctex_scanner_class(sheet); 5986 DEFINE_synctex_scanner_class(form); 5987 DEFINE_synctex_scanner_class(hbox); 5988 DEFINE_synctex_scanner_class(void_hbox); 5989 DEFINE_synctex_scanner_class(vbox); 5990 DEFINE_synctex_scanner_class(void_vbox); 5991 DEFINE_synctex_scanner_class(kern); 5992 DEFINE_synctex_scanner_class(glue); 5993 DEFINE_synctex_scanner_class(rule); 5994 DEFINE_synctex_scanner_class(math); 5995 DEFINE_synctex_scanner_class(boundary); 5996 DEFINE_synctex_scanner_class(box_bdry); 5997 DEFINE_synctex_scanner_class(ref); 5998 DEFINE_synctex_scanner_class(proxy_hbox); 5999 DEFINE_synctex_scanner_class(proxy_vbox); 6000 DEFINE_synctex_scanner_class(proxy); 6001 DEFINE_synctex_scanner_class(proxy_last); 6002 DEFINE_synctex_scanner_class(handle); 6003 /* set up the lists of friends */ 6004 scanner->number_of_lists = 1024; 6005 scanner->lists_of_friends = (synctex_node_r)_synctex_malloc(scanner->number_of_lists*sizeof(synctex_node_p)); 6006 if (NULL == scanner->lists_of_friends) { 6007 synctex_scanner_free(scanner); 6008 _synctex_error("malloc:2"); 6009 return NULL; 6010 } 6011 scanner->display_switcher = 100; 6012 scanner->display_prompt = (char *)_synctex_display_prompt+strlen(_synctex_display_prompt)-1; 6013 } 6014 return scanner; 6015 } 6016 /* Where the synctex scanner is created. */ 6017 synctex_scanner_p synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse) { 6018 synctex_scanner_p scanner = synctex_scanner_new(); 6019 if (NULL == scanner) { 6020 _synctex_error("malloc problem"); 6021 return NULL; 6022 } 6023 if ((scanner->reader = synctex_reader_init_with_output_file(scanner->reader, output, build_directory))) { 6024 return parse? synctex_scanner_parse(scanner):scanner; 6025 } 6026 _synctex_error("No file?"); 6027 return NULL; 6028 } 6029 6030 /* The scanner destructor 6031 */ 6032 int synctex_scanner_free(synctex_scanner_p scanner) { 6033 int node_count = 0; 6034 if (scanner) { 6035 if (SYNCTEX_FILE) { 6036 gzclose(SYNCTEX_FILE); 6037 SYNCTEX_FILE = NULL; 6038 } 6039 synctex_node_free(scanner->sheet); 6040 synctex_node_free(scanner->form); 6041 synctex_node_free(scanner->input); 6042 synctex_reader_free(scanner->reader); 6043 SYNCTEX_SCANNER_FREE_HANDLE(scanner); 6044 synctex_iterator_free(scanner->iterator); 6045 free(scanner->output_fmt); 6046 free(scanner->lists_of_friends); 6047 #if SYNCTEX_USE_NODE_COUNT>0 6048 node_count = scanner->node_count; 6049 #endif 6050 free(scanner); 6051 } 6052 return node_count; 6053 } 6054 6055 /* Where the synctex scanner parses the contents of the file. */ 6056 synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner) { 6057 synctex_status_t status = 0; 6058 if (!scanner || scanner->flags.has_parsed) { 6059 return scanner; 6060 } 6061 scanner->flags.has_parsed=1; 6062 scanner->pre_magnification = 1000; 6063 scanner->pre_unit = 8192; 6064 scanner->pre_x_offset = scanner->pre_y_offset = 578; 6065 /* initialize the offset with a fake unprobable value, 6066 * If there is a post scriptum section, this value will be overridden by the real life value */ 6067 scanner->x_offset = scanner->y_offset = 6.027e23f; 6068 scanner->reader->line_number = 1; 6069 6070 SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE+1); /* one more character for null termination */ 6071 if (NULL == SYNCTEX_START) { 6072 _synctex_error("! malloc error in synctex_scanner_parse."); 6073 bailey: 6074 #ifdef SYNCTEX_DEBUG 6075 return scanner; 6076 #else 6077 synctex_scanner_free(scanner); 6078 return NULL; 6079 #endif 6080 } 6081 synctex_scanner_set_display_switcher(scanner, 1000); 6082 SYNCTEX_END = SYNCTEX_START+SYNCTEX_BUFFER_SIZE; 6083 /* SYNCTEX_END always points to a null terminating character. 6084 * Maybe there is another null terminating character between SYNCTEX_CUR and SYNCTEX_END-1. 6085 * At least, we are sure that SYNCTEX_CUR points to a string covering a valid part of the memory. */ 6086 *SYNCTEX_END = '\0'; 6087 SYNCTEX_CUR = SYNCTEX_END; 6088 # if defined(SYNCTEX_USE_CHARINDEX) 6089 scanner->reader->charindex_offset = -SYNCTEX_BUFFER_SIZE; 6090 # endif 6091 status = _synctex_scan_preamble(scanner); 6092 if (status<SYNCTEX_STATUS_OK) { 6093 _synctex_error("Bad preamble\n"); 6094 goto bailey; 6095 } 6096 status = _synctex_scan_content(scanner); 6097 if (status<SYNCTEX_STATUS_OK) { 6098 _synctex_error("Bad content\n"); 6099 goto bailey; 6100 } 6101 status = _synctex_scan_postamble(scanner); 6102 if (status<SYNCTEX_STATUS_OK) { 6103 _synctex_error("Bad postamble. Ignored\n"); 6104 } 6105 #if SYNCTEX_DEBUG>500 6106 synctex_scanner_set_display_switcher(scanner, 100); 6107 synctex_node_display(scanner->sheet); 6108 synctex_node_display(scanner->form); 6109 #endif 6110 synctex_scanner_set_display_switcher(scanner, 1000); 6111 /* Everything is finished, free the buffer, close the file */ 6112 free((void *)SYNCTEX_START); 6113 SYNCTEX_START = SYNCTEX_CUR = SYNCTEX_END = NULL; 6114 gzclose(SYNCTEX_FILE); 6115 SYNCTEX_FILE = NULL; 6116 /* Final tuning: set the default values for various parameters */ 6117 /* 1 pre_unit = (scanner->pre_unit)/65536 pt = (scanner->pre_unit)/65781.76 bp 6118 * 1 pt = 65536 sp */ 6119 if (scanner->pre_unit<=0) { 6120 scanner->pre_unit = 8192; 6121 } 6122 if (scanner->pre_magnification<=0) { 6123 scanner->pre_magnification = 1000; 6124 } 6125 if (scanner->unit <= 0) { 6126 /* no post magnification */ 6127 scanner->unit = scanner->pre_unit / 65781.76;/* 65781.76 or 65536.0*/ 6128 } else { 6129 /* post magnification */ 6130 scanner->unit *= scanner->pre_unit / 65781.76; 6131 } 6132 scanner->unit *= scanner->pre_magnification / 1000.0; 6133 if (scanner->x_offset > 6e23) { 6134 /* no post offset */ 6135 scanner->x_offset = scanner->pre_x_offset * (scanner->pre_unit / 65781.76); 6136 scanner->y_offset = scanner->pre_y_offset * (scanner->pre_unit / 65781.76); 6137 } else { 6138 /* post offset */ 6139 scanner->x_offset /= 65781.76f; 6140 scanner->y_offset /= 65781.76f; 6141 } 6142 return scanner; 6143 #undef SYNCTEX_FILE 6144 } 6145 6146 /* Scanner accessors. 6147 */ 6148 int synctex_scanner_pre_x_offset(synctex_scanner_p scanner){ 6149 return scanner?scanner->pre_x_offset:0; 6150 } 6151 int synctex_scanner_pre_y_offset(synctex_scanner_p scanner){ 6152 return scanner?scanner->pre_y_offset:0; 6153 } 6154 int synctex_scanner_x_offset(synctex_scanner_p scanner){ 6155 return scanner?scanner->x_offset:0; 6156 } 6157 int synctex_scanner_y_offset(synctex_scanner_p scanner){ 6158 return scanner?scanner->y_offset:0; 6159 } 6160 float synctex_scanner_magnification(synctex_scanner_p scanner){ 6161 return scanner?scanner->unit:1; 6162 } 6163 void synctex_scanner_display(synctex_scanner_p scanner) { 6164 if (NULL == scanner) { 6165 return; 6166 } 6167 printf("The scanner:\noutput:%s\noutput_fmt:%s\nversion:%i\n",scanner->reader->output,scanner->output_fmt,scanner->version); 6168 printf("pre_unit:%i\nx_offset:%i\ny_offset:%i\n",scanner->pre_unit,scanner->pre_x_offset,scanner->pre_y_offset); 6169 printf("count:%i\npost_magnification:%f\npost_x_offset:%f\npost_y_offset:%f\n", 6170 scanner->count,scanner->unit,scanner->x_offset,scanner->y_offset); 6171 printf("The input:\n"); 6172 synctex_node_display(scanner->input); 6173 if (scanner->count<1000) { 6174 printf("The sheets:\n"); 6175 synctex_node_display(scanner->sheet); 6176 printf("The friends:\n"); 6177 if (scanner->lists_of_friends) { 6178 int i = scanner->number_of_lists; 6179 synctex_node_p node; 6180 while(i--) { 6181 printf("Friend index:%i\n",i); 6182 node = (scanner->lists_of_friends)[i]; 6183 while(node) { 6184 printf("%s:%i,%i\n", 6185 synctex_node_isa(node), 6186 _synctex_data_tag(node), 6187 _synctex_data_line(node) 6188 ); 6189 node = _synctex_tree_friend(node); 6190 } 6191 } 6192 } 6193 } else { 6194 printf("SyncTeX Warning: Too many objects\n"); 6195 } 6196 } 6197 /* Public */ 6198 const char * synctex_scanner_get_name(synctex_scanner_p scanner,int tag) { 6199 synctex_node_p input = NULL; 6200 if (NULL == scanner) { 6201 return NULL; 6202 } 6203 if ((input = scanner->input)) {; 6204 do { 6205 if (tag == _synctex_data_tag(input)) { 6206 return (_synctex_data_name(input)); 6207 } 6208 } while((input = __synctex_tree_sibling(input))); 6209 } 6210 return NULL; 6211 } 6212 const char * synctex_node_get_name(synctex_node_p node) { 6213 if (node) { 6214 return synctex_scanner_get_name(node->class_->scanner,_synctex_data_tag(node)); 6215 } 6216 return NULL; 6217 } 6218 6219 static int _synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name); 6220 static int _synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name) { 6221 synctex_node_p input = NULL; 6222 if (NULL == scanner) { 6223 return 0; 6224 } 6225 if ((input = scanner->input)) { 6226 do { 6227 if (_synctex_is_equivalent_file_name(name,(_synctex_data_name(input)))) { 6228 return _synctex_data_tag(input); 6229 } 6230 } while((input = __synctex_tree_sibling(input))); 6231 } 6232 // 2011 version 6233 name = _synctex_base_name(name); 6234 if ((input = scanner->input)) { 6235 do { 6236 if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(input)))) { 6237 synctex_node_p other_input = input; 6238 while((other_input = __synctex_tree_sibling(other_input))) { 6239 if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(other_input))) 6240 && (strlen(_synctex_data_name(input))!=strlen(_synctex_data_name(other_input)) 6241 || strncmp(_synctex_data_name(other_input),_synctex_data_name(input),strlen(_synctex_data_name(input))))) { 6242 // There is a second possible candidate 6243 return 0; 6244 } 6245 } 6246 return _synctex_data_tag(input); 6247 } 6248 } while((input = __synctex_tree_sibling(input))); 6249 } 6250 return 0; 6251 } 6252 6253 int synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name) { 6254 size_t char_index = strlen(name); 6255 if ((scanner = synctex_scanner_parse(scanner)) && (0 < char_index)) { 6256 /* the name is not void */ 6257 char_index -= 1; 6258 if (!SYNCTEX_IS_PATH_SEPARATOR(name[char_index])) { 6259 /* the last character of name is not a path separator */ 6260 int result = _synctex_scanner_get_tag(scanner,name); 6261 if (result) { 6262 return result; 6263 } else { 6264 /* the given name was not the one known by TeX 6265 * try a name relative to the enclosing directory of the scanner->output file */ 6266 const char * relative = name; 6267 const char * ptr = scanner->reader->output; 6268 while((strlen(relative) > 0) && (strlen(ptr) > 0) && (*relative == *ptr)) 6269 { 6270 relative += 1; 6271 ptr += 1; 6272 } 6273 /* Find the last path separator before relative */ 6274 while(relative > name) { 6275 if (SYNCTEX_IS_PATH_SEPARATOR(*(relative-1))) { 6276 break; 6277 } 6278 relative -= 1; 6279 } 6280 if ((relative > name) && (result = _synctex_scanner_get_tag(scanner,relative))) { 6281 return result; 6282 } 6283 if (SYNCTEX_IS_PATH_SEPARATOR(name[0])) { 6284 /* No tag found for the given absolute name, 6285 * Try each relative path starting from the shortest one */ 6286 while(0<char_index) { 6287 char_index -= 1; 6288 if (SYNCTEX_IS_PATH_SEPARATOR(name[char_index]) 6289 && (result = _synctex_scanner_get_tag(scanner,name+char_index+1))) { 6290 return result; 6291 } 6292 } 6293 } 6294 } 6295 return result; 6296 } 6297 } 6298 return 0; 6299 } 6300 synctex_node_p synctex_scanner_input(synctex_scanner_p scanner) { 6301 return scanner?scanner->input:NULL; 6302 } 6303 synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner, int tag) { 6304 synctex_node_p input = scanner?scanner->input:NULL; 6305 while (_synctex_data_tag(input)!=tag) { 6306 if ((input = __synctex_tree_sibling(input))) { 6307 continue; 6308 } 6309 break; 6310 } 6311 return input; 6312 } 6313 const char * synctex_scanner_get_output_fmt(synctex_scanner_p scanner) { 6314 return NULL != scanner && scanner->output_fmt?scanner->output_fmt:""; 6315 } 6316 const char * synctex_scanner_get_output(synctex_scanner_p scanner) { 6317 return NULL != scanner && scanner->reader->output?scanner->reader->output:""; 6318 } 6319 const char * synctex_scanner_get_synctex(synctex_scanner_p scanner) { 6320 return NULL != scanner && scanner->reader->synctex?scanner->reader->synctex:""; 6321 } 6322 # ifdef SYNCTEX_NOTHING 6323 # pragma mark - 6324 # pragma mark Public node attributes 6325 # endif 6326 6327 # define SYNCTEX_DEFINE_NODE_HVWHD(WHAT) \ 6328 int synctex_node_##WHAT(synctex_node_p node) { \ 6329 return (node && node->class_->inspector->WHAT)? \ 6330 node->class_->inspector->WHAT(node): 0; \ 6331 } 6332 # define SYNCTEX_DEFINE_PROXY_HV(WHAT) \ 6333 static int _synctex_proxy_##WHAT(synctex_proxy_p proxy) { \ 6334 synctex_node_p target = _synctex_tree_target(proxy); \ 6335 if (target) { \ 6336 return _synctex_data_##WHAT(proxy)+synctex_node_##WHAT(target); \ 6337 } else { \ 6338 return proxy? _synctex_data_##WHAT(proxy): 0; \ 6339 } \ 6340 } 6341 #define SYNCTEX_DEFINE_PROXY_TLCWVD(WHAT) \ 6342 static int _synctex_proxy_##WHAT(synctex_proxy_p proxy) { \ 6343 synctex_node_p target = _synctex_tree_target(proxy); \ 6344 return target? synctex_node_##WHAT(target): 0; \ 6345 } 6346 6347 /** 6348 * The horizontal location of the node. 6349 * Idem for v, width, height and depth. 6350 * - parameter node: a node with geometrical information. 6351 * - returns: an integer. 6352 * - requires: every proxy node has a target. 6353 * - note: recursive call if the parameter has a proxy. 6354 * - author: JL 6355 */ 6356 SYNCTEX_DEFINE_NODE_HVWHD(h) 6357 SYNCTEX_DEFINE_NODE_HVWHD(v) 6358 SYNCTEX_DEFINE_NODE_HVWHD(width) 6359 SYNCTEX_DEFINE_NODE_HVWHD(height) 6360 SYNCTEX_DEFINE_NODE_HVWHD(depth) 6361 SYNCTEX_DEFINE_PROXY_TLCWVD(tag) 6362 SYNCTEX_DEFINE_PROXY_TLCWVD(line) 6363 SYNCTEX_DEFINE_PROXY_TLCWVD(column) 6364 SYNCTEX_DEFINE_PROXY_HV(h) 6365 SYNCTEX_DEFINE_PROXY_HV(v) 6366 SYNCTEX_DEFINE_PROXY_TLCWVD(width) 6367 SYNCTEX_DEFINE_PROXY_TLCWVD(height) 6368 SYNCTEX_DEFINE_PROXY_TLCWVD(depth) 6369 6370 /** 6371 * Whether the argument is a box, 6372 * either vertical or horizontal, 6373 * either void or not, 6374 * or a proxy to such a box. 6375 * - parameter NODE: of type synctex_node_p 6376 * - returns: yorn 6377 */ 6378 6379 SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_box(synctex_node_p node) { 6380 return node && 6381 (node->class_->type == synctex_node_type_hbox 6382 || node->class_->type == synctex_node_type_void_hbox 6383 || node->class_->type == synctex_node_type_vbox 6384 || node->class_->type == synctex_node_type_void_vbox 6385 || _synctex_node_is_box(_synctex_tree_target(node))); 6386 } 6387 6388 /** 6389 * Whether the argument is a handle. 6390 * Handles are similar to proxies because they have a target. 6391 * They are used for query results. 6392 * - parameter NODE: of type synctex_node_p 6393 * - returns: yorn 6394 */ 6395 6396 SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_handle(synctex_node_p node) { 6397 return node && 6398 (node->class_->type == synctex_node_type_handle); 6399 } 6400 6401 /** 6402 * Resolves handle indirection. 6403 * - parameter node: of type synctex_node_p 6404 * - returns: node if it is not a handle, 6405 * its target otherwise. 6406 */ 6407 6408 SYNCTEX_INLINE static synctex_node_p _synctex_node_or_handle_target(synctex_node_p node) { 6409 return _synctex_node_is_handle(node)? 6410 _synctex_tree_target(node):node; 6411 } 6412 6413 /** 6414 * Whether the argument is an hbox. 6415 * - parameter NODE: of type synctex_node_p 6416 * - returns: yorn 6417 */ 6418 6419 SYNCTEX_INLINE static synctex_bool_t _synctex_node_is_hbox(synctex_node_p node) { 6420 return node && 6421 (node->class_->type == synctex_node_type_hbox 6422 || node->class_->type == synctex_node_type_void_hbox 6423 || _synctex_node_is_hbox(_synctex_tree_target(node))); 6424 } 6425 6426 /** 6427 * The horizontal location of the first box enclosing node. 6428 * - parameter node: a node with geometrical information. 6429 * - returns: an integer. 6430 * - author: JL 6431 */ 6432 int synctex_node_box_h(synctex_node_p node) { 6433 if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { 6434 return synctex_node_h(node); 6435 } 6436 return 0; 6437 } 6438 /** 6439 * The vertical location of the first box enclosing node. 6440 * - parameter node: a node with geometrical information. 6441 * - returns: an integer. 6442 * - author: JL 6443 */ 6444 int synctex_node_box_v(synctex_node_p node) { 6445 if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { 6446 return synctex_node_v(node); 6447 } 6448 return 0; 6449 } 6450 /** 6451 * The width of the first box enclosing node. 6452 * - parameter node: a node with geometrical information. 6453 * - returns: an integer. 6454 * - author: JL 6455 */ 6456 int synctex_node_box_width(synctex_node_p node) { 6457 if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { 6458 return synctex_node_width(node); 6459 } 6460 return 0; 6461 } 6462 /** 6463 * The height of the first box enclosing node. 6464 * - parameter node: a node with geometrical information. 6465 * - returns: an integer. 6466 * - author: JL 6467 */ 6468 int synctex_node_box_height(synctex_node_p node) { 6469 if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { 6470 return synctex_node_height(node); 6471 } 6472 return 0; 6473 } 6474 /** 6475 * The depth of the first box enclosing node. 6476 * - parameter node: a node with geometrical information. 6477 * - returns: an integer. 6478 * - author: JL 6479 */ 6480 int synctex_node_box_depth(synctex_node_p node) { 6481 if (_synctex_node_is_box(node) || (node = _synctex_tree_parent(node))) { 6482 return synctex_node_depth(node); 6483 } 6484 return 0; 6485 } 6486 /** 6487 * The horizontal location of an hbox, corrected with contents. 6488 * - parameter node: an hbox node. 6489 * - returns: an integer, 0 if node is not an hbox or an hbox proxy. 6490 * - note: recursive call when node is an hbox proxy. 6491 * - author: JL 6492 */ 6493 int synctex_node_hbox_h(synctex_node_p node) { 6494 switch(synctex_node_type(node)) { 6495 case synctex_node_type_hbox: 6496 return _synctex_data_h_V(node); 6497 case synctex_node_type_proxy_hbox: 6498 return _synctex_data_h(node)+synctex_node_hbox_h(_synctex_tree_target(node)); 6499 default: 6500 return 0; 6501 } 6502 } 6503 /** 6504 * The vertical location of an hbox, corrected with contents. 6505 * - parameter node: an hbox node. 6506 * - returns: an integer, 0 if node is not an hbox or an hbox proxy. 6507 * - note: recursive call when node is an hbox proxy. 6508 * - author: JL 6509 */ 6510 int synctex_node_hbox_v(synctex_node_p node) { 6511 switch(synctex_node_type(node)) { 6512 case synctex_node_type_hbox: 6513 return _synctex_data_v_V(node); 6514 case synctex_node_type_proxy_hbox: 6515 return _synctex_data_v(node)+synctex_node_hbox_v(_synctex_tree_target(node)); 6516 default: 6517 return 0; 6518 } 6519 } 6520 /** 6521 * The width of an hbox, corrected with contents. 6522 * - parameter node: an hbox node, 0 if node is not an hbox or an hbox proxy. 6523 * - returns: an integer. 6524 * - author: JL 6525 */ 6526 int synctex_node_hbox_width(synctex_node_p node) { 6527 synctex_node_p target = _synctex_tree_target(node); 6528 if (target) { 6529 node = target; 6530 } 6531 return synctex_node_type(node) == synctex_node_type_hbox? 6532 _synctex_data_width_V(node): 0; 6533 } 6534 /** 6535 * The height of an hbox, corrected with contents. 6536 * - parameter node: an hbox node. 6537 * - returns: an integer, 0 if node is not an hbox or an hbox proxy. 6538 * - author: JL 6539 */ 6540 int synctex_node_hbox_height(synctex_node_p node) { 6541 synctex_node_p target = _synctex_tree_target(node); 6542 if (target) { 6543 node = target; 6544 } 6545 return synctex_node_type(node) == synctex_node_type_hbox? 6546 _synctex_data_height_V(node): 0; 6547 } 6548 /** 6549 * The depth of an hbox, corrected with contents. 6550 * - parameter node: an hbox node. 6551 * - returns: an integer, 0 if node is not an hbox or an hbox proxy. 6552 * - note: recursive call when node is an hbox proxy. 6553 * - author: JL 6554 */ 6555 int synctex_node_hbox_depth(synctex_node_p node) { 6556 synctex_node_p target = _synctex_tree_target(node); 6557 if (target) { 6558 node = target; 6559 } 6560 return synctex_node_type(node) == synctex_node_type_hbox? 6561 _synctex_data_depth_V(node): 0; 6562 } 6563 # ifdef SYNCTEX_NOTHING 6564 # pragma mark - 6565 # pragma mark Public node visible attributes 6566 # endif 6567 6568 #define SYNCTEX_VISIBLE_SIZE(node,s) \ 6569 (s)*node->class_->scanner->unit 6570 #define SYNCTEX_VISIBLE_DISTANCE_h(node,d) \ 6571 ((d)*node->class_->scanner->unit+node->class_->scanner->x_offset) 6572 #define SYNCTEX_VISIBLE_DISTANCE_v(node,d) \ 6573 ((d)*node->class_->scanner->unit+node->class_->scanner->y_offset) 6574 static float __synctex_node_visible_h(synctex_node_p node) { 6575 return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node)); 6576 } 6577 static float __synctex_node_visible_v(synctex_node_p node) { 6578 return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node)); 6579 } 6580 static float __synctex_node_visible_width(synctex_node_p node) { 6581 return SYNCTEX_VISIBLE_SIZE(node,synctex_node_width(node)); 6582 } 6583 static float __synctex_node_visible_height(synctex_node_p node) { 6584 return SYNCTEX_VISIBLE_SIZE(node,synctex_node_height(node)); 6585 } 6586 static float __synctex_node_visible_depth(synctex_node_p node) { 6587 return SYNCTEX_VISIBLE_SIZE(node,synctex_node_depth(node)); 6588 } 6589 static float __synctex_proxy_visible_h(synctex_node_p node) { 6590 return SYNCTEX_VISIBLE_DISTANCE_h(node,synctex_node_h(node)); 6591 } 6592 static float __synctex_proxy_visible_v(synctex_node_p node) { 6593 return SYNCTEX_VISIBLE_DISTANCE_v(node,synctex_node_v(node)); 6594 } 6595 static float __synctex_proxy_visible_width(synctex_node_p node) { 6596 synctex_node_p target = _synctex_tree_target(node); 6597 return __synctex_node_visible_width(target); 6598 } 6599 static float __synctex_proxy_visible_height(synctex_node_p node) { 6600 synctex_node_p target = _synctex_tree_target(node); 6601 return __synctex_node_visible_height(target); 6602 } 6603 static float __synctex_proxy_visible_depth(synctex_node_p node) { 6604 synctex_node_p target = _synctex_tree_target(node); 6605 return __synctex_node_visible_depth(target); 6606 } 6607 static float __synctex_kern_visible_h(synctex_noxy_p noxy) { 6608 int h = _synctex_data_h(noxy); 6609 int width = _synctex_data_width(noxy); 6610 return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width>0?h-width:h); 6611 } 6612 static float __synctex_kern_visible_width(synctex_noxy_p noxy) { 6613 int width = _synctex_data_width(noxy); 6614 return SYNCTEX_VISIBLE_SIZE(noxy, width>0?width:-width); 6615 } 6616 static float __synctex_rule_visible_h(synctex_noxy_p noxy) { 6617 int h = _synctex_data_h(noxy); 6618 int width = _synctex_data_width(noxy); 6619 return SYNCTEX_VISIBLE_DISTANCE_h(noxy, width>0?h:h-width); 6620 } 6621 static float __synctex_rule_visible_width(synctex_noxy_p noxy) { 6622 int width = _synctex_data_width(noxy); 6623 return SYNCTEX_VISIBLE_SIZE(noxy, width>0?width:-width); 6624 } 6625 static float __synctex_rule_visible_v(synctex_noxy_p noxy) { 6626 return __synctex_node_visible_v(noxy); 6627 } 6628 static float __synctex_rule_visible_height(synctex_noxy_p noxy) { 6629 return __synctex_node_visible_height(noxy); 6630 } 6631 static float __synctex_rule_visible_depth(synctex_noxy_p noxy) { 6632 return __synctex_node_visible_depth(noxy); 6633 } 6634 6635 /** 6636 * The horizontal location of node, in page coordinates. 6637 * - parameter node: a node. 6638 * - returns: a float. 6639 * - author: JL 6640 */ 6641 float synctex_node_visible_h(synctex_node_p node){ 6642 return node? node->class_->vispector->h(node): 0; 6643 } 6644 /** 6645 * The vertical location of node, in page coordinates. 6646 * - parameter node: a node. 6647 * - returns: a float. 6648 * - author: JL 6649 */ 6650 float synctex_node_visible_v(synctex_node_p node){ 6651 return node? node->class_->vispector->v(node): 0; 6652 } 6653 /** 6654 * The width of node, in page coordinates. 6655 * - parameter node: a node. 6656 * - returns: a float. 6657 * - author: JL 6658 */ 6659 float synctex_node_visible_width(synctex_node_p node){ 6660 return node? node->class_->vispector->width(node): 0; 6661 } 6662 /** 6663 * The height of node, in page coordinates. 6664 * - parameter node: a node. 6665 * - returns: a float. 6666 * - author: JL 6667 */ 6668 float synctex_node_visible_height(synctex_node_p node){ 6669 return node? node->class_->vispector->height(node): 0; 6670 } 6671 /** 6672 * The depth of node, in page coordinates. 6673 * - parameter node: a node. 6674 * - returns: a float. 6675 * - author: JL 6676 */ 6677 float synctex_node_visible_depth(synctex_node_p node){ 6678 return node? node->class_->vispector->depth(node): 0; 6679 } 6680 6681 /** 6682 * The V variant of geometrical information. 6683 * - parameter node: a node. 6684 * - returns: an integer. 6685 * - author: JL 6686 */ 6687 #define SYNCTEX_DEFINE_V(WHAT)\ 6688 SYNCTEX_INLINE static int _synctex_node_##WHAT##_V(synctex_node_p node) { \ 6689 synctex_node_p target = _synctex_tree_target(node); \ 6690 if (target) { \ 6691 return _synctex_data_##WHAT(node)+_synctex_node_##WHAT##_V(target); \ 6692 } else if (_synctex_data_has_##WHAT##_V(node)) { \ 6693 return _synctex_data_##WHAT##_V(node); \ 6694 } else { \ 6695 return _synctex_data_##WHAT(node); \ 6696 } \ 6697 } 6698 SYNCTEX_DEFINE_V(h) 6699 SYNCTEX_DEFINE_V(v) 6700 SYNCTEX_DEFINE_V(width) 6701 SYNCTEX_DEFINE_V(height) 6702 SYNCTEX_DEFINE_V(depth) 6703 6704 SYNCTEX_INLINE static synctex_point_s _synctex_data_point(synctex_node_p node) { 6705 return (synctex_point_s){synctex_node_h(node),synctex_node_v(node)}; 6706 } 6707 SYNCTEX_INLINE static synctex_point_s _synctex_data_point_V(synctex_node_p node) { 6708 return (synctex_point_s){_synctex_node_h_V(node),_synctex_node_v_V(node)}; 6709 } 6710 SYNCTEX_INLINE static synctex_point_s _synctex_data_set_point(synctex_node_p node, synctex_point_s point) { 6711 synctex_point_s old = _synctex_data_point(node); 6712 _synctex_data_set_h(node,point.h); 6713 _synctex_data_set_v(node,point.v); 6714 return old; 6715 } 6716 SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node) { 6717 synctex_box_s box = {{0,0},{0,0}}; 6718 int n; 6719 n = synctex_node_width(node); 6720 if (n<0) { 6721 box.max.h = synctex_node_h(node); 6722 box.min.h = box.max.h + n; 6723 } else { 6724 box.min.h = synctex_node_h(node); 6725 box.max.h = box.min.h + n; 6726 } 6727 n = synctex_node_v(node); 6728 box.min.v = n - synctex_node_height(node); 6729 box.max.v = n + synctex_node_depth(node); 6730 return box; 6731 } 6732 SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node) { 6733 synctex_box_s box = {{0,0},{0,0}}; 6734 int n; 6735 n = synctex_node_width(node); 6736 if (n>0) { 6737 box.max.h = synctex_node_h(node); 6738 box.min.h = box.max.h - n; 6739 } else { 6740 box.min.h = synctex_node_h(node); 6741 box.max.h = box.min.h - n; 6742 } 6743 n = synctex_node_v(node); 6744 box.min.v = n - synctex_node_height(node); 6745 box.max.v = n + synctex_node_depth(node); 6746 return box; 6747 } 6748 SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node) { 6749 synctex_box_s box = {{0,0},{0,0}}; 6750 int n; 6751 n = _synctex_node_width_V(node); 6752 if (n<0) { 6753 box.max.h = _synctex_node_h_V(node); 6754 box.min.h = box.max.h + n; 6755 } else { 6756 box.min.h = _synctex_node_h_V(node); 6757 box.max.h = box.min.h + n; 6758 } 6759 n = _synctex_node_v_V(node); 6760 box.min.v = n - _synctex_node_height_V(node); 6761 box.max.v = n + _synctex_node_depth_V(node); 6762 return box; 6763 } 6764 6765 /** 6766 * The higher box node in the parent hierarchy which 6767 * mean line number is the one of node ±1. 6768 * This enclosing box is computed as follows 6769 * 1) get the first hbox in the parent linked list 6770 * starting at node. 6771 * If there is none, simply return the parent of node. 6772 * 2) compute the mean line number 6773 * 3) scans up the tree for the higher hbox with 6774 * the same mean line number, ±1 eventually 6775 * - parameter node: a node. 6776 * - returns: a (proxy to a) box node. 6777 * - author: JL 6778 */ 6779 static synctex_node_p _synctex_node_box_visible(synctex_node_p node) { 6780 if ((node = _synctex_node_or_handle_target(node))) { 6781 int mean = 0; 6782 int bound = 1500000/(node->class_->scanner->pre_magnification/1000.0); 6783 synctex_node_p parent = NULL; 6784 /* get the first enclosing parent 6785 * then get the highest enclosing parent with the same mean line ±1 */ 6786 node = _synctex_node_or_handle_target(node); 6787 if (!_synctex_node_is_box(node)) { 6788 if ((parent = _synctex_tree_parent(node))) { 6789 node = parent; 6790 } else if ((node = _synctex_tree_target(node))) { 6791 if (!_synctex_node_is_box(node)) { 6792 if ((parent = _synctex_tree_parent(node))) { 6793 node = parent; 6794 } else { 6795 return NULL; 6796 } 6797 } 6798 } 6799 } 6800 parent = node; 6801 mean = synctex_node_mean_line(node); 6802 while ((parent = _synctex_tree_parent(parent))) { 6803 if (_synctex_node_is_hbox(parent)) { 6804 if (_synctex_abs(mean-synctex_node_mean_line(parent))>1) { 6805 return node; 6806 } else if (synctex_node_width(parent)>bound) { 6807 return parent; 6808 } else if (synctex_node_height(parent)+synctex_node_depth(parent)>bound) { 6809 return parent; 6810 } 6811 node = parent; 6812 } 6813 } 6814 } 6815 return node; 6816 } 6817 /** 6818 * The horizontal location of the first box enclosing node, in page coordinates. 6819 * - parameter node: a node. 6820 * - returns: a float. 6821 * - author: JL 6822 */ 6823 float synctex_node_box_visible_h(synctex_node_p node) { 6824 return SYNCTEX_VISIBLE_DISTANCE_h(node,_synctex_node_h_V(_synctex_node_box_visible(node))); 6825 } 6826 /** 6827 * The vertical location of the first box enclosing node, in page coordinates. 6828 * - parameter node: a node. 6829 * - returns: a float. 6830 * - author: JL 6831 */ 6832 float synctex_node_box_visible_v(synctex_node_p node) { 6833 return SYNCTEX_VISIBLE_DISTANCE_v(node,_synctex_node_v_V(_synctex_node_box_visible(node))); 6834 } 6835 /** 6836 * The width of the first box enclosing node, in page coordinates. 6837 * - parameter node: a node. 6838 * - returns: a float. 6839 * - author: JL 6840 */ 6841 float synctex_node_box_visible_width(synctex_node_p node) { 6842 return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_width_V(_synctex_node_box_visible(node))); 6843 } 6844 /** 6845 * The height of the first box enclosing node, in page coordinates. 6846 * - parameter node: a node. 6847 * - returns: a float. 6848 * - author: JL 6849 */ 6850 float synctex_node_box_visible_height(synctex_node_p node) { 6851 return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_height_V(_synctex_node_box_visible(node))); 6852 } 6853 /** 6854 * The depth of the first box enclosing node, in page coordinates. 6855 * - parameter node: a node. 6856 * - returns: a float. 6857 * - author: JL 6858 */ 6859 float synctex_node_box_visible_depth(synctex_node_p node) { 6860 return SYNCTEX_VISIBLE_SIZE(node,_synctex_node_depth_V(_synctex_node_box_visible(node))); 6861 } 6862 # ifdef SYNCTEX_NOTHING 6863 # pragma mark - 6864 # pragma mark Other public node attributes 6865 # endif 6866 6867 /** 6868 * The page number of the sheet enclosing node. 6869 * - parameter node: a node. 6870 * - returns: the page number or -1 if node does not belong to a sheet tree. 6871 * - note: a proxy target does not belong to a sheet 6872 * but a form, its page number is always -1. 6873 * - note: a handles does not belong to a sheet not a form. 6874 * its page number is -1. 6875 * - author: JL 6876 */ 6877 int synctex_node_page(synctex_node_p node){ 6878 synctex_node_p parent = NULL; 6879 while((parent = _synctex_tree_parent(node))) { 6880 node = parent; 6881 } 6882 if (synctex_node_type(node) == synctex_node_type_sheet) { 6883 return _synctex_data_page(node); 6884 } 6885 return -1; 6886 } 6887 /** 6888 * The page number of the target. 6889 * - author: JL 6890 */ 6891 SYNCTEX_INLINE static int _synctex_node_target_page(synctex_node_p node){ 6892 return synctex_node_page(_synctex_tree_target(node)); 6893 } 6894 6895 #if defined (SYNCTEX_USE_CHARINDEX) 6896 synctex_charindex_t synctex_node_charindex(synctex_node_p node) { 6897 synctex_node_p target = _synctex_tree_target(node); 6898 return target? SYNCTEX_CHARINDEX(target):(node?SYNCTEX_CHARINDEX(node):0); 6899 } 6900 #endif 6901 6902 /** 6903 * The tag of the node. 6904 * - parameter node: a node. 6905 * - returns: the tag or -1 if node is NULL. 6906 * - author: JL 6907 */ 6908 int synctex_node_tag(synctex_node_p node) { 6909 return node? node->class_->tlcpector->tag(node): -1; 6910 } 6911 /** 6912 * The line of the node. 6913 * - parameter node: a node. 6914 * - returns: the line or -1 if node is NULL. 6915 * - author: JL 6916 */ 6917 int synctex_node_line(synctex_node_p node) { 6918 return node? node->class_->tlcpector->line(node): -1; 6919 } 6920 /** 6921 * The column of the node. 6922 * - parameter node: a node. 6923 * - returns: the column or -1 if node is NULL. 6924 * - author: JL 6925 */ 6926 int synctex_node_column(synctex_node_p node) { 6927 return node? node->class_->tlcpector->column(node): -1; 6928 } 6929 /** 6930 * The mean line number of the node. 6931 * - parameter node: a node. 6932 * - returns: the mean line or -1 if node is NULL. 6933 * - author: JL 6934 */ 6935 int synctex_node_mean_line(synctex_node_p node) { 6936 synctex_node_p other = _synctex_tree_target(node); 6937 if (other) { 6938 node = other; 6939 } 6940 if (_synctex_data_has_mean_line(node)) { 6941 return _synctex_data_mean_line(node); 6942 } 6943 if ((other = synctex_node_parent(node))) { 6944 if (_synctex_data_has_mean_line(other)) { 6945 return _synctex_data_mean_line(other); 6946 } 6947 } 6948 return synctex_node_line(node); 6949 } 6950 /** 6951 * The weight of the node. 6952 * - parameter node: a node. 6953 * - returns: the weight or -1 if node is NULL. 6954 * - author: JL 6955 */ 6956 int synctex_node_weight(synctex_node_p node) { 6957 synctex_node_p target = _synctex_tree_target(node); 6958 if (target) { 6959 node = target; 6960 } 6961 return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1; 6962 } 6963 /** 6964 * The number of children of the node. 6965 * - parameter node: a node. 6966 * - returns: the count or -1 if node is NULL. 6967 * - author: JL 6968 */ 6969 int synctex_node_child_count(synctex_node_p node) { 6970 synctex_node_p target = _synctex_tree_target(node); 6971 if (target) { 6972 node = target; 6973 } 6974 return node?(synctex_node_type(node)==synctex_node_type_hbox?_synctex_data_weight(node):0):-1; 6975 } 6976 # ifdef SYNCTEX_NOTHING 6977 # pragma mark - 6978 # pragma mark Sheet & Form 6979 # endif 6980 6981 /** 6982 * The sheet of the scanner with a given page number. 6983 * - parameter scanner: a scanner. 6984 * - parameter page: a 1 based page number. 6985 * If page == 0, returns the first sheet. 6986 * - returns: a sheet or NULL. 6987 * - author: JL 6988 */ 6989 synctex_node_p synctex_sheet(synctex_scanner_p scanner,int page) { 6990 if (scanner) { 6991 synctex_node_p sheet = scanner->sheet; 6992 while(sheet) { 6993 if (page == _synctex_data_page(sheet)) { 6994 return sheet; 6995 } 6996 sheet = __synctex_tree_sibling(sheet); 6997 } 6998 if (page == 0) { 6999 return scanner->sheet; 7000 } 7001 } 7002 return NULL; 7003 } 7004 /** 7005 * The form of the scanner with a given tag. 7006 * - parameter scanner: a scanner. 7007 * - parameter tag: an integer identifier. 7008 * If tag == 0, returns the first form. 7009 * - returns: a form. 7010 * - author: JL 7011 */ 7012 synctex_node_p synctex_form(synctex_scanner_p scanner,int tag) { 7013 if (scanner) { 7014 synctex_node_p form = scanner->form; 7015 while(form) { 7016 if (tag == _synctex_data_tag(form)) { 7017 return form; 7018 } 7019 form = __synctex_tree_sibling(form); 7020 } 7021 if (tag == 0) { 7022 return scanner->form; 7023 } 7024 } 7025 return NULL; 7026 } 7027 7028 /** 7029 * The content of the sheet with given page number. 7030 * - parameter scanner: a scanner. 7031 * - parameter page: a 1 based page number. 7032 * - returns: a (vertical) box node. 7033 * - author: JL 7034 */ 7035 synctex_node_p synctex_sheet_content(synctex_scanner_p scanner,int page) { 7036 if (scanner) { 7037 return _synctex_tree_child(synctex_sheet(scanner,page)); 7038 } 7039 return NULL; 7040 } 7041 7042 /** 7043 * The content of the sheet with given page number. 7044 * - parameter scanner: a scanner. 7045 * - parameter tag: an integer identifier. 7046 * - returns: a box node. 7047 * - author: JL 7048 */ 7049 synctex_node_p synctex_form_content(synctex_scanner_p scanner,int tag) { 7050 if (scanner) { 7051 return _synctex_tree_child(synctex_form(scanner,tag)); 7052 } 7053 return NULL; 7054 } 7055 7056 SYNCTEX_INLINE static synctex_node_p _synctex_scanner_friend(synctex_scanner_p scanner,int i) { 7057 if (i>=0) { 7058 i = _synctex_abs(i)%(scanner->number_of_lists); 7059 return (scanner->lists_of_friends)[i]; 7060 } 7061 return NULL; 7062 } 7063 SYNCTEX_INLINE static synctex_bool_t _synctex_nodes_are_friend(synctex_node_p left, synctex_node_p right) { 7064 return synctex_node_tag(left) == synctex_node_tag(right) && synctex_node_line(left) == synctex_node_line(right); 7065 } 7066 /** 7067 * The sibling argument is a parent/child list of nodes of the same page. 7068 */ 7069 typedef struct { 7070 int count; 7071 synctex_node_p node; 7072 } synctex_counted_node_s; 7073 7074 SYNCTEX_INLINE static synctex_counted_node_s _synctex_vertically_sorted_v2(synctex_node_p sibling) { 7075 /* Clean the weights of the parents */ 7076 synctex_counted_node_s result = {0, NULL}; 7077 synctex_node_p h = NULL; 7078 synctex_node_p next_h = NULL; 7079 synctex_node_p parent = NULL; 7080 int weight = 0; 7081 synctex_node_p N = NULL; 7082 h = sibling; 7083 do { 7084 N = _synctex_tree_target(h); 7085 parent = _synctex_tree_parent(N); 7086 _synctex_data_set_weight(parent, 0); 7087 } while((h = _synctex_tree_child(h))); 7088 /* Compute the weights of the nodes */ 7089 h = sibling; 7090 do { 7091 N = _synctex_tree_target(h); 7092 parent = _synctex_tree_parent(N); 7093 weight = _synctex_data_weight(parent); 7094 if (weight==0) { 7095 N = _synctex_tree_child(parent); 7096 do { 7097 if (_synctex_nodes_are_friend(N,sibling)) { 7098 ++ weight; 7099 } 7100 } while ((N = __synctex_tree_sibling(N))); 7101 _synctex_data_set_weight(h,weight); 7102 _synctex_data_set_weight(parent,weight); 7103 } 7104 } while((h = _synctex_tree_child(h))); 7105 /* Order handle nodes according to the weight */ 7106 h = _synctex_tree_reset_child(sibling); 7107 result.node = sibling; 7108 weight = 0; 7109 while((h)) { 7110 N = result.node; 7111 if (_synctex_data_weight(h)>_synctex_data_weight(N)) { 7112 next_h = _synctex_tree_set_child(h,N); 7113 result.node = h; 7114 } else if (_synctex_data_weight(h) == 0) { 7115 ++ weight; 7116 next_h = _synctex_tree_reset_child(h); 7117 synctex_node_free(h); 7118 } else { 7119 synctex_node_p next_N = NULL; 7120 while((next_N = _synctex_tree_child(N))) { 7121 N = next_N; 7122 if (_synctex_data_weight(h)<_synctex_data_weight(next_N)) { 7123 continue; 7124 } 7125 break; 7126 } 7127 next_h = _synctex_tree_set_child(h,_synctex_tree_set_child(N,h)); 7128 } 7129 h = next_h; 7130 }; 7131 h = result.node; 7132 weight = 0; 7133 do { 7134 ++weight; 7135 } while((h = _synctex_tree_child(h))); 7136 result.count = 1; 7137 h = result.node; 7138 while((next_h = _synctex_tree_child(h))) { 7139 if (_synctex_data_weight(next_h)==0) { 7140 _synctex_tree_reset_child(h); 7141 weight = 1; 7142 h = next_h; 7143 while((h = _synctex_tree_child(h))) { 7144 ++weight; 7145 } 7146 synctex_node_free(next_h); 7147 break; 7148 } 7149 ++result.count; 7150 h = next_h; 7151 } 7152 return result; 7153 } 7154 7155 SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hitP, synctex_node_p node); 7156 7157 /* This struct records distances, the left one is non negative and the right one is non positive. 7158 * When comparing the locations of 2 different graphical objects on the page, we will have to also record the 7159 * horizontal distance as signed to keep track of the typesetting order.*/ 7160 7161 typedef struct { 7162 synctex_node_p node; 7163 int distance; 7164 } synctex_nd_s; 7165 7166 #define SYNCTEX_ND_0 (synctex_nd_s){NULL,INT_MAX} 7167 7168 typedef synctex_nd_s * synctex_nd_p; 7169 7170 typedef struct { 7171 synctex_nd_s l; 7172 synctex_nd_s r; 7173 } synctex_nd_lr_s; 7174 7175 /* The best container is the deeper box that contains the hit point (H,V). 7176 * _synctex_eq_deepest_container_v2 starts with node whereas 7177 * _synctex_box_child_deepest starts with node's children, if any 7178 * if node is not a box, or a void box, NULL is returned. 7179 * We traverse the node tree in a deep first manner and stop as soon as a result is found. */ 7180 static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hitP, synctex_node_p node); 7181 7182 SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node); 7183 7184 /* Closest child, recursive. */ 7185 static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node); 7186 7187 /* The smallest container between two has the smallest width or height. 7188 * This comparison is used when there are 2 overlapping boxes that contain the hit point. 7189 * For ConTeXt, the problem appears at each page. 7190 * The chosen box is the one with the smallest height, then the smallest width. */ 7191 SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node); 7192 7193 /* Returns the distance between the hit point hit point=(H,V) and the given node. */ 7194 7195 static int _synctex_point_node_distance_v2(synctex_point_p hitP, synctex_node_p node); 7196 7197 /* The closest container is the box that is the one closest to the given point. 7198 * The "visible" version takes into account the visible dimensions instead of the real ones given by TeX. */ 7199 static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node); 7200 7201 # ifdef SYNCTEX_NOTHING 7202 # pragma mark - 7203 # pragma mark Queries 7204 # endif 7205 7206 /** 7207 * iterator for a deep first tree traversal. 7208 */ 7209 struct synctex_iterator_t { 7210 synctex_node_p seed; 7211 synctex_node_p top; 7212 synctex_node_p next; 7213 int count0; 7214 int count; 7215 }; 7216 7217 SYNCTEX_INLINE static synctex_iterator_p _synctex_iterator_new(synctex_node_p result, int count) { 7218 synctex_iterator_p iterator; 7219 if ((iterator = _synctex_malloc(sizeof(synctex_iterator_s)))) { 7220 iterator->seed = iterator->top = iterator->next = result; 7221 iterator->count0 = iterator->count = count; 7222 } 7223 return iterator; 7224 }; 7225 7226 void synctex_iterator_free(synctex_iterator_p iterator) { 7227 if (iterator) { 7228 synctex_node_free(iterator->seed); 7229 _synctex_free(iterator); 7230 } 7231 } 7232 synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator) { 7233 return iterator?iterator->count>0:0; 7234 } 7235 int synctex_iterator_count(synctex_iterator_p iterator) { 7236 return iterator? iterator->count: 0; 7237 } 7238 7239 /** 7240 * The next result of the iterator. 7241 * Internally, the iterator stores handles to nodes. 7242 * Externally, it returns the targets, 7243 * such that the caller only sees nodes. 7244 */ 7245 synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator) { 7246 if (iterator && iterator->count>0) { 7247 synctex_node_p N = iterator->next; 7248 if(!(iterator->next = _synctex_tree_child(N))) { 7249 iterator->next = iterator->top = __synctex_tree_sibling(iterator->top); 7250 } 7251 --iterator->count; 7252 return _synctex_tree_target(N); 7253 } 7254 return NULL; 7255 } 7256 int synctex_iterator_reset(synctex_iterator_p iterator) { 7257 if (iterator) { 7258 iterator->next = iterator->top = iterator->seed; 7259 return iterator->count = iterator->count0; 7260 } 7261 return 0; 7262 } 7263 7264 synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner,int page,float h,float v){ 7265 if (scanner) { 7266 synctex_node_p sheet = NULL; 7267 synctex_point_s hit; 7268 synctex_node_p node = NULL; 7269 synctex_nd_lr_s nds = {{NULL,0},{NULL,0}}; 7270 if (NULL == (scanner = synctex_scanner_parse(scanner)) || 0 >= scanner->unit) {/* scanner->unit must be >0 */ 7271 return NULL; 7272 } 7273 /* Find the proper sheet */ 7274 sheet = synctex_sheet(scanner,page); 7275 if (NULL == sheet) { 7276 return NULL; 7277 } 7278 /* Now sheet points to the sheet node with proper page number. */ 7279 /* Now that scanner has been initialized, we can convert 7280 * the given point to scanner integer coordinates */ 7281 hit = (synctex_point_s) 7282 {(h-scanner->x_offset)/scanner->unit, 7283 (v-scanner->y_offset)/scanner->unit}; 7284 /* At first, we browse all the horizontal boxes of the sheet 7285 * until we find one containing the hit point. */ 7286 if ((node = _synctex_tree_next_hbox(sheet))) { 7287 do { 7288 if (_synctex_point_in_box_v2(&hit,node)) { 7289 /* Maybe the hit point belongs to a contained vertical box. 7290 * This is the most likely situation. 7291 */ 7292 synctex_node_p next = node; 7293 #if defined(SYNCTEX_DEBUG) 7294 printf("--- We are lucky\n"); 7295 #endif 7296 /* This trick is for catching overlapping boxes */ 7297 while ((next = _synctex_tree_next_hbox(next))) { 7298 if (_synctex_point_in_box_v2(&hit,next)) { 7299 node = _synctex_smallest_container_v2(next,node); 7300 } 7301 } 7302 /* node is the smallest horizontal box that contains hit, 7303 * unless there is no hbox at all. 7304 */ 7305 node = _synctex_eq_deepest_container_v2(&hit, node); 7306 nds = _synctex_eq_get_closest_children_in_box_v2(&hit, node); 7307 end: 7308 if (nds.r.node && nds.l.node) { 7309 if ((_synctex_data_tag(nds.r.node)!=_synctex_data_tag(nds.l.node)) 7310 || (_synctex_data_line(nds.r.node)!=_synctex_data_line(nds.l.node)) 7311 || (_synctex_data_column(nds.r.node)!=_synctex_data_column(nds.l.node))) { 7312 if (_synctex_data_line(nds.r.node)<_synctex_data_line(nds.l.node)) { 7313 node = nds.r.node; 7314 nds.r.node = nds.l.node; 7315 nds.l.node = node; 7316 } else if (_synctex_data_line(nds.r.node)==_synctex_data_line(nds.l.node)) { 7317 if (nds.l.distance>nds.r.distance) { 7318 node = nds.r.node; 7319 nds.r.node = nds.l.node; 7320 nds.l.node = node; 7321 } 7322 } 7323 if((node = _synctex_new_handle_with_target(nds.l.node))) { 7324 synctex_node_p other_handle; 7325 if((other_handle = _synctex_new_handle_with_target(nds.r.node))) { 7326 _synctex_tree_set_sibling(node,other_handle); 7327 return _synctex_iterator_new(node,2); 7328 } 7329 return _synctex_iterator_new(node,1); 7330 } 7331 return NULL; 7332 } 7333 /* both nodes have the same input coordinates 7334 * We choose the one closest to the hit point */ 7335 if (nds.l.distance>nds.r.distance) { 7336 nds.l.node = nds.r.node; 7337 } 7338 nds.r.node = NULL; 7339 } else if (nds.r.node) { 7340 nds.l = nds.r; 7341 } else if (!nds.l.node) { 7342 nds.l.node = node; 7343 } 7344 if((node = _synctex_new_handle_with_target(nds.l.node))) { 7345 return _synctex_iterator_new(node,1); 7346 } 7347 return 0; 7348 } 7349 } while ((node = _synctex_tree_next_hbox(node))); 7350 /* All the horizontal boxes have been tested, 7351 * None of them contains the hit point. 7352 */ 7353 } 7354 /* We are not lucky, 7355 * we test absolutely all the node 7356 * to find the closest... */ 7357 if ((node = _synctex_tree_child(sheet))) { 7358 #if defined(SYNCTEX_DEBUG) 7359 printf("--- We are not lucky\n"); 7360 #endif 7361 nds.l = __synctex_closest_deep_child_v2(&hit, node); 7362 #if defined(SYNCTEX_DEBUG) 7363 printf("Edit query best: %i\n", nds.l.distance); 7364 #endif 7365 goto end; 7366 } 7367 } 7368 return NULL; 7369 } 7370 7371 /** 7372 * Loop the candidate friendly list to find the ones with the proper 7373 * tag and line. 7374 * Returns a tree of results targeting the found candidates. 7375 * At the top level each sibling has its own page number. 7376 * All the results with the same page number are linked by child/parent entry. 7377 * - parameter candidate: a friendly list of candidates 7378 */ 7379 static synctex_node_p _synctex_display_query_v2(synctex_node_p target, int tag, int line, synctex_bool_t exclude_box) { 7380 synctex_node_p first_handle = NULL; 7381 /* Search the first match */ 7382 if (target == NULL) { 7383 return first_handle; 7384 } 7385 do { 7386 int page; 7387 if ((exclude_box 7388 && _synctex_node_is_box(target)) 7389 || (tag != synctex_node_tag(target)) 7390 || (line != synctex_node_line(target))) { 7391 continue; 7392 } 7393 /* We found a first match, create 7394 * a result handle targeting that candidate. */ 7395 first_handle = _synctex_new_handle_with_target(target); 7396 if (first_handle == NULL) { 7397 return first_handle; 7398 } 7399 /* target is either a node, 7400 * or a proxy to some node, in which case, 7401 * the target's target belongs to a form, 7402 * not a sheet. */ 7403 page = synctex_node_page(target); 7404 /* Now create all the other results */ 7405 while ((target = _synctex_tree_friend(target))) { 7406 synctex_node_p result = NULL; 7407 if ((exclude_box 7408 && _synctex_node_is_box(target)) 7409 || (tag != synctex_node_tag(target)) 7410 || (line != synctex_node_line(target))) { 7411 continue; 7412 } 7413 /* Another match, same page number ? */ 7414 result = _synctex_new_handle_with_target(target); 7415 if (NULL == result ) { 7416 return first_handle; 7417 } 7418 /* is it the same page number ? */ 7419 if (synctex_node_page(target) == page) { 7420 __synctex_tree_set_child(result, first_handle); 7421 first_handle = result; 7422 } else { 7423 /* We have 2 page numbers involved */ 7424 __synctex_tree_set_sibling(first_handle, result); 7425 while ((target = _synctex_tree_friend(target))) { 7426 synctex_node_p same_page_node; 7427 if ((exclude_box 7428 && _synctex_node_is_box(target)) 7429 || (tag != synctex_node_tag(target)) 7430 || (line != synctex_node_line(target))) { 7431 continue; 7432 } 7433 /* New match found, which page? */ 7434 result = _synctex_new_handle_with_target(target); 7435 if (NULL == result) { 7436 return first_handle; 7437 } 7438 same_page_node = first_handle; 7439 page = synctex_node_page(target); 7440 /* Find a result with the same page number */; 7441 do { 7442 if (_synctex_node_target_page(same_page_node) == page) { 7443 /* Insert result between same_page_node and its child */ 7444 _synctex_tree_set_child(result,_synctex_tree_set_child(same_page_node,result)); 7445 } else if ((same_page_node = __synctex_tree_sibling(same_page_node))) { 7446 continue; 7447 } else { 7448 /* This is a new page number */ 7449 __synctex_tree_set_sibling(result,first_handle); 7450 first_handle = result; 7451 } 7452 break; 7453 } while (synctex_YES); 7454 } 7455 return first_handle; 7456 } 7457 } 7458 } while ((target = _synctex_tree_friend(target))); 7459 return first_handle; 7460 } 7461 synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) { 7462 SYNCTEX_UNUSED(column) 7463 if (scanner) { 7464 int tag = synctex_scanner_get_tag(scanner,name);/* parse if necessary */ 7465 int max_line = 0; 7466 int line_offset = 1; 7467 int try_count = 100; 7468 synctex_node_p node = NULL; 7469 synctex_node_p result = NULL; 7470 if (tag == 0) { 7471 printf("SyncTeX Warning: No tag for %s\n",name); 7472 return NULL; 7473 } 7474 node = synctex_scanner_input_with_tag(scanner, tag); 7475 max_line = _synctex_data_line(node); 7476 /* node = NULL; */ 7477 if (line>max_line) { 7478 line = max_line; 7479 } 7480 while(try_count--) { 7481 if (line<=max_line) { 7482 /* This loop will only be performed once for advanced viewers */ 7483 synctex_node_p friend = _synctex_scanner_friend(scanner,tag+line); 7484 if ((node = friend)) { 7485 result = _synctex_display_query_v2(node,tag,line,synctex_YES); 7486 if (!result) { 7487 /* We did not find any matching boundary, retry including boxes */ 7488 node = friend;/* no need to test it again, already done */ 7489 result = _synctex_display_query_v2(node,tag,line,synctex_NO); 7490 } 7491 /* Now reverse the order to have nodes in display order, and then keep just a few nodes. 7492 * Order first the best node. */ 7493 /* The result is a tree. At the root level, all nodes 7494 * correspond to different page numbers. 7495 * Each node has a child which corresponds to the same 7496 * page number if relevant. 7497 * Then reorder the nodes to put first the one which fits best. 7498 * The idea is to count the number of nodes 7499 * with the same tag and line number in the parents 7500 * and choose the ones with the biggest count. 7501 */ 7502 if (result) { 7503 /* navigate through siblings, then children */ 7504 synctex_node_p next_sibling = __synctex_tree_reset_sibling(result); 7505 int best_match = abs(page_hint-_synctex_node_target_page(result)); 7506 synctex_node_p sibling; 7507 int match; 7508 synctex_counted_node_s cn = _synctex_vertically_sorted_v2(result); 7509 int count = cn.count; 7510 result = cn.node; 7511 while((sibling = next_sibling)) { 7512 /* What is next? Do not miss that step! */ 7513 next_sibling = __synctex_tree_reset_sibling(sibling); 7514 cn = _synctex_vertically_sorted_v2(sibling); 7515 count += cn.count; 7516 sibling = cn.node; 7517 match = abs(page_hint-_synctex_node_target_page(sibling)); 7518 if (match<best_match) { 7519 /* Order this node first */ 7520 __synctex_tree_set_sibling(sibling,result); 7521 result = sibling; 7522 best_match = match; 7523 } else /*if (match>=best_match)*/ { 7524 __synctex_tree_set_sibling(sibling,__synctex_tree_sibling(result)); 7525 __synctex_tree_set_sibling(result,sibling); 7526 } 7527 } 7528 return _synctex_iterator_new(result,count); 7529 } 7530 } 7531 # if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__) 7532 break; 7533 # else 7534 line += line_offset; 7535 line_offset=line_offset<0?-(line_offset-1):-(line_offset+1); 7536 if (line <= 0) { 7537 line += line_offset; 7538 line_offset=line_offset<0?-(line_offset-1):-(line_offset+1); 7539 } 7540 # endif 7541 } 7542 } 7543 } 7544 return NULL; 7545 } 7546 synctex_status_t synctex_display_query(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) { 7547 if (scanner) { 7548 synctex_iterator_free(scanner->iterator); 7549 scanner->iterator = synctex_iterator_new_display(scanner, name,line,column, page_hint); 7550 return synctex_iterator_count(scanner->iterator); 7551 } 7552 return SYNCTEX_STATUS_ERROR; 7553 } 7554 synctex_status_t synctex_edit_query(synctex_scanner_p scanner,int page,float h,float v) { 7555 if (scanner) { 7556 synctex_iterator_free(scanner->iterator); 7557 scanner->iterator = synctex_iterator_new_edit(scanner, page, h, v); 7558 return synctex_iterator_count(scanner->iterator); 7559 } 7560 return SYNCTEX_STATUS_ERROR; 7561 } 7562 /** 7563 * The next result of a query. 7564 */ 7565 synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner) { 7566 return scanner? synctex_iterator_next_result(scanner->iterator): NULL; 7567 } 7568 synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner) { 7569 return scanner? synctex_iterator_reset(scanner->iterator): SYNCTEX_STATUS_ERROR; 7570 } 7571 7572 synctex_node_p synctex_node_target(synctex_node_p node) { 7573 return _synctex_tree_target(node); 7574 } 7575 7576 # ifdef SYNCTEX_NOTHING 7577 # pragma mark - 7578 # pragma mark Geometric utilities 7579 # endif 7580 7581 /** Roughly speaking, this is: 7582 * node's h coordinate - hit point's h coordinate. 7583 * If node is to the right of the hit point, then this distance is positive, 7584 * if node is to the left of the hit point, this distance is negative. 7585 * If the argument is a pdf form reference, then the child is used and returned instead. 7586 * Last Revision: Mon Apr 24 07:05:27 UTC 2017 7587 */ 7588 static synctex_nd_s _synctex_point_h_ordered_distance_v2 7589 (synctex_point_p hit, synctex_node_p node) { 7590 synctex_nd_s nd = {node,INT_MAX}; 7591 if (node) { 7592 int min,med,max,width; 7593 switch(synctex_node_type(node)) { 7594 /* The distance between a point and a box is special. 7595 * It is not the euclidean distance, nor something similar. 7596 * We have to take into account the particular layout, 7597 * and the box hierarchy. 7598 * Given a box, there are 9 regions delimited by the lines of the edges of the box. 7599 * The origin being at the top left corner of the page, 7600 * we also give names to the vertices of the box. 7601 * 7602 * 1 | 2 | 3 7603 * ---A---B---> 7604 * 4 | 5 | 6 7605 * ---C---D---> 7606 * 7 | 8 | 9 7607 * v v 7608 */ 7609 case synctex_node_type_vbox: 7610 case synctex_node_type_void_vbox: 7611 case synctex_node_type_void_hbox: 7612 /* getting the box bounds, taking into account negative width, height and depth. */ 7613 width = _synctex_data_width(node); 7614 min = _synctex_data_h(node); 7615 max = min + (width>0?width:-width); 7616 /* We always have min <= max */ 7617 if (hit->h<min) { 7618 nd.distance = min - hit->h; /* regions 1+4+7, result is > 0 */ 7619 } else if (hit->h>max) { 7620 nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ 7621 } else { 7622 nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ 7623 } 7624 break; 7625 case synctex_node_type_proxy_vbox: 7626 /* getting the box bounds, taking into account negative width, height and depth. */ 7627 width = synctex_node_width(node); 7628 min = synctex_node_h(node); 7629 max = min + (width>0?width:-width); 7630 /* We always have min <= max */ 7631 if (hit->h<min) { 7632 nd.distance = min - hit->h; /* regions 1+4+7, result is > 0 */ 7633 } else if (hit->h>max) { 7634 nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ 7635 } else { 7636 nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ 7637 } 7638 break; 7639 case synctex_node_type_hbox: 7640 case synctex_node_type_proxy_hbox: 7641 /* getting the box bounds, taking into account negative width, height and depth. */ 7642 width = synctex_node_hbox_width(node); 7643 min = synctex_node_hbox_h(node); 7644 max = min + (width>0?width:-width); 7645 /* We always have min <= max */ 7646 if (hit->h<min) { 7647 nd.distance = min - hit->h; /* regions 1+4+7, result is > 0 */ 7648 } else if (hit->h>max) { 7649 nd.distance = max - hit->h; /* regions 3+6+9, result is < 0 */ 7650 } else { 7651 nd.distance = 0; /* regions 2+5+8, inside the box, except for vertical coordinates */ 7652 } 7653 break; 7654 case synctex_node_type_kern: 7655 /* IMPORTANT NOTICE: the location of the kern is recorded AFTER the move. 7656 * The distance to the kern is very special, 7657 * in general, there is no text material in the kern, 7658 * this is why we compute the offset relative to the closest edge of the kern.*/ 7659 max = _synctex_data_width(node); 7660 if (max<0) { 7661 min = _synctex_data_h(node); 7662 max = min - max; 7663 } else { 7664 min = -max; 7665 max = _synctex_data_h(node); 7666 min += max; 7667 } 7668 med = (min+max)/2; 7669 /* positive kern: '.' means text, '>' means kern offset 7670 * ............. 7671 * min>>>>med>>>>max 7672 * ............... 7673 * negative kern: '.' means text, '<' means kern offset 7674 * ............................ 7675 * min<<<<med<<<<max 7676 * ................................. 7677 * Actually, we do not take into account negative widths. 7678 * There is a problem for such situation when there is effectively overlapping text. 7679 * But this should be extremely rare. I guess that in that case, many different choices 7680 * could be made, one being in contradiction with the other. 7681 * It means that the best choice should be made according to the situation that occurs 7682 * most frequently. 7683 */ 7684 if (hit->h<min) { 7685 nd.distance = min - hit->h + 1; /* penalty to ensure other nodes are chosen first in case of overlapping ones */ 7686 } else if (hit->h>max) { 7687 nd.distance = max - hit->h - 1; /* same kind of penalty */ 7688 } else if (hit->h>med) { 7689 /* do things like if the node had 0 width and was placed at the max edge + 1*/ 7690 nd.distance = max - hit->h + 1; /* positive, the kern is to the right of the hit point */ 7691 } else { 7692 nd.distance = min - hit->h - 1; /* negative, the kern is to the left of the hit point */ 7693 } 7694 break; 7695 case synctex_node_type_rule:/* to do: special management */ 7696 case synctex_node_type_glue: 7697 case synctex_node_type_math: 7698 case synctex_node_type_boundary: 7699 case synctex_node_type_box_bdry: 7700 nd.distance = _synctex_data_h(node) - hit->h; 7701 break; 7702 case synctex_node_type_ref: 7703 nd.node = synctex_node_child(node); 7704 nd = _synctex_point_h_ordered_distance_v2(hit,nd.node); 7705 break; 7706 case synctex_node_type_proxy: 7707 case synctex_node_type_proxy_last: 7708 { 7709 /* shift the hit point to be relative to the proxy origin, 7710 * then compute the distance to the target 7711 */ 7712 synctex_point_s otherHit = *hit; 7713 otherHit.h -= _synctex_data_h(node); 7714 otherHit.v -= _synctex_data_v(node); 7715 nd.node = _synctex_tree_target(node); 7716 nd = _synctex_point_h_ordered_distance_v2(&otherHit,nd.node); 7717 nd.node = node; 7718 } 7719 default: 7720 break; 7721 } 7722 } 7723 return nd; 7724 } 7725 /** Roughly speaking, this is: 7726 * node's v coordinate - hit point's v coordinate. 7727 * If node is at the top of the hit point, then this distance is positive, 7728 * if node is at the bottom of the hit point, this distance is negative. 7729 */ 7730 static synctex_nd_s _synctex_point_v_ordered_distance_v2 7731 (synctex_point_p hit, synctex_node_p node) { 7732 synctex_nd_s nd = {node, INT_MAX}; 7733 int min,max,depth,height; 7734 switch(synctex_node_type(node)) { 7735 /* The distance between a point and a box is special. 7736 * It is not the euclidean distance, nor something similar. 7737 * We have to take into account the particular layout, 7738 * and the box hierarchy. 7739 * Given a box, there are 9 regions delimited by the lines of the edges of the box. 7740 * The origin being at the top left corner of the page, 7741 * we also give names to the vertices of the box. 7742 * 7743 * 1 | 2 | 3 7744 * ---A---B---> 7745 * 4 | 5 | 6 7746 * ---C---D---> 7747 * 7 | 8 | 9 7748 * v v 7749 */ 7750 case synctex_node_type_vbox: 7751 case synctex_node_type_void_vbox: 7752 case synctex_node_type_void_hbox: 7753 /* getting the box bounds, taking into account negative width, height and depth. */ 7754 min = synctex_node_v(node); 7755 max = min + _synctex_abs(_synctex_data_depth(node)); 7756 min -= _synctex_abs(_synctex_data_height(node)); 7757 /* We always have min <= max */ 7758 if (hit->v<min) { 7759 nd.distance = min - hit->v; /* regions 1+2+3, result is > 0 */ 7760 } else if (hit->v>max) { 7761 nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ 7762 } else { 7763 nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ 7764 } 7765 break; 7766 case synctex_node_type_proxy_vbox: 7767 /* getting the box bounds, taking into account negative width, height and depth. */ 7768 min = synctex_node_v(node); 7769 max = min + _synctex_abs(synctex_node_depth(node)); 7770 min -= _synctex_abs(synctex_node_height(node)); 7771 /* We always have min <= max */ 7772 if (hit->v<min) { 7773 nd.distance = min - hit->v; /* regions 1+2+3, result is > 0 */ 7774 } else if (hit->v>max) { 7775 nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ 7776 } else { 7777 nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ 7778 } 7779 break; 7780 case synctex_node_type_hbox: 7781 case synctex_node_type_proxy_hbox: 7782 /* getting the box bounds, taking into account negative height and depth. */ 7783 min = synctex_node_hbox_v(node); 7784 depth = synctex_node_hbox_depth(node); 7785 max = min + (depth>0?depth:-depth); 7786 height = synctex_node_hbox_height(node); 7787 min -= (height>0?height:-height); 7788 /* We always have min <= max */ 7789 if (hit->v<min) { 7790 nd.distance = min - hit->v; /* regions 1+2+3, result is > 0 */ 7791 } else if (hit->v>max) { 7792 nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ 7793 } else { 7794 nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ 7795 } 7796 break; 7797 case synctex_node_type_rule:/* to do: special management */ 7798 case synctex_node_type_kern: 7799 case synctex_node_type_glue: 7800 case synctex_node_type_math: 7801 min = _synctex_data_v(node); 7802 max = min + _synctex_abs(_synctex_data_depth(_synctex_tree_parent(node))); 7803 min -= _synctex_abs(_synctex_data_height(_synctex_tree_parent(node))); 7804 /* We always have min <= max */ 7805 if (hit->v<min) { 7806 nd.distance = min - hit->v; /* regions 1+2+3, result is > 0 */ 7807 } else if (hit->v>max) { 7808 nd.distance = max - hit->v; /* regions 7+8+9, result is < 0 */ 7809 } else { 7810 nd.distance = 0; /* regions 4.5.6, inside the box, except for horizontal coordinates */ 7811 } 7812 break; 7813 case synctex_node_type_ref: 7814 nd.node = synctex_node_child(node); 7815 nd = _synctex_point_v_ordered_distance_v2(hit,nd.node); 7816 break; 7817 case synctex_node_type_proxy: 7818 case synctex_node_type_proxy_last: 7819 { 7820 synctex_point_s otherHit = *hit; 7821 otherHit.h -= _synctex_data_h(node); 7822 otherHit.v -= _synctex_data_v(node); 7823 nd.node = _synctex_tree_target(node); 7824 nd = _synctex_point_v_ordered_distance_v2(&otherHit,nd.node); 7825 nd.node = node; 7826 } 7827 default: break; 7828 } 7829 return nd; 7830 } 7831 /** 7832 * The best is the one with the smallest area. 7833 * The area is width*height where width and height may be big. 7834 * So there is a real risk of overflow if we stick with ints. 7835 */ 7836 SYNCTEX_INLINE static synctex_node_p _synctex_smallest_container_v2(synctex_node_p node, synctex_node_p other_node) { 7837 long total_height, other_total_height; 7838 unsigned long area, other_area; 7839 long width = synctex_node_hbox_width(node); 7840 long other_width = synctex_node_hbox_width(other_node); 7841 if (width<0) { 7842 width = -width; 7843 } 7844 if (other_width<0) { 7845 other_width = -other_width; 7846 } 7847 total_height = _synctex_abs(synctex_node_hbox_depth(node)) + _synctex_abs(synctex_node_hbox_height(node)); 7848 other_total_height = _synctex_abs(synctex_node_hbox_depth(other_node)) + _synctex_abs(synctex_node_hbox_height(other_node)); 7849 area = total_height*width; 7850 other_area = other_total_height*other_width; 7851 if (area<other_area) { 7852 return node; 7853 } 7854 if (area>other_area) { 7855 return other_node; 7856 } 7857 if (_synctex_abs(_synctex_data_width(node))>_synctex_abs(_synctex_data_width(other_node))) { 7858 return node; 7859 } 7860 if (_synctex_abs(_synctex_data_width(node))<_synctex_abs(_synctex_data_width(other_node))) { 7861 return other_node; 7862 } 7863 if (total_height<other_total_height) { 7864 return node; 7865 } 7866 if (total_height>other_total_height) { 7867 return other_node; 7868 } 7869 return node; 7870 } 7871 7872 SYNCTEX_INLINE static synctex_bool_t _synctex_point_in_box_v2(synctex_point_p hit, synctex_node_p node) { 7873 if (node) { 7874 if (0 == _synctex_point_h_ordered_distance_v2(hit,node).distance 7875 && 0 == _synctex_point_v_ordered_distance_v2(hit,node).distance) { 7876 return synctex_YES; 7877 } 7878 } 7879 return synctex_NO; 7880 } 7881 7882 static int _synctex_distance_to_box_v2(synctex_point_p hit,synctex_box_p box) { 7883 /* The distance between a point and a box is special. 7884 * It is not the euclidean distance, nor something similar. 7885 * We have to take into account the particular layout, 7886 * and the box hierarchy. 7887 * Given a box, there are 9 regions delimited by the lines of the edges of the box. 7888 * The origin being at the top left corner of the page, 7889 * we also give names to the vertices of the box. 7890 * 7891 * 1 | 2 | 3 7892 * ---A---B---> 7893 * 4 | 5 | 6 7894 * ---C---D---> 7895 * 7 | 8 | 9 7896 * v v 7897 * In each region, there is a different formula. 7898 * In the end we have a continuous distance which may not be a mathematical distance but who cares. */ 7899 if (hit->v<box->min.v) { 7900 /* Regions 1, 2 or 3 */ 7901 if (hit->h<box->min.h) { 7902 /* This is region 1. The distance to the box is the L1 distance PA. */ 7903 return box->min.v - hit->v + box->min.h - hit->h;/* Integer overflow? probability epsilon */ 7904 } else if (hit->h<=box->max.h) { 7905 /* This is region 2. The distance to the box is the geometrical distance to the top edge. */ 7906 return box->min.v - hit->v; 7907 } else { 7908 /* This is region 3. The distance to the box is the L1 distance PB. */ 7909 return box->min.v - hit->v + hit->h - box->max.h; 7910 } 7911 } else if (hit->v<=box->max.v) { 7912 /* Regions 4, 5 or 6 */ 7913 if (hit->h<box->min.h) { 7914 /* This is region 4. The distance to the box is the geometrical distance to the left edge. */ 7915 return box->min.h - hit->h; 7916 } else if (hit->h<=box->max.h) { 7917 /* This is region 5. We are inside the box. */ 7918 return 0; 7919 } else { 7920 /* This is region 6. The distance to the box is the geometrical distance to the right edge. */ 7921 return hit->h - box->max.h; 7922 } 7923 } else { 7924 /* Regions 7, 8 or 9 */ 7925 if (hit->h<box->min.h) { 7926 /* This is region 7. The distance to the box is the L1 distance PC. */ 7927 return hit->v - box->max.v + box->min.h - hit->h; 7928 } else if (hit->h<=box->max.h) { 7929 /* This is region 8. The distance to the box is the geometrical distance to the top edge. */ 7930 return hit->v - box->max.v; 7931 } else { 7932 /* This is region 9. The distance to the box is the L1 distance PD. */ 7933 return hit->v - box->max.v + hit->h - box->max.h; 7934 } 7935 } 7936 } 7937 7938 /** 7939 * The distance from the hit point to the node. 7940 */ 7941 static int _synctex_point_node_distance_v2(synctex_point_p hit, synctex_node_p node) { 7942 int d = INT_MAX; 7943 if (node) { 7944 synctex_box_s box = {{0,0},{0,0}}; 7945 int dd = INT_MAX; 7946 switch(synctex_node_type(node)) { 7947 case synctex_node_type_vbox: 7948 box.min.h = _synctex_data_h(node); 7949 box.max.h = box.min.h + _synctex_abs(_synctex_data_width(node)); 7950 box.min.v = synctex_node_v(node); 7951 box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node)); 7952 box.min.v -= _synctex_abs(_synctex_data_height(node)); 7953 return _synctex_distance_to_box_v2(hit,&box); 7954 case synctex_node_type_proxy_vbox: 7955 box.min.h = synctex_node_h(node); 7956 box.max.h = box.min.h + _synctex_abs(synctex_node_width(node)); 7957 box.min.v = synctex_node_v(node); 7958 box.max.v = box.min.v + _synctex_abs(synctex_node_depth(node)); 7959 box.min.v -= _synctex_abs(synctex_node_height(node)); 7960 return _synctex_distance_to_box_v2(hit,&box); 7961 case synctex_node_type_hbox: 7962 case synctex_node_type_proxy_hbox: 7963 box.min.h = synctex_node_hbox_h(node); 7964 box.max.h = box.min.h + _synctex_abs(synctex_node_hbox_width(node)); 7965 box.min.v = synctex_node_hbox_v(node); 7966 box.max.v = box.min.v + _synctex_abs(synctex_node_hbox_depth(node)); 7967 box.min.v -= _synctex_abs(synctex_node_hbox_height(node)); 7968 return _synctex_distance_to_box_v2(hit,&box); 7969 case synctex_node_type_void_vbox: 7970 case synctex_node_type_void_hbox: 7971 /* best of distances from the left edge and right edge*/ 7972 box.min.h = _synctex_data_h(node); 7973 box.max.h = box.min.h; 7974 box.min.v = _synctex_data_v(node); 7975 box.max.v = box.min.v + _synctex_abs(_synctex_data_depth(node)); 7976 box.min.v -= _synctex_abs(_synctex_data_height(node)); 7977 d = _synctex_distance_to_box_v2(hit,&box); 7978 box.min.h = box.min.h + _synctex_abs(_synctex_data_width(node)); 7979 box.max.h = box.min.h; 7980 dd = _synctex_distance_to_box_v2(hit,&box); 7981 return d<dd ? d:dd; 7982 case synctex_node_type_kern: 7983 box.min.h = _synctex_data_h(node); 7984 box.max.h = box.min.h; 7985 box.max.v = _synctex_data_v(node); 7986 box.min.v = box.max.v - _synctex_abs(_synctex_data_height(_synctex_tree_parent(node))); 7987 d = _synctex_distance_to_box_v2(hit,&box); 7988 box.min.h -= _synctex_data_width(node); 7989 box.max.h = box.min.h; 7990 dd = _synctex_distance_to_box_v2(hit,&box); 7991 return d<dd ? d:dd; 7992 case synctex_node_type_glue: 7993 case synctex_node_type_math: 7994 case synctex_node_type_boundary: 7995 case synctex_node_type_box_bdry: 7996 box.min.h = _synctex_data_h(node); 7997 box.max.h = box.min.h; 7998 box.max.v = _synctex_data_v(node); 7999 box.min.v = box.max.v - _synctex_abs(_synctex_data_height(_synctex_tree_parent(node))); 8000 return _synctex_distance_to_box_v2(hit,&box); 8001 case synctex_node_type_proxy: 8002 case synctex_node_type_proxy_last: 8003 { 8004 synctex_point_s otherHit = *hit; 8005 otherHit.h -= _synctex_data_h(node); 8006 otherHit.v -= _synctex_data_v(node); 8007 return _synctex_point_node_distance_v2(&otherHit, _synctex_tree_target(node)); 8008 } 8009 default: break; 8010 } 8011 } 8012 return d; 8013 } 8014 static synctex_node_p _synctex_eq_deepest_container_v2(synctex_point_p hit, synctex_node_p node) { 8015 if (node) { 8016 /**/ 8017 synctex_node_p child; 8018 if ((child = synctex_node_child(node))) { 8019 /* Non void hbox or vbox, form ref or proxy */ 8020 /* We go deep first because some boxes have 0 dimensions 8021 * despite they do contain some black material. 8022 */ 8023 do { 8024 if ((_synctex_point_in_box_v2(hit,child))) { 8025 synctex_node_p deep = _synctex_eq_deepest_container_v2(hit,child); 8026 if (deep) { 8027 /* One of the children contains the hit. */ 8028 return deep; 8029 } 8030 } 8031 } while((child = synctex_node_sibling(child))); 8032 /* is the hit point inside the box? */ 8033 if (synctex_node_type(node) == synctex_node_type_vbox 8034 || synctex_node_type(node) == synctex_node_type_proxy_vbox) { 8035 /* For vboxes we try to use some node inside. 8036 * Walk through the list of siblings until we find the closest one. 8037 * Only consider siblings with children inside. */ 8038 if ((child = _synctex_tree_child(node))) { 8039 synctex_nd_s best = SYNCTEX_ND_0; 8040 do { 8041 if (_synctex_tree_child(child)) { 8042 int d = _synctex_point_node_distance_v2(hit,child); 8043 if (d <= best.distance) { 8044 best = (synctex_nd_s){child, d}; 8045 } 8046 } 8047 } while((child = __synctex_tree_sibling(child))); 8048 if (best.node) { 8049 return best.node; 8050 } 8051 } 8052 } 8053 if (_synctex_point_in_box_v2(hit,node)) { 8054 return node; 8055 } 8056 } 8057 } 8058 return NULL; 8059 } 8060 static synctex_nd_s _synctex_eq_deepest_container_v3(synctex_point_p hit, synctex_node_p node) { 8061 if (node) { 8062 synctex_node_p child = NULL; 8063 if ((child = synctex_node_child(node))) { 8064 /* Non void hbox, vbox, box proxy or form ref */ 8065 /* We go deep first because some boxes have 0 dimensions 8066 * despite they do contain some black material. 8067 */ 8068 do { 8069 synctex_nd_s deep = _synctex_eq_deepest_container_v3(hit, child); 8070 if (deep.node) { 8071 /* One of the children contains the hit-> */ 8072 return deep; 8073 } 8074 } while((child = synctex_node_sibling(child))); 8075 /* For vboxes we try to use some node inside. 8076 * Walk through the list of siblings until we find the closest one. 8077 * Only consider siblings with children inside. */ 8078 if (synctex_node_type(node) == synctex_node_type_vbox 8079 || synctex_node_type(node) == synctex_node_type_proxy_vbox) { 8080 if ((child = synctex_node_child(node))) { 8081 synctex_nd_s best = SYNCTEX_ND_0; 8082 do { 8083 if (synctex_node_child(child)) { 8084 int d = _synctex_point_node_distance_v2(hit,child); 8085 if (d < best.distance) { 8086 best = (synctex_nd_s){child,d}; 8087 } 8088 } 8089 } while((child = synctex_node_sibling(child))); 8090 if (best.node) { 8091 return best; 8092 } 8093 } 8094 } 8095 /* is the hit point inside the box? */ 8096 if (_synctex_point_in_box_v2(hit,node)) { 8097 return (synctex_nd_s){node, 0}; 8098 } 8099 } 8100 } 8101 return SYNCTEX_ND_0; 8102 } 8103 8104 /* Compares the locations of the hit point with the locations of 8105 * the various nodes contained in the box. 8106 * As it is an horizontal box, we only compare horizontal coordinates. 8107 */ 8108 SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v2(synctex_point_p hitP, synctex_node_p node) { 8109 synctex_nd_s childd = SYNCTEX_ND_0; 8110 synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; 8111 if ((childd.node = synctex_node_child(node))) { 8112 synctex_nd_s nd = SYNCTEX_ND_0; 8113 do { 8114 childd = _synctex_point_h_ordered_distance_v2(hitP,childd.node); 8115 if (childd.distance > 0) { 8116 /* node is to the right of the hit point. 8117 * We compare node and the previously recorded one, through the recorded distance. 8118 * If the nodes have the same tag, prefer the one with the smallest line number, 8119 * if the nodes also have the same line number, prefer the one with the smallest column. */ 8120 if (nds.r.distance > childd.distance) { 8121 nds.r = childd; 8122 } else if (nds.r.distance == childd.distance && nds.r.node) { 8123 if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(childd.node) 8124 && (_synctex_data_line(nds.r.node) > _synctex_data_line(childd.node) 8125 || (_synctex_data_line(nds.r.node) == _synctex_data_line(childd.node) 8126 && _synctex_data_column(nds.r.node) > _synctex_data_column(childd.node)))) { 8127 nds.r = childd; 8128 } 8129 } 8130 } else if (childd.distance == 0) { 8131 /* hit point is inside node. */ 8132 if (_synctex_tree_child(childd.node)) { 8133 return _synctex_eq_get_closest_children_in_box_v2(hitP, childd.node); 8134 } 8135 nds.l = childd; 8136 } else { /* here childd.distance < 0, the hit point is to the right of node */ 8137 childd.distance = -childd.distance; 8138 if (nds.l.distance > childd.distance) { 8139 nds.l = childd; 8140 } else if (nds.l.distance == childd.distance && nds.l.node) { 8141 if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(childd.node) 8142 && (_synctex_data_line(nds.l.node) > _synctex_data_line(childd.node) 8143 || (_synctex_data_line(nds.l.node) == _synctex_data_line(childd.node) 8144 && _synctex_data_column(nds.l.node) > _synctex_data_column(childd.node)))) { 8145 nds.l = childd; 8146 } 8147 } 8148 } 8149 } while((childd.node = synctex_node_sibling(childd.node))); 8150 if (nds.l.node) { 8151 /* the left node is new, try to narrow the result */ 8152 if ((nd = _synctex_eq_deepest_container_v3(hitP,nds.l.node)).node) { 8153 nds.l = nd; 8154 } 8155 if((nd = __synctex_closest_deep_child_v2(hitP,nds.l.node)).node) { 8156 nds.l.node = nd.node; 8157 } 8158 } 8159 if (nds.r.node) { 8160 /* the right node is new, try to narrow the result */ 8161 if ((nd = _synctex_eq_deepest_container_v3(hitP,nds.r.node)).node) { 8162 nds.r = nd; 8163 } 8164 if((nd = __synctex_closest_deep_child_v2(hitP,nds.r.node)).node) { 8165 nds.r.node = nd.node; 8166 } 8167 } 8168 } 8169 return nds; 8170 } 8171 8172 #if 0 8173 SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_hbox_v3(synctex_point_p hitP, synctex_node_p nodeP) { 8174 synctex_nd_s nd = SYNCTEX_ND_0; 8175 synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; 8176 if ((nd.node = _synctex_tree_child(nodeP))) { 8177 do { 8178 nd = _synctex_point_h_ordered_distance_v2(hitP,nd.node); 8179 if (nd.distance > 0) { 8180 /* node is to the right of the hit point. 8181 * We compare node and the previously recorded one, through the recorded distance. 8182 * If the nodes have the same tag, prefer the one with the smallest line number, 8183 * if the nodes also have the same line number, prefer the one with the smallest column. */ 8184 if (nds.r.distance > nd.distance) { 8185 nds.r = nd; 8186 } else if (nds.r.distance == nd.distance && nds.r.node) { 8187 if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node) 8188 && (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node) 8189 || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node) 8190 && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) { 8191 nds.r = nd; 8192 } 8193 } 8194 } else if (nd.distance == 0) { 8195 /* hit point is inside node. */ 8196 nds.l = nd; 8197 } else { /* here nd.d < 0, the hit point is to the right of node */ 8198 nd.distance = -nd.distance; 8199 if (nds.l.distance > nd.distance) { 8200 nds.l = nd; 8201 } else if (nds.l.distance == nd.distance && nds.l.node) { 8202 if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node) 8203 && (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node) 8204 || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node) 8205 && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) { 8206 nds.l = nd; 8207 } 8208 } 8209 } 8210 } while((nd.node = __synctex_tree_sibling(nd.node))); 8211 if (nds.l.node) { 8212 /* the left node is new, try to narrow the result */ 8213 if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) { 8214 nds.l.node = nd.node; 8215 } 8216 if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) { 8217 nds.l.node = nd.node; 8218 } 8219 } 8220 if (nds.r.node) { 8221 /* the right node is new, try to narrow the result */ 8222 if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) { 8223 nds.r.node = nd.node; 8224 } 8225 if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) { 8226 nds.r.node = nd.node; 8227 } 8228 } 8229 } 8230 return nds; 8231 } 8232 #endif 8233 SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_vbox_v2(synctex_point_p hitP, synctex_node_p nodeP) { 8234 SYNCTEX_UNUSED(nodeP) 8235 synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; 8236 synctex_nd_s nd = SYNCTEX_ND_0; 8237 if ((nd.node = synctex_node_child(nd.node))) { 8238 do { 8239 nd = _synctex_point_v_ordered_distance_v2(hitP,nd.node); 8240 /* this is what makes the difference with the h version above */ 8241 if (nd.distance > 0) { 8242 /* node is to the top of the hit point (below because TeX is oriented from top to bottom. 8243 * We compare node and the previously recorded one, through the recorded distance. 8244 * If the nodes have the same tag, prefer the one with the smallest line number, 8245 * if the nodes also have the same line number, prefer the one with the smallest column. */ 8246 if (nds.r.distance > nd.distance) { 8247 nds.r = nd; 8248 } else if (nds.r.distance == nd.distance && nds.r.node) { 8249 if (_synctex_data_tag(nds.r.node) == _synctex_data_tag(nd.node) 8250 && (_synctex_data_line(nds.r.node) > _synctex_data_line(nd.node) 8251 || (_synctex_data_line(nds.r.node) == _synctex_data_line(nd.node) 8252 && _synctex_data_column(nds.r.node) > _synctex_data_column(nd.node)))) { 8253 nds.r = nd; 8254 } 8255 } 8256 } else if (nd.distance == 0) { 8257 nds.l = nd; 8258 } else { /* here nd < 0 */ 8259 nd.distance = -nd.distance; 8260 if (nds.l.distance > nd.distance) { 8261 nds.l = nd; 8262 } else if (nds.l.distance == nd.distance && nds.l.node) { 8263 if (_synctex_data_tag(nds.l.node) == _synctex_data_tag(nd.node) 8264 && (_synctex_data_line(nds.l.node) > _synctex_data_line(nd.node) 8265 || (_synctex_data_line(nds.l.node) == _synctex_data_line(nd.node) 8266 && _synctex_data_column(nds.l.node) > _synctex_data_column(nd.node)))) { 8267 nds.l = nd; 8268 } 8269 } 8270 } 8271 } while((nd.node = synctex_node_sibling(nd.node))); 8272 if (nds.l.node) { 8273 if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.l.node))) { 8274 nds.l.node = nd.node; 8275 } 8276 if((nd = _synctex_eq_closest_child_v2(hitP,nds.l.node)).node) { 8277 nds.l.node = nd.node; 8278 } 8279 } 8280 if (nds.r.node) { 8281 if ((nd.node = _synctex_eq_deepest_container_v2(hitP,nds.r.node))) { 8282 nds.r.node = nd.node; 8283 } 8284 if((nd = _synctex_eq_closest_child_v2(hitP,nds.r.node)).node) { 8285 nds.r.node = nd.node; 8286 } 8287 } 8288 } 8289 return nds; 8290 } 8291 8292 /** 8293 * Get the child closest to the hit point. 8294 * - parameter: hit point 8295 * - parameter: containing node 8296 * - returns: the child and the distance to the hit point. 8297 * SYNCTEX_ND_0 if the parameter node has no children. 8298 * - note: recursive call. 8299 */ 8300 static synctex_nd_s __synctex_closest_deep_child_v2(synctex_point_p hitP, synctex_node_p node) { 8301 synctex_nd_s best = SYNCTEX_ND_0; 8302 synctex_node_p child = NULL; 8303 if ((child = synctex_node_child(node))) { 8304 #if defined(SYNCTEX_DEBUG) 8305 printf("Closest deep child on box at line %i\n", 8306 SYNCTEX_LINEINDEX(node)); 8307 #endif 8308 do { 8309 #if SYNCTEX_DEBUG>500 8310 synctex_node_display(child); 8311 #endif 8312 synctex_nd_s nd = SYNCTEX_ND_0; 8313 if (_synctex_node_is_box(child)) { 8314 nd = __synctex_closest_deep_child_v2(hitP,child); 8315 } else { 8316 nd = (synctex_nd_s) {child, _synctex_point_node_distance_v2(hitP,child)}; 8317 } 8318 if (nd.distance < best.distance ||(nd.distance == best.distance 8319 && synctex_node_type(nd.node) != synctex_node_type_kern)) { 8320 #if defined(SYNCTEX_DEBUG) 8321 if(nd.node) { 8322 printf("New best %i<=%i line %i\n",nd.distance, 8323 best.distance,SYNCTEX_LINEINDEX(nd.node)); 8324 } 8325 #endif 8326 best = nd; 8327 } 8328 } while((child = synctex_node_sibling(child))); 8329 #if defined(SYNCTEX_DEBUG) 8330 if(best.node) { 8331 printf("Found new best %i line %i\n",best.distance,SYNCTEX_LINEINDEX(best.node)); 8332 } 8333 #endif 8334 } 8335 return best; 8336 } 8337 8338 /** 8339 * Return the closest child. 8340 * - parameter: a pointer to the hit point, 8341 * - parameter: the container 8342 * - return: SYNCTEX_ND_0 if node has no child, 8343 * the __synctex_closest_deep_child_v2 otherwise. 8344 */ 8345 static synctex_nd_s _synctex_eq_closest_child_v2(synctex_point_p hitP, synctex_node_p node) { 8346 synctex_nd_s nd = SYNCTEX_ND_0; 8347 if (_synctex_node_is_box(node)) { 8348 nd = __synctex_closest_deep_child_v2(hitP, node); 8349 if (_synctex_node_is_box(nd.node)) { 8350 synctex_node_p child = NULL; 8351 if ((child = synctex_node_child(nd.node))) { 8352 synctex_nd_s best = {child,_synctex_point_node_distance_v2(hitP,child)}; 8353 while((child = synctex_node_sibling(child))) { 8354 int d = _synctex_point_node_distance_v2(hitP,child); 8355 if (d < best.distance) { 8356 best = (synctex_nd_s){child,d}; 8357 } else if (d == best.distance && synctex_node_type(child) != synctex_node_type_kern) { 8358 best.node = child; 8359 } 8360 } 8361 return best; 8362 } 8363 } 8364 return nd; 8365 } 8366 return SYNCTEX_ND_0; 8367 } 8368 SYNCTEX_INLINE static synctex_nd_lr_s _synctex_eq_get_closest_children_in_box_v2(synctex_point_p hitP, synctex_node_p node) { 8369 synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0}; 8370 if(_synctex_tree_has_child(node)) { /* node != NULL */ 8371 if (node->class_->type==synctex_node_type_hbox || 8372 node->class_->type==synctex_node_type_proxy_hbox) { 8373 return __synctex_eq_get_closest_children_in_hbox_v2(hitP,node); 8374 } else { 8375 return __synctex_eq_get_closest_children_in_vbox_v2(hitP,node); 8376 } 8377 } 8378 return nds; 8379 } 8380 8381 #ifndef SYNCTEX_NO_UPDATER 8382 8383 # ifdef SYNCTEX_NOTHING 8384 # pragma mark - 8385 # pragma mark Updater 8386 # endif 8387 8388 typedef int (*synctex_print_f)(synctex_updater_p, const char * , ...); /* print formatted to either FILE * or gzFile */ 8389 typedef void (*synctex_close_f)(synctex_updater_p); /* close FILE * or gzFile */ 8390 8391 # define SYNCTEX_BITS_PER_BYTE 8 8392 8393 typedef union { 8394 gzFile as_gzFile; 8395 FILE * as_FILE_p; 8396 void * as_ptr; 8397 } syncex_file_u; 8398 8399 struct synctex_updater_t { 8400 syncex_file_u file; 8401 synctex_print_f print; 8402 synctex_close_f close; 8403 int length; /* the number of chars appended */ 8404 }; 8405 8406 static int _synctex_updater_print(synctex_updater_p updater, const char * format, ...) { 8407 int result = 0; 8408 if (updater) { 8409 va_list va; 8410 va_start(va, format); 8411 result = vfprintf(updater->file.as_FILE_p, 8412 format, 8413 va); 8414 va_end(va); 8415 } 8416 return result; 8417 } 8418 #if defined(_MSC_VER) 8419 #include <stdio.h> 8420 #include <stdlib.h> 8421 #include <stdarg.h> 8422 8423 static int vasprintf(char **ret, 8424 const char *format, 8425 va_list ap) 8426 { 8427 int len; 8428 len = _vsnprintf(NULL, 0, format, ap); 8429 if (len < 0) return -1; 8430 *ret = malloc(len + 1); 8431 if (!*ret) return -1; 8432 _vsnprintf(*ret, len+1, format, ap); 8433 (*ret)[len] = '\0'; 8434 return len; 8435 } 8436 8437 #endif 8438 8439 /** 8440 * gzvprintf is not available until OSX 10.10 8441 */ 8442 static int _synctex_updater_print_gz(synctex_updater_p updater, const char * format, ...) { 8443 int result = 0; 8444 if (updater) { 8445 char * buffer; 8446 va_list va; 8447 va_start(va, format); 8448 if (vasprintf(&buffer, format, va) < 0) { 8449 _synctex_error("Out of memory..."); 8450 } else if ((result = (int)strlen(buffer))) { 8451 result = gzwrite(updater->file.as_gzFile, buffer, (unsigned)result); 8452 } 8453 va_end(va); 8454 free(buffer); 8455 } 8456 return result; 8457 } 8458 8459 static void _synctex_updater_close(synctex_updater_p updater) { 8460 if (updater) { 8461 fclose(updater->file.as_FILE_p); 8462 } 8463 } 8464 8465 static void _synctex_updater_close_gz(synctex_updater_p updater) { 8466 if (updater) { 8467 gzclose(updater->file.as_gzFile); 8468 } 8469 } 8470 8471 synctex_updater_p synctex_updater_new_with_output_file(const char * output, const char * build_directory) { 8472 synctex_updater_p updater = NULL; 8473 const char * mode = NULL; 8474 synctex_open_s open; 8475 /* prepare the updater, the memory is the only one dynamically allocated */ 8476 updater = (synctex_updater_p)_synctex_malloc(sizeof(synctex_updater_s)); 8477 if (NULL == updater) { 8478 _synctex_error("! synctex_updater_new_with_file: malloc problem"); 8479 return NULL; 8480 } 8481 open = _synctex_open_v2(output,build_directory,0,synctex_ADD_QUOTES); 8482 if (open.status < SYNCTEX_STATUS_OK) { 8483 open = _synctex_open_v2(output,build_directory,0,synctex_DONT_ADD_QUOTES); 8484 if (open.status < SYNCTEX_STATUS_OK) { 8485 return_on_error: 8486 _synctex_free(updater); 8487 return updater = NULL; 8488 } 8489 } 8490 /* OK, the file exists, we close it and reopen it with the correct mode. 8491 * The receiver is now the owner of the "synctex" variable. */ 8492 gzclose(open.file); 8493 updater->file.as_ptr = NULL; 8494 mode = _synctex_get_io_mode_name(open.io_mode|synctex_io_append_mask);/* either "a" or "ab", depending on the file extension */ 8495 if (open.io_mode&synctex_io_gz_mask) { 8496 if (NULL == (updater->file.as_FILE_p = fopen(open.synctex,mode))) { 8497 no_write_error: 8498 _synctex_error("! synctex_updater_new_with_file: Can't append to %s",open.synctex); 8499 free(open.synctex); 8500 goto return_on_error; 8501 } 8502 updater->print = &_synctex_updater_print; 8503 updater->close = &_synctex_updater_close; 8504 } else { 8505 if (NULL == (updater->file.as_gzFile = gzopen(open.synctex,mode))) { 8506 goto no_write_error; 8507 } 8508 updater->print = &_synctex_updater_print_gz; 8509 updater->close = &_synctex_updater_close_gz; 8510 } 8511 printf("SyncTeX: updating %s...",open.synctex); 8512 _synctex_free(open.synctex); 8513 return updater; 8514 } 8515 8516 void synctex_updater_append_magnification(synctex_updater_p updater, char * magnification){ 8517 if (NULL==updater) { 8518 return; 8519 } 8520 if (magnification && strlen(magnification)) { 8521 updater->length += 8522 updater->print(updater,"Magnification:%s\n",magnification); 8523 } 8524 } 8525 8526 void synctex_updater_append_x_offset(synctex_updater_p updater, char * x_offset){ 8527 if (NULL==updater) { 8528 return; 8529 } 8530 if (x_offset && strlen(x_offset)) { 8531 updater->length += updater->print(updater,"X Offset:%s\n",x_offset); 8532 } 8533 } 8534 8535 void synctex_updater_append_y_offset(synctex_updater_p updater, char * y_offset){ 8536 if (NULL==updater) { 8537 return; 8538 } 8539 if (y_offset && strlen(y_offset)) { 8540 updater->length += updater->print(updater,"Y Offset:%s\n",y_offset); 8541 } 8542 } 8543 8544 void synctex_updater_free(synctex_updater_p updater){ 8545 if (NULL==updater) { 8546 return; 8547 } 8548 if (updater->length>0) { 8549 updater->print(updater,"!%i\n",updater->length); 8550 } 8551 updater->close(updater); 8552 _synctex_free(updater); 8553 printf("... done.\n"); 8554 return; 8555 } 8556 #endif 8557 8558 #if defined(SYNCTEX_TESTING) 8559 # ifdef SYNCTEX_NOTHING 8560 # pragma mark - 8561 # pragma mark Testers 8562 # endif 8563 static int _synctex_input_copy_name(synctex_node_p input, char * name) { 8564 char * copy = _synctex_malloc(strlen(name)+1); 8565 memcpy(copy,name,strlen(name)+1); 8566 _synctex_data_set_name(input,copy); 8567 return 0; 8568 } 8569 int synctex_test_setup_scanner_sheets_421(synctex_scanner_p scanner) { 8570 int TC = 0; 8571 synctex_node_p sheet = synctex_node_new(scanner,synctex_node_type_sheet); 8572 _synctex_data_set_page(sheet,4); 8573 SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==4,""); 8574 synctex_node_free(scanner->sheet); 8575 scanner->sheet = sheet; 8576 sheet = synctex_node_new(scanner,synctex_node_type_sheet); 8577 _synctex_data_set_page(sheet,2); 8578 SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==2,""); 8579 __synctex_tree_set_sibling(sheet, scanner->sheet); 8580 scanner->sheet = sheet; 8581 sheet = synctex_node_new(scanner,synctex_node_type_sheet); 8582 _synctex_data_set_page(sheet,1); 8583 SYNCTEX_TEST_BODY(TC, _synctex_data_page(sheet)==1,""); 8584 __synctex_tree_set_sibling(sheet, scanner->sheet); 8585 scanner->sheet = sheet; 8586 return TC; 8587 } 8588 int synctex_test_input(synctex_scanner_p scanner) { 8589 int TC = 0; 8590 synctex_node_p input = synctex_node_new(scanner,synctex_node_type_input); 8591 _synctex_data_set_tag(input,421); 8592 SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==421,""); 8593 _synctex_data_set_tag(input,124); 8594 SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==124,""); 8595 _synctex_data_set_line(input,421); 8596 SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==421,""); 8597 _synctex_data_set_line(input,214); 8598 SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==214,""); 8599 _synctex_data_set_line(input,214); 8600 SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==214,""); 8601 _synctex_input_copy_name(input,"214"); 8602 SYNCTEX_TEST_BODY(TC, 0==memcmp(_synctex_data_name(input),"214",4),""); 8603 _synctex_input_copy_name(input,"421421"); 8604 8605 SYNCTEX_TEST_BODY(TC, 8606 0==memcmp(_synctex_data_name(input), 8607 "421421", 8608 4), 8609 ""); 8610 synctex_node_free(input); 8611 return TC; 8612 } 8613 int synctex_test_proxy(synctex_scanner_p scanner) { 8614 int TC = 0; 8615 synctex_node_p proxy = synctex_node_new(scanner,synctex_node_type_proxy); 8616 synctex_node_p target = synctex_node_new(scanner,synctex_node_type_rule); 8617 _synctex_tree_set_target(proxy,target); 8618 _synctex_data_set_tag(target,421); 8619 SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==421,""); 8620 SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==421,""); 8621 SYNCTEX_TEST_BODY(TC, synctex_node_tag(proxy)==421,""); 8622 synctex_node_free(proxy); 8623 synctex_node_free(target); 8624 return TC; 8625 } 8626 int synctex_test_handle(synctex_scanner_p scanner) { 8627 int TC = 0; 8628 synctex_node_p handle = synctex_node_new(scanner,synctex_node_type_handle); 8629 synctex_node_p proxy = synctex_node_new(scanner, synctex_node_type_proxy); 8630 synctex_node_p target = synctex_node_new(scanner,synctex_node_type_rule); 8631 _synctex_tree_set_target(handle,target); 8632 _synctex_data_set_tag(target,421); 8633 SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==421,""); 8634 SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==421,""); 8635 SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle)==421,""); 8636 _synctex_data_set_line(target,214); 8637 SYNCTEX_TEST_BODY(TC, _synctex_data_line(target)==214,""); 8638 SYNCTEX_TEST_BODY(TC, synctex_node_line(target)==214,""); 8639 SYNCTEX_TEST_BODY(TC, synctex_node_line(handle)==214,""); 8640 _synctex_data_set_column(target,142); 8641 SYNCTEX_TEST_BODY(TC, _synctex_data_column(target)==142,""); 8642 SYNCTEX_TEST_BODY(TC, synctex_node_column(target)==142,""); 8643 SYNCTEX_TEST_BODY(TC, synctex_node_column(handle)==142,""); 8644 _synctex_tree_set_target(proxy,target); 8645 _synctex_tree_set_target(handle,proxy); 8646 _synctex_data_set_tag(target,412); 8647 SYNCTEX_TEST_BODY(TC, _synctex_data_tag(target)==412,""); 8648 SYNCTEX_TEST_BODY(TC, synctex_node_tag(target)==412,""); 8649 SYNCTEX_TEST_BODY(TC, synctex_node_tag(handle)==412,""); 8650 _synctex_data_set_line(target,124); 8651 SYNCTEX_TEST_BODY(TC, _synctex_data_line(target)==124,""); 8652 SYNCTEX_TEST_BODY(TC, synctex_node_line(target)==124,""); 8653 SYNCTEX_TEST_BODY(TC, synctex_node_line(handle)==124,""); 8654 _synctex_data_set_column(target,241); 8655 SYNCTEX_TEST_BODY(TC, _synctex_data_column(target)==241,""); 8656 SYNCTEX_TEST_BODY(TC, synctex_node_column(target)==241,""); 8657 SYNCTEX_TEST_BODY(TC, synctex_node_column(handle)==241,""); 8658 synctex_node_free(handle); 8659 synctex_node_free(proxy); 8660 synctex_node_free(target); 8661 return TC; 8662 } 8663 int synctex_test_setup_scanner_input(synctex_scanner_p scanner) { 8664 int TC = 0; 8665 synctex_node_p input = synctex_node_new(scanner,synctex_node_type_input); 8666 _synctex_data_set_tag(input,4); 8667 _synctex_input_copy_name(input,"21"); 8668 _synctex_data_set_line(input,421); 8669 synctex_node_free(scanner->input); 8670 scanner->input = input; 8671 SYNCTEX_TEST_BODY(TC, _synctex_data_tag(input)==4,""); 8672 SYNCTEX_TEST_BODY(TC, strcmp(_synctex_data_name(input),"21")==0,""); 8673 SYNCTEX_TEST_BODY(TC, _synctex_data_line(input)==421,""); 8674 return TC; 8675 } 8676 int synctex_test_setup_nodes(synctex_scanner_p scanner, synctex_node_r nodes) { 8677 int TC = 0; 8678 int n; 8679 for (n=0;n<synctex_node_number_of_types;++n) { 8680 nodes[n] = synctex_node_new(scanner,n); 8681 SYNCTEX_TEST_BODY(TC, nodes[n]!=NULL,""); 8682 } 8683 return TC; 8684 } 8685 int synctex_test_teardown_nodes(synctex_scanner_p scanner, synctex_node_r nodes) { 8686 int n; 8687 for (n=0;n<synctex_node_number_of_types;++n) { 8688 synctex_node_free(nodes[n]); 8689 nodes[n]=NULL; 8690 } 8691 return 1; 8692 } 8693 int synctex_test_tree(synctex_scanner_p scanner) { 8694 int TC = 0; 8695 synctex_node_p nodes1[synctex_node_number_of_types]; 8696 synctex_node_p nodes2[synctex_node_number_of_types]; 8697 synctex_node_p nodes3[synctex_node_number_of_types]; 8698 int i,j; 8699 TC += synctex_test_setup_nodes(scanner,nodes1); 8700 TC += synctex_test_setup_nodes(scanner,nodes2); 8701 TC += synctex_test_setup_nodes(scanner,nodes3); 8702 /* Every node has a sibling */ 8703 for (i=0;i<synctex_node_number_of_types;++i) { 8704 for (j=0;j<synctex_node_number_of_types;++j) { 8705 _synctex_tree_set_sibling(nodes1[i],nodes2[i]); 8706 SYNCTEX_TEST_BODY(TC, nodes2[i]==synctex_node_sibling(nodes1[i]),""); 8707 } 8708 } 8709 synctex_test_teardown_nodes(scanner,nodes3); 8710 synctex_test_teardown_nodes(scanner,nodes2); 8711 synctex_test_teardown_nodes(scanner,nodes1); 8712 return TC; 8713 } 8714 int synctex_test_page(synctex_scanner_p scanner) { 8715 int TC = synctex_test_setup_scanner_sheets_421(scanner); 8716 synctex_node_p sheet = scanner->sheet; 8717 synctex_node_p node = synctex_node_new(scanner,synctex_node_type_rule); 8718 _synctex_data_set_tag(node,4); 8719 _synctex_data_set_line(node,21); 8720 synctex_node_free(_synctex_node_set_child(sheet,node)); 8721 SYNCTEX_TEST_BODY(TC, synctex_node_page(node)==synctex_node_page(sheet),""); 8722 return TC; 8723 } 8724 int synctex_test_display_query(synctex_scanner_p scanner) { 8725 int TC = synctex_test_setup_scanner_sheets_421(scanner); 8726 synctex_node_p sheet = scanner->sheet; 8727 synctex_node_p node = synctex_node_new(scanner,synctex_node_type_rule); 8728 _synctex_data_set_tag(node,4); 8729 _synctex_data_set_line(node,21); 8730 synctex_node_free(_synctex_node_set_child(sheet,node)); 8731 SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); 8732 __synctex_node_make_friend_tlc(node); 8733 SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25)==node,""); 8734 sheet = __synctex_tree_sibling(sheet); 8735 node = synctex_node_new(scanner,synctex_node_type_rule); 8736 _synctex_data_set_tag(node,4); 8737 _synctex_data_set_line(node,21); 8738 synctex_node_free(_synctex_node_set_child(sheet,node)); 8739 SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); 8740 __synctex_node_make_friend_tlc(node); 8741 SYNCTEX_TEST_BODY(TC, _synctex_scanner_friend(scanner, 25)==node,""); 8742 sheet = __synctex_tree_sibling(sheet); 8743 node = synctex_node_new(scanner,synctex_node_type_rule); 8744 _synctex_data_set_tag(node,4); 8745 _synctex_data_set_line(node,21); 8746 synctex_node_free(_synctex_node_set_child(sheet,node)); 8747 SYNCTEX_TEST_BODY(TC, node==synctex_node_child(sheet),""); 8748 __synctex_node_make_friend_tlc(node); 8749 SYNCTEX_TEST_BODY(TC, (_synctex_scanner_friend(scanner, 25)==node),""); 8750 synctex_test_setup_scanner_input(scanner); 8751 scanner->flags.has_parsed = synctex_YES; 8752 #if 1 8753 SYNCTEX_TEST_BODY(TC, (synctex_display_query(scanner,"21",21,4,-1)==3),""); 8754 #endif 8755 return TC; 8756 } 8757 typedef struct { 8758 int s; /* status */ 8759 char n[25]; /* name */ 8760 } synctex_test_sn_s; 8761 8762 synctex_test_sn_s synctex_test_tmp_sn(char * content) { 8763 synctex_test_sn_s sn = {0, "/tmp/test.XXXXXX.synctex"}; 8764 FILE *sfp; 8765 int fd = mkstemps(sn.n,8); 8766 if (fd < 0) { 8767 fprintf(stderr, "%s: %s\n", sn.n, strerror(errno)); 8768 sn.s = -1; 8769 return sn; 8770 } 8771 if ((sfp = fdopen(fd, "w+")) == NULL) { 8772 unlink(sn.n); 8773 close(fd); 8774 fprintf(stderr, "%s: %s\n", sn.n, strerror(errno)); 8775 sn.s = -2; 8776 return sn; 8777 } 8778 sn.s = fputs(content,sfp); 8779 printf("temp:%s\n%i\n",sn.n,sn.s); 8780 fclose(sfp); 8781 if (sn.s==0) { 8782 sn.s = -2; 8783 unlink(sn.n); 8784 } 8785 return sn; 8786 } 8787 int synctex_test_sheet_1() { 8788 int TC = 0; 8789 char * content = 8790 "SyncTeX Version:1 \n" /*00-19*/ 8791 "Input:1:./1.tex \n" /*20-39*/ 8792 "Output:pdf \n" /*40-59*/ 8793 "Magnification:100000000 \n" /*60-89*/ 8794 "Unit:1 \n" /*90-99*/ 8795 "X Offset:0 \n" /*00-19*/ 8796 "Y Offset:0 \n" /*20-39*/ 8797 "Content: \n" /*40-49*/ 8798 "{1 \n" /*50-59*/ 8799 "[1,10:20,350:330,330,0 \n" /*60-89*/ 8800 "] \n" /*90-99*/ 8801 "} \n" /*00-09*/ 8802 "Postamble:\n"; 8803 synctex_test_sn_s sn = synctex_test_tmp_sn(content); 8804 if (sn.s>0) { 8805 synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); 8806 synctex_node_p node = synctex_scanner_handle(scanner); 8807 printf("Created nodes:\n"); 8808 while (node) { 8809 printf("%s\n",_synctex_node_abstract(node)); 8810 node = synctex_node_next(node); 8811 } 8812 synctex_scanner_free(scanner); 8813 unlink(sn.n); 8814 } else { 8815 ++TC; 8816 } 8817 return TC; 8818 } 8819 int synctex_test_sheet_2() { 8820 int TC = 0; 8821 char * content = 8822 "SyncTeX Version:1 \n" /*00-19*/ 8823 "Input:1:./1.tex \n" /*20-39*/ 8824 "Output:pdf \n" /*40-59*/ 8825 "Magnification:100000000 \n" /*60-89*/ 8826 "Unit:1 \n" /*90-99*/ 8827 "X Offset:0 \n" /*00-19*/ 8828 "Y Offset:0 \n" /*20-39*/ 8829 "Content: \n" /*40-49*/ 8830 "{1 \n" /*50-59*/ 8831 "(1,10:20,350:330,330,0 \n" /*60-89*/ 8832 ") \n" /*90-99*/ 8833 "} \n" /*00-09*/ 8834 "Postamble:\n"; 8835 synctex_test_sn_s sn = synctex_test_tmp_sn(content); 8836 if (sn.s>0) { 8837 synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); 8838 synctex_node_p node = synctex_scanner_handle(scanner); 8839 printf("Created nodes:\n"); 8840 while (node) { 8841 printf("%s\n",_synctex_node_abstract(node)); 8842 node = _synctex_node_next(node); 8843 } 8844 TC += synctex_scanner_free(scanner); 8845 unlink(sn.n); 8846 } else { 8847 ++TC; 8848 } 8849 return TC; 8850 } 8851 int synctex_test_charindex() { 8852 int TC = 0; 8853 char * content = 8854 "SyncTeX Version:1 \n" /*00-19*/ 8855 "Input:1:./1.tex \n" /*20-39*/ 8856 "Output:pdf \n" /*40-59*/ 8857 "Magnification:100000000 \n" /*60-89*/ 8858 "Unit:1 \n" /*90-99*/ 8859 "X Offset:0 \n" /*00-19*/ 8860 "Y Offset:0 \n" /*20-39*/ 8861 "Content: \n" /*40-49*/ 8862 "{1 \n" /*50-59*/ 8863 "[1,10:20,350:330,330,0 \n" /*60-89*/ 8864 "(1,58:20,100:250,10,5 \n" /*90-119*/ 8865 "f1000:50,100 \n" /*20-39*/ 8866 ") \n" /*40-49*/ 8867 "] \n" /*50-59*/ 8868 "} \n" /*60-69*/ 8869 "Postamble:\n"; 8870 synctex_test_sn_s sn = synctex_test_tmp_sn(content); 8871 if (sn.s>0) { 8872 synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); 8873 synctex_node_p node = synctex_scanner_handle(scanner); 8874 printf("Created nodes:\n"); 8875 while (node) { 8876 printf("%s\n",_synctex_node_abstract(node)); 8877 node = synctex_node_next(node); 8878 } 8879 TC += synctex_scanner_free(scanner); 8880 unlink(sn.n); 8881 } else { 8882 ++TC; 8883 } 8884 return TC; 8885 } 8886 int synctex_test_form() { 8887 int TC = 0; 8888 char * content = 8889 "SyncTeX Version:1 \n" /*00-19*/ 8890 "Input:1:./1.tex \n" /*20-39*/ 8891 "Output:pdf \n" /*40-59*/ 8892 "Magnification:100000000 \n" /*60-89*/ 8893 "Unit:1 \n" /*90-99*/ 8894 "X Offset:0 \n" /*00-19*/ 8895 "Y Offset:0 \n" /*20-39*/ 8896 "Content: \n" /*40-49*/ 8897 "{1 \n" /*50-59*/ 8898 "[1,10:20,350:330,330,0 \n" /*60-89*/ 8899 "(1,58:20,100:250,10,5 \n" /*90-119*/ 8900 "f1000:50,100 \n" /*20-39*/ 8901 ") \n" /*40-49*/ 8902 "] \n" /*50-59*/ 8903 "} \n" /*60-69*/ 8904 "<1000 \n" /*70-79*/ 8905 "(1,63:0,0:100,8,3 \n" /*80-99*/ 8906 ") \n" /*00-09*/ 8907 "> \n" /*10-19*/ 8908 "Postamble:\n"; 8909 synctex_test_sn_s sn = synctex_test_tmp_sn(content); 8910 if (sn.s>0) { 8911 synctex_scanner_p scanner = synctex_scanner_new_with_output_file(sn.n, NULL, synctex_YES); 8912 synctex_node_p node = synctex_scanner_handle(scanner); 8913 while (node) { 8914 printf("%s\n",_synctex_node_abstract(node)); 8915 node = _synctex_node_next(node); 8916 } 8917 TC += synctex_scanner_free(scanner); 8918 unlink(sn.n); 8919 } else { 8920 ++TC; 8921 } 8922 return TC; 8923 } 8924 #endif