synctex_parser.c.svn-base

来自「SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多K」· SVN-BASE 代码 · 共 1,720 行 · 第 1/5 页

SVN-BASE
1,720
字号
/* Copyright (c) 2008 jerome DOT laurens AT u-bourgogne DOT frThis file is part of the SyncTeX package.Version: 1.6See synctex_parser_readme.txt for more detailsLicense:--------Permission is hereby granted, free of charge, to any personobtaining a copy of this software and associated documentationfiles (the "Software"), to deal in the Software withoutrestriction, including without limitation the rights to use,copy, modify, merge, publish, distribute, sublicense, and/or sellcopies of the Software, and to permit persons to whom theSoftware is furnished to do so, subject to the followingconditions:The above copyright notice and this permission notice shall beincluded in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIESOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE ANDNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISINGFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OROTHER DEALINGS IN THE SOFTWAREExcept as contained in this notice, the name of the copyright holder  shall not be used in advertising or otherwise to promote the sale,  use or other dealings in this Software without prior written  authorization from the copyright holder.*//*  We assume that high level application like pdf viewers will want *  to embed this code as is. We assume that they also have locale.h and setlocale. *  For other tools such as TeXLive tools, you must define SYNCTEX_USE_LOCAL_HEADER, *  when building. You also have to create and customize synctex_parser_local.h to fit your system. *  In particular, the HAVE_LOCALE_H and HAVE_SETLOCALE macros should be properly defined. *  With this design, you should not need to edit this file. */#   define synctex_bool_t int#   define synctex_YES -1#   define synctex_NO 0#   if defined(SYNCTEX_USE_LOCAL_HEADER)#       include "synctex_parser_local.h"#   else#       define HAVE_LOCALE_H 1#       define HAVE_SETLOCALE 1#       if defined(_MSC_VER) #          define SYNCTEX_INLINE __inline#       else#          define SYNCTEX_INLINE inline#       endif#   endif#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <limits.h>#if defined(HAVE_LOCALE_H)#include <locale.h>#endif/*  The data is organized in a graph with multiple entries. *  The root object is a scanner, it is created with the contents on a synctex file. *  Each leaf of the tree is a synctex_node_t object. *  There are 3 subtrees, two of them sharing the same leaves. *  The first tree is the list of input records, where input file names are associated with tags. *  The second tree is the box tree as given by TeX when shipping pages out. *  First level objects are sheets, containing boxes, glues, kerns... *  The third tree allows to browse leaves according to tag and line. */#include "synctex_parser.h"#include <synctex_parser_utils.h>/*  each synctex node has a class */typedef struct __synctex_class_t _synctex_class_t;typedef _synctex_class_t *  synctex_class_t;/*  synctex_node_t is a pointer to a node *  _synctex_node is the target of the synctex_node_t pointer *  It is a pseudo object oriented program. *  class is a pointer to the class object the node belongs to. *  implementation is meant to contain the private data of the node *  basically, there are 2 kinds of information: navigation information and *  synctex information. Both will depend on the type of the node, *  thus different nodes will have different private data. *  There is no inheritancy overhead. */typedef union _synctex_info_t {	int    INT;	char *  PTR;} synctex_info_t;struct _synctex_node {	synctex_class_t class;	synctex_info_t *  implementation;};/*  Each node of the tree, except the scanner itself belongs to a class. *  The class object is just a struct declaring the owning scanner *  This is a pointer to the scanner as root of the tree. *  The type is used to identify the kind of node. *  The class declares pointers to a creator and a destructor method. *  The log and display fields are used to log and display the node. *  display will also display the child, sibling and parent sibling. *  parent, child and sibling are used to navigate the tree, *  from TeX box hierarchy point of view. *  The friend field points to a method which allows to navigate from friend to friend. *  A friend is a node with very close tag and line numbers. *  Finally, the info field point to a method giving the private node info offset. */typedef synctex_node_t *(*_synctex_node_getter_t)(synctex_node_t);typedef synctex_info_t *(*_synctex_info_getter_t)(synctex_node_t);struct __synctex_class_t {	synctex_scanner_t scanner;	int type;	synctex_node_t (*new)(synctex_scanner_t scanner);	void (*free)(synctex_node_t);	void (*log)(synctex_node_t);	void (*display)(synctex_node_t);	_synctex_node_getter_t parent;	_synctex_node_getter_t child;	_synctex_node_getter_t sibling;	_synctex_node_getter_t friend;	_synctex_node_getter_t next_box;	_synctex_info_getter_t info;};#	ifdef SYNCTEX_NOTHING#       pragma mark -#       pragma mark Abstract OBJECTS and METHODS#   endif/*  These macros are shortcuts *  This macro checks if a message can be sent. */#   define SYNCTEX_CAN_PERFORM(NODE,SELECTOR)\		(NULL!=((((NODE)->class))->SELECTOR))/*  This macro is some kind of objc_msg_send. *  It takes care of sending the proper message if possible. */#   define SYNCTEX_MSG_SEND(NODE,SELECTOR) if(NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR)) {\		(*((((NODE)->class))->SELECTOR))(NODE);\	}/*  read only safe getter */#   define SYNCTEX_GET(NODE,SELECTOR)((NODE && SYNCTEX_CAN_PERFORM(NODE,SELECTOR))?SYNCTEX_GETTER(NODE,SELECTOR)[0]:(NULL))/*  read/write getter */#   define SYNCTEX_GETTER(NODE,SELECTOR)\		((synctex_node_t *)((*((((NODE)->class))->SELECTOR))(NODE)))#   define SYNCTEX_FREE(NODE) SYNCTEX_MSG_SEND(NODE,free);/*  Parent getter and setter */#   define SYNCTEX_PARENT(NODE) SYNCTEX_GET(NODE,parent)#   define SYNCTEX_SET_PARENT(NODE,NEW_PARENT) if(NODE && NEW_PARENT && SYNCTEX_CAN_PERFORM(NODE,parent)){\		SYNCTEX_GETTER(NODE,parent)[0]=NEW_PARENT;\	}/*  Child getter and setter */#   define SYNCTEX_CHILD(NODE) SYNCTEX_GET(NODE,child)#   define SYNCTEX_SET_CHILD(NODE,NEW_CHILD) if(NODE && NEW_CHILD){\		SYNCTEX_GETTER(NODE,child)[0]=NEW_CHILD;\		SYNCTEX_GETTER(NEW_CHILD,parent)[0]=NODE;\	}/*  Sibling getter and setter */#   define SYNCTEX_SIBLING(NODE) SYNCTEX_GET(NODE,sibling)#   define SYNCTEX_SET_SIBLING(NODE,NEW_SIBLING) if(NODE && NEW_SIBLING) {\		SYNCTEX_GETTER(NODE,sibling)[0]=NEW_SIBLING;\		if(SYNCTEX_CAN_PERFORM(NEW_SIBLING,parent) && SYNCTEX_CAN_PERFORM(NODE,parent)) {\			SYNCTEX_GETTER(NEW_SIBLING,parent)[0]=SYNCTEX_GETTER(NODE,parent)[0];\		}\	}/*  Friend getter and setter. A friend is a kern, math, glue or void box node which tag and line numbers are similar. *  This is a first filter on the nodes that avoids testing all of them. *  Friends are used mainly in forward synchronization aka from source to output. */#   define SYNCTEX_FRIEND(NODE) SYNCTEX_GET(NODE,friend)#   define SYNCTEX_SET_FRIEND(NODE,NEW_FRIEND) if(NODE && NEW_FRIEND){\		SYNCTEX_GETTER(NODE,friend)[0]=NEW_FRIEND;\	}/*  Next box getter and setter. The box tree can be traversed from one horizontal boxes to the other. *  Navigation starts with the deeper boxes. */#   define SYNCTEX_NEXT_HORIZ_BOX(NODE) SYNCTEX_GET(NODE,next_box)#   define SYNCTEX_SET_NEXT_HORIZ_BOX(NODE,NEXT_BOX) if(NODE && NEXT_BOX){\		SYNCTEX_GETTER(NODE,next_box)[0]=NEXT_BOX;\	}void _synctex_free_node(synctex_node_t node);void _synctex_free_leaf(synctex_node_t node);/*  A node is meant to own its child and sibling. *  It is not owned by its parent, unless it is its first child. *  This destructor is for all nodes with children. */void _synctex_free_node(synctex_node_t node) {	if(node) {		(*((node->class)->sibling))(node);		SYNCTEX_FREE(SYNCTEX_SIBLING(node));		SYNCTEX_FREE(SYNCTEX_CHILD(node));		free(node);	}	return;}/*  A node is meant to own its child and sibling. *  It is not owned by its parent, unless it is its first child. *  This destructor is for nodes with no child. */void _synctex_free_leaf(synctex_node_t node) {	if(node) {		SYNCTEX_FREE(SYNCTEX_SIBLING(node));		free(node);	}	return;}#include <zlib.h>/*  The synctex scanner is the root object. *  Is is initialized with the contents of a text file or a gzipped file. *  The buffer_? are first used to parse the text. */struct __synctex_scanner_t {	gzFile file;                  /*  The (possibly compressed) file */	unsigned char *  buffer_cur;   /*  current location in the buffer */	unsigned char *  buffer_start; /*  start of the buffer */	unsigned char *  buffer_end;   /*  end of the buffer */	char *  output_fmt;            /*  dvi or pdf, not yet used */	char *  output;                /*  the output name used to create the scanner */	char *  synctex;               /*  the .synctex or .synctex.gz name used to create the scanner */	int version;                  /* 1, not yet used */	struct {		unsigned has_parsed:1;		/*  Whether the scanner has parsed its underlying synctex file. */		unsigned reserved:sizeof(unsigned)-1;	/*  alignment */	} flags;	int pre_magnification;        /*  magnification from the synctex preamble */	int pre_unit;                 /*  unit from the synctex preamble */	int pre_x_offset;             /*  X offste from the synctex preamble */	int pre_y_offset;             /*  Y offset from the synctex preamble */	int count;                    /*  Number of records, from the synctex postamble */	float unit;                   /*  real unit, from synctex preamble or post scriptum */	float x_offset;               /*  X offset, from synctex preamble or post scriptum */	float y_offset;               /*  Y Offset, from synctex preamble or post scriptum */	synctex_node_t sheet;         /*  The first sheet node, its siblings are the other sheet nodes */	synctex_node_t input;         /*  The first input node, its siblings are the other input nodes */	int number_of_lists;          /*  The number of friend lists */	synctex_node_t *  lists_of_friends;/*  The friend lists */	_synctex_class_t class[synctex_node_number_of_types]; /*  The classes of the nodes of the scanner */};/*  SYNCTEX_CUR, SYNCTEX_START and SYNCTEX_END are convenient shortcuts */#   define SYNCTEX_CUR (scanner->buffer_cur)#   define SYNCTEX_START (scanner->buffer_start)#   define SYNCTEX_END (scanner->buffer_end)#	ifdef SYNCTEX_NOTHING#       pragma mark -#       pragma mark OBJECTS, their creators and destructors.#   endif/*  Here, we define the indices for the different informations. *  They are used to declare the size of the implementation. *  For example, if one object uses SYNCTEX_HORIZ_IDX is its size, *  then its info will contain a tag, line, column, horiz but no width nor height nor depth *//*  The sheet is a first level node. *  It has no parent (the parent is the scanner itself) *  Its sibling points to another sheet. *  Its child points to its first child, in general a box. *  A sheet node contains only one synctex information: the page. *  This is the 1 based page index as given by TeX. *//*  The next macros are used to access the node info *  SYNCTEX_INFO(node) points to the first synctex integer or pointer data of node *  SYNCTEX_INFO(node)[index] is the information at index *  for example, the page of a sheet is stored in SYNCTEX_INFO(sheet)[SYNCTEX_PAGE_IDX] */#   define SYNCTEX_INFO(NODE) ((*((((NODE)->class))->info))(NODE))#   define SYNCTEX_PAGE_IDX 0#   define SYNCTEX_PAGE(NODE) SYNCTEX_INFO(NODE)[SYNCTEX_PAGE_IDX].INT/*  This macro defines implementation offsets *  It is only used for pointer values */#   define SYNCTEX_MAKE_GET(SYNCTEX_GETTER,OFFSET)\synctex_node_t *  SYNCTEX_GETTER (synctex_node_t node);\synctex_node_t *  SYNCTEX_GETTER (synctex_node_t node) {\	return node?(synctex_node_t *)((&((node)->implementation))+OFFSET):NULL;\}SYNCTEX_MAKE_GET(_synctex_implementation_0,0)SYNCTEX_MAKE_GET(_synctex_implementation_1,1)SYNCTEX_MAKE_GET(_synctex_implementation_2,2)SYNCTEX_MAKE_GET(_synctex_implementation_3,3)SYNCTEX_MAKE_GET(_synctex_implementation_4,4)SYNCTEX_MAKE_GET(_synctex_implementation_5,5)typedef struct {	synctex_class_t class;	synctex_info_t implementation[3+SYNCTEX_PAGE_IDX+1];/*  child, sibling, next box,	                         *  SYNCTEX_PAGE_IDX */} synctex_sheet_t;synctex_node_t _synctex_new_sheet(synctex_scanner_t scanner);void _synctex_display_sheet(synctex_node_t sheet);void _synctex_log_sheet(synctex_node_t sheet);static const _synctex_class_t synctex_class_sheet = {	NULL,                       /*  No scanner yet */	synctex_node_type_sheet,    /*  Node type */	&_synctex_new_sheet,        /*  creator */	&_synctex_free_node,        /*  destructor */	&_synctex_log_sheet,        /*  log */	&_synctex_display_sheet,    /*  display */	NULL,                       /*  No parent */	&_synctex_implementation_0, /*  child */	&_synctex_implementation_1, /*  sibling */	NULL,                       /*  No friend */	&_synctex_implementation_2, /*  Next box */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?