You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
396 lines
16 KiB
396 lines
16 KiB
/* |
|
SPDX-FileCopyrightText: 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr |
|
SPDX-License-Identifier: X11 |
|
|
|
This file is part of the __SyncTeX__ package. |
|
|
|
[//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017) |
|
[//]: # (Version: 1.19) |
|
|
|
See `synctex_parser_readme.md` for more details |
|
|
|
## Acknowledgments: |
|
|
|
The author received useful remarks from the __pdfTeX__ developers, especially Hahn The Thanh, |
|
and significant help from __XeTeX__ developer Jonathan Kew. |
|
|
|
## Nota Bene: |
|
|
|
If you include or use a significant part of the __SyncTeX__ package into a software, |
|
I would appreciate to be listed as contributor and see "__SyncTeX__" highlighted. |
|
*/ |
|
|
|
#ifndef __SYNCTEX_PARSER__ |
|
#define __SYNCTEX_PARSER__ |
|
|
|
#ifdef __cplusplus |
|
extern "C" { |
|
#endif |
|
|
|
#define SYNCTEX_VERSION_STRING "1.19" |
|
|
|
/* The main synctex object is a scanner. |
|
* Its implementation is considered private. |
|
* The basic workflow is |
|
* - create a "synctex scanner" with the contents of a file |
|
* - perform actions on that scanner like |
|
synctex_display_query or synctex_edit_query below. |
|
* - perform actions on nodes returned by the scanner |
|
* - free the scanner when the work is done |
|
*/ |
|
typedef struct synctex_scanner_t synctex_scanner_s; |
|
typedef synctex_scanner_s *synctex_scanner_p; |
|
|
|
/** |
|
* This is the designated method to create |
|
* a new synctex scanner object. |
|
* - argument output: the pdf/dvi/xdv file associated |
|
* to the synctex file. |
|
* If necessary, it can be the tex file that |
|
* originated the synctex file but this might cause |
|
* problems if the \\jobname has a custom value. |
|
* Despite this method can accept a relative path |
|
* in practice, you should only pass full paths. |
|
* The path should be encoded by the underlying |
|
* file system, assuming that it is based on |
|
* 8 bits characters, including UTF8, |
|
* not 16 bits nor 32 bits. |
|
* The last file extension is removed and |
|
* replaced by the proper extension, |
|
* either synctex or synctex.gz. |
|
* - argument build_directory: It is the directory where |
|
* all the auxiliary stuff is created. |
|
* If no synctex file is found in the same directory |
|
* as the output file, then we try to find one in |
|
* this build directory. |
|
* It is the directory where all the auxiliary |
|
* stuff is created. Sometimes, the synctex output |
|
* file and the pdf, dvi or xdv files are not |
|
* created in the same location. See MikTeX. |
|
* This directory path can be NULL, |
|
* it will be ignored then. |
|
* It can be either absolute or relative to the |
|
* directory of the output pdf (dvi or xdv) file. |
|
* Please note that this new argument is provided |
|
* as a convenience but should not be used. |
|
* Available since version 1.5. |
|
* - argument parse: In general, use 1. |
|
* Use 0 only if you do not want to parse the |
|
* content but just check for existence. |
|
* Available since version 1.5 |
|
* - resturn: a scanner. NULL is returned in case |
|
* of an error or non existent file. |
|
*/ |
|
synctex_scanner_p synctex_scanner_new_with_output_file(const char *output, const char *build_directory, int parse); |
|
|
|
/** |
|
* Designated method to delete a synctex scanner object, |
|
* including all its internal resources. |
|
* Frees all the memory, you must call it when you are finished with the scanner. |
|
* - argument scanner: a scanner. |
|
* - returns: an integer used for testing purposes. |
|
*/ |
|
int synctex_scanner_free(synctex_scanner_p scanner); |
|
|
|
/** |
|
* Send this message to force the scanner to |
|
* parse the contents of the synctex output file. |
|
* Nothing is performed if the file was already parsed. |
|
* In each query below, this message is sent, |
|
* but if you need to access information more directly, |
|
* you must ensure that the parsing did occur. |
|
* Usage: |
|
* if((my_scanner = synctex_scanner_parse(my_scanner))) { |
|
* continue with my_scanner... |
|
* } else { |
|
* there was a problem |
|
* } |
|
* - returns: the argument on success. |
|
* On failure, frees scanner and returns NULL. |
|
*/ |
|
synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner); |
|
|
|
/* synctex_node_p is the type for all synctex nodes. |
|
* Its implementation is considered private. |
|
* The synctex file is parsed into a tree of nodes, either sheet, form, boxes, math nodes... */ |
|
|
|
typedef struct synctex_node_t synctex_node_s; |
|
typedef synctex_node_s *synctex_node_p; |
|
|
|
/* The main entry points. |
|
* Given the file name, a line and a column number, synctex_display_query returns the number of nodes |
|
* satisfying the contrain. Use code like |
|
* |
|
* if(synctex_display_query(scanner,name,line,column,page_hint)>0) { |
|
* synctex_node_p node; |
|
* while((node = synctex_scanner_next_result(scanner))) { |
|
* // do something with node |
|
* ... |
|
* } |
|
* } |
|
* |
|
* Please notice that since version 1.19, |
|
* there is a new argument page_hint. |
|
* The results in pages closer to page_hint are given first. |
|
* For example, one can |
|
* - highlight each resulting node in the output, using synctex_node_visible_h and synctex_node_visible_v |
|
* - highlight all the rectangles enclosing those nodes, using synctex_node_box_visible_... functions |
|
* - highlight just the character using that information |
|
* |
|
* Given the page and the position in the page, synctex_edit_query returns the number of nodes |
|
* satisfying the contrain. Use code like |
|
* |
|
* if(synctex_edit_query(scanner,page,h,v)>0) { |
|
* synctex_node_p node; |
|
* while(node = synctex_scanner_next_result(scanner)) { |
|
* // do something with node |
|
* ... |
|
* } |
|
* } |
|
* |
|
* For example, one can |
|
* - highlight each resulting line in the input, |
|
* - highlight just the character using that information |
|
* |
|
* page is 1 based |
|
* h and v are coordinates in 72 dpi unit, relative to the top left corner of the page. |
|
* If you make a new query, the result of the previous one is discarded. If you need to make more than one query |
|
* in parallel, use the iterator API exposed in |
|
* the synctex_parser_private.h header. |
|
* If one of this function returns a negative integer, |
|
* it means that an error occurred. |
|
* |
|
* Both methods are conservative, in the sense that matching is weak. |
|
* If the exact column number is not found, there will be an answer with the whole line. |
|
* |
|
* Sumatra-PDF, Skim, iTeXMac2, TeXShop and Texworks are examples of open source software that use this library. |
|
* You can browse their code for a concrete implementation. |
|
*/ |
|
typedef long synctex_status_t; |
|
/* The page_hint argument is used to resolve ambiguities. |
|
* Whenever, different matches occur, the ones closest |
|
* to the page will be given first. Pass a negative number |
|
* when in doubt. Using pdf forms may lead to ambiguities. |
|
*/ |
|
synctex_status_t synctex_display_query(synctex_scanner_p scanner, const char *name, int line, int column, int page_hint); |
|
synctex_status_t synctex_edit_query(synctex_scanner_p scanner, int page, float h, float v); |
|
synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner); |
|
synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner); |
|
|
|
/** |
|
* The horizontal and vertical location, |
|
* the width, height and depth of a box enclosing node. |
|
* All dimensions are given in page coordinates |
|
* as opposite to TeX coordinates. |
|
* The origin is at the top left corner of the page. |
|
* Code example for Qt5: |
|
* (from TeXworks source TWSynchronize.cpp) |
|
* QRectF nodeRect(synctex_node_box_visible_h(node), |
|
* synctex_node_box_visible_v(node) - |
|
* synctex_node_box_visible_height(node), |
|
* synctex_node_box_visible_width(node), |
|
* synctex_node_box_visible_height(node) + |
|
* synctex_node_box_visible_depth(node)); |
|
* Code example for Cocoa: |
|
* NSRect bounds = [pdfPage |
|
* boundsForBox:kPDFDisplayBoxMediaBox]; |
|
* NSRect nodeRect = NSMakeRect( |
|
* synctex_node_box_visible_h(node), |
|
* NSMaxY(bounds)-synctex_node_box_visible_v(node) + |
|
* synctex_node_box_visible_height(node), |
|
* synctex_node_box_visible_width(node), |
|
* synctex_node_box_visible_height(node) + |
|
* synctex_node_box_visible_depth(node) |
|
* ); |
|
* The visible dimensions are bigger than real ones |
|
* to compensate 0 width boxes or nodes intentionally |
|
* put outside the box (using \\kern for example). |
|
* - parameter node: a node. |
|
* - returns: a float. |
|
* - author: JL |
|
*/ |
|
float synctex_node_box_visible_h(synctex_node_p node); |
|
float synctex_node_box_visible_v(synctex_node_p node); |
|
float synctex_node_box_visible_width(synctex_node_p node); |
|
float synctex_node_box_visible_height(synctex_node_p node); |
|
float synctex_node_box_visible_depth(synctex_node_p node); |
|
|
|
/** |
|
* For quite all nodes, horizontal and vertical coordinates, and width. |
|
* All dimensions are given in page coordinates |
|
* as opposite to TeX coordinates. |
|
* The origin is at the top left corner of the page. |
|
* The visible dimensions are bigger than real ones |
|
* to compensate 0 width boxes or nodes intentionally |
|
* put outside the box (using \\kern for example). |
|
* All nodes have coordinates, but all nodes don't |
|
* have non null size. For example, math nodes |
|
* have no width according to TeX, and in that case |
|
* synctex_node_visible_width simply returns 0. |
|
* The same holds for kern nodes that do not have |
|
* height nor depth, etc... |
|
*/ |
|
float synctex_node_visible_h(synctex_node_p node); |
|
float synctex_node_visible_v(synctex_node_p node); |
|
float synctex_node_visible_width(synctex_node_p node); |
|
float synctex_node_visible_height(synctex_node_p node); |
|
float synctex_node_visible_depth(synctex_node_p node); |
|
|
|
/** |
|
* Given a node, access to its tag, line and column. |
|
* The line and column numbers are 1 based. |
|
* The latter is not yet fully supported in TeX, |
|
* the default implementation returns 0 |
|
* which means the whole line. |
|
* synctex_node_get_name returns the path of the |
|
* TeX source file that was used to create the node. |
|
* When the tag is known, the scanner of the node |
|
* will also give that same file name, see |
|
* synctex_scanner_get_name below. |
|
*/ |
|
int synctex_node_tag(synctex_node_p node); |
|
int synctex_node_line(synctex_node_p node); |
|
int synctex_node_column(synctex_node_p node); |
|
const char *synctex_node_get_name(synctex_node_p node); |
|
|
|
/** |
|
This is the page where the node appears. |
|
* This is a 1 based index as given by TeX. |
|
*/ |
|
int synctex_node_page(synctex_node_p node); |
|
|
|
/** |
|
* Display all the information contained in the scanner. |
|
* If the records are too numerous, only the first ones are displayed. |
|
* This is mainly for informational purpose to help developers. |
|
*/ |
|
void synctex_scanner_display(synctex_scanner_p scanner); |
|
|
|
/* Managing the input file names. |
|
* Given a tag, synctex_scanner_get_name will return the corresponding file name. |
|
* Conversely, given a file name, synctex_scanner_get_tag will return, the corresponding tag. |
|
* The file name must be the very same as understood by TeX. |
|
* For example, if you \input myDir/foo.tex, the file name is myDir/foo.tex. |
|
* No automatic path expansion is performed. |
|
* Finally, synctex_scanner_input is the first input node of the scanner. |
|
* To browse all the input node, use a loop like |
|
* ... |
|
* synctex_node_p = input_node; |
|
* ... |
|
* if((input_node = synctex_scanner_input(scanner))) { |
|
* do { |
|
* blah |
|
* } while((input_node=synctex_node_sibling(input_node))); |
|
* } |
|
* |
|
* The output is the name that was used to create the scanner. |
|
* The synctex is the real name of the synctex file, |
|
* it was obtained from output by setting the proper file extension. |
|
*/ |
|
const char *synctex_scanner_get_name(synctex_scanner_p scanner, int tag); |
|
|
|
int synctex_scanner_get_tag(synctex_scanner_p scanner, const char *name); |
|
|
|
synctex_node_p synctex_scanner_input(synctex_scanner_p scanner); |
|
synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner, int tag); |
|
const char *synctex_scanner_get_output(synctex_scanner_p scanner); |
|
const char *synctex_scanner_get_synctex(synctex_scanner_p scanner); |
|
|
|
/* The x and y offset of the origin in TeX coordinates. The magnification |
|
These are used by pdf viewers that want to display the real box size. |
|
For example, getting the horizontal coordinates of a node would require |
|
synctex_node_box_h(node)*synctex_scanner_magnification(scanner)+synctex_scanner_x_offset(scanner) |
|
Getting its TeX width would simply require |
|
synctex_node_box_width(node)*synctex_scanner_magnification(scanner) |
|
but direct methods are available for that below. |
|
*/ |
|
int synctex_scanner_x_offset(synctex_scanner_p scanner); |
|
int synctex_scanner_y_offset(synctex_scanner_p scanner); |
|
float synctex_scanner_magnification(synctex_scanner_p scanner); |
|
|
|
/** |
|
* ## Browsing the nodes |
|
* parent, child and sibling are standard names for tree nodes. |
|
* The parent is one level higher, |
|
* the child is one level deeper, |
|
* and the sibling is at the same level. |
|
* A node and its sibling have the same parent. |
|
* A node is the parent of its children. |
|
* A node is either the child of its parent, |
|
* or belongs to the sibling chain of its parent's child. |
|
* The sheet or form of a node is the topmost ancestor, |
|
* it is of type sheet or form. |
|
* The next node is either the child, the sibling or the parent's sibling, |
|
* unless the parent is a sheet, a form or NULL. |
|
* This allows to navigate through all the nodes of a given sheet node: |
|
* |
|
* synctex_node_p node = sheet; |
|
* while((node = synctex_node_next(node))) { |
|
* // do something with node |
|
* } |
|
* |
|
* With synctex_sheet_content and synctex_form_content, |
|
* you can retrieve the sheet node given the page |
|
* or form tag. |
|
* The page is 1 based, according to TeX standards. |
|
* Conversely synctex_node_parent_sheet or |
|
* synctex_node_parent_form allows to retrieve |
|
* the sheet or the form containing a given node. |
|
* Notice that a node is not contained in a sheet |
|
* and a form at the same time. |
|
* Some nodes are not contained in either (handles). |
|
*/ |
|
|
|
synctex_node_p synctex_node_parent(synctex_node_p node); |
|
synctex_node_p synctex_node_parent_sheet(synctex_node_p node); |
|
synctex_node_p synctex_node_parent_form(synctex_node_p node); |
|
synctex_node_p synctex_node_child(synctex_node_p node); |
|
synctex_node_p synctex_node_last_child(synctex_node_p node); |
|
synctex_node_p synctex_node_sibling(synctex_node_p node); |
|
synctex_node_p synctex_node_last_sibling(synctex_node_p node); |
|
synctex_node_p synctex_node_arg_sibling(synctex_node_p node); |
|
synctex_node_p synctex_node_next(synctex_node_p node); |
|
|
|
/** |
|
* Top level entry points. |
|
* The scanner owns a list of sheet siblings and |
|
* a list of form siblings. |
|
* Sheets or forms have one child which is a box: |
|
* theie contents. |
|
* - argument page: 1 based sheet page number. |
|
* - argument tag: 1 based form tag number. |
|
*/ |
|
synctex_node_p synctex_sheet(synctex_scanner_p scanner, int page); |
|
synctex_node_p synctex_sheet_content(synctex_scanner_p scanner, int page); |
|
synctex_node_p synctex_form(synctex_scanner_p scanner, int tag); |
|
synctex_node_p synctex_form_content(synctex_scanner_p scanner, int tag); |
|
|
|
/* This is primarily used for debugging purpose. |
|
* The second one logs information for the node and recursively displays information for its next node */ |
|
void synctex_node_log(synctex_node_p node); |
|
void synctex_node_display(synctex_node_p node); |
|
|
|
/* For quite all nodes, horizontal, vertical coordinates, and width. |
|
* These are expressed in TeX small points coordinates, with origin at the top left corner. |
|
*/ |
|
int synctex_node_h(synctex_node_p node); |
|
int synctex_node_v(synctex_node_p node); |
|
int synctex_node_width(synctex_node_p node); |
|
int synctex_node_height(synctex_node_p node); |
|
int synctex_node_depth(synctex_node_p node); |
|
|
|
/* For all nodes, dimensions of the enclosing box. |
|
* These are expressed in TeX small points coordinates, with origin at the top left corner. |
|
* A box is enclosing itself. |
|
*/ |
|
int synctex_node_box_h(synctex_node_p node); |
|
int synctex_node_box_v(synctex_node_p node); |
|
int synctex_node_box_width(synctex_node_p node); |
|
int synctex_node_box_height(synctex_node_p node); |
|
int synctex_node_box_depth(synctex_node_p node); |
|
|
|
#ifdef __cplusplus |
|
} |
|
#endif |
|
|
|
#endif
|
|
|