summaryrefslogtreecommitdiff
path: root/Build
diff options
context:
space:
mode:
authorJonathan Kew <jfkthame@googlemail.com>2008-03-05 14:08:35 +0000
committerJonathan Kew <jfkthame@googlemail.com>2008-03-05 14:08:35 +0000
commitba66bff99b5f90d3af25cbd6b4d186b6d852c544 (patch)
tree6b5f398826d757c80b3716854d2d78d0506bc01c /Build
parent371983a6df9ee7971173f2ce91dc414674be97ff (diff)
initial synctex dir (needed for new xetex build)
git-svn-id: svn://tug.org/texlive/trunk@6864 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build')
-rw-r--r--Build/source/texk/web2c/synctex/synctex.c659
-rw-r--r--Build/source/texk/web2c/synctex/synctex.ch860
-rw-r--r--Build/source/texk/web2c/synctex/synctex.defines49
-rw-r--r--Build/source/texk/web2c/synctex/synctex.h61
-rw-r--r--Build/source/texk/web2c/synctex/synctex.mk50
5 files changed, 1679 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/synctex/synctex.c b/Build/source/texk/web2c/synctex/synctex.c
new file mode 100644
index 00000000000..8f1e5a72aca
--- /dev/null
+++ b/Build/source/texk/web2c/synctex/synctex.c
@@ -0,0 +1,659 @@
+/*
+Copyright (c) 2008 jerome DOT laurens AT u-bourgogne DOT fr
+
+This file is part of the SyncTeX package.
+
+License:
+--------
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included 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 WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE
+
+Except 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.
+
+Important notice:
+-----------------
+This file is named "synctex.c", it may or may not have a header counterpart
+depending on its use. It aims to provide basic components useful for the
+input/output synchronization technology for TeX.
+The purpose of the implementation is threefold
+- firstly, it defines a new input/output synchronization technology named
+ "synchronize texnology", "SyncTeX" or "synctex"
+- secondly, it defines the naming convention and format of the auxiliary file
+ used by this technology
+- thirdly, it defines the API of a controller and a controller, used in
+ particular by the pdfTeX and XeTeX programs to prepare synchronization.
+
+All these are up to a great extent de facto definitions, which means that they
+are partly defined by the implementation itself.
+
+This technology was first designed for pdfTeX, an extension of TeX managing the
+pdf output file format, but it can certainly be adapted to other programs built
+from TeX as long as the extensions do not break too much the core design.
+Moreover, the synchronize texnology only relies on code concept and not
+implementation details, so it can be ported to other TeX systems. In order to
+support SyncTeX, one can start reading the dedicated section in synctex.ch,
+sync-pdftex.ch and sync-xetex.ch.
+
+Other existing public synchronization technologies are defined by srcltx.sty -
+also used by source specials - and pdfsync.sty. Like them, the synchronize
+texnology is meant to be shared by various text editors, viewers and TeX
+engines. A centralized reference and source of information is available on
+CTAN, in directory support/synctex.
+
+Versioning:
+-----------
+As synctex is embedded into different TeX implementation, there is an independent
+versionning system.
+For TeX implementations, the actual version is: 1
+For .synctex file format, the actual version is SYNCTEX_VERSION below
+
+Please, do not remove these explanations.
+
+*/
+
+# define SYNCTEX_DEBUG 0
+
+extern char *gettexstring(int n);
+
+# define EXTERN extern
+
+# define SYNCTEX_VERSION 1
+
+/* Some parts of the code may differ depending on the TeX engine.
+ * Here are the possible switches: */
+# define SYNCTEX_ENGINE_TEX 0
+# define SYNCTEX_ENGINE_PDFTEX 1
+/* Default engine (suitable for xetex): */
+# define SYNCTEX_ENGINE SYNCTEX_ENGINE_TEX
+
+/* Other parts of the code may differ depending on the ouput mode,
+ * dvi or xdv vs pdf, in particular the management of magnification.
+ * The default is not pdf mode. */
+# define SYNCTEX_IS_PDF 0
+
+# if defined(XETEX_MAC) || defined(XETEX_OTHER)
+
+# include <stdio.h>
+
+# include "xetexd.h"
+ /* this will define XeTeX, which we can use in later conditionals */
+
+# include <xetexdir/xetexextra.h>
+
+# define MAX(a, b) ((a) > (b) ? (a) : (b))
+# define xfree(x) do { if (x) free(x); } while (0)
+
+# else
+
+# ifdef pdfTeX
+# undef pdfTeX
+# endif
+
+# include "pdftexd.h"
+
+# undef SYNCTEX_ENGINE
+# define SYNCTEX_ENGINE SYNCTEX_ENGINE_PDFTEX
+
+/* We observe pdfoutputvalue in order to determine whether output mode is pdf.
+ * We will assume that pdf_output_value equals pdf_output before entering
+ * the synctex_sheet function below. */
+# undef SYNCTEX_IS_PDF
+# define SYNCTEX_IS_PDF (pdfoutputvalue>0)
+
+# endif /* defined XETEX_* */
+
+# if defined(pdfTeX) || defined(XeTeX) || defined(__SyncTeX__)
+
+/* Here are all the local variables gathered in one "synchronization context" */
+static struct {
+ FILE *file; /* the foo.synctex I/O identifier */
+ char *name; /* the real "foo.synctex" name */
+ char *root_name; /* in general jobname.tex */
+ integer count; /* The number of records in "foo.synctex" */
+ /* next concern the last sync record encountered */
+ halfword p; /* the last synchronized node, must be set
+ * before the recorder */
+ void (*recorder) (halfword p); /* the recorder of the node above, the
+ * routine that knows how to record the
+ * node to the .synctex file */
+ integer h, v; /* the last sync record coordinates */
+ integer offset; /* the offset of the origin / the topleft of
+ * the page in both directions */
+ integer scale; /* Some magnification factor to define UNIT */
+} synctex_ctxt = {
+NULL, NULL, NULL, 0, 0, NULL, 0, 0, 0, 0};
+
+/* the macros defined below do the same job than their almost eponym
+ * counterparts of *tex.web, the memory access is sometimes more direct
+ * because *tex.web won't share its own constants the main purpose is to
+ * maintain very few hook points into *tex.web in order both to ensure
+ * portability and not modifying to much the original code. see texmfmem.h
+ * and *tex.web for details, the synctex_ prefix prevents name conflicts, it
+ * is some kind of namespace
+*/
+# warning These structures MUST be kept in synchronization with the main program
+/* synctexoption is a global integer variable defined in *tex.web
+ * it is set to 1 by texmfmp.c if the command line has the '-synchronize=1'
+ * option. */
+# define SYNCTEX_OPTIONS synctexoption
+# define SYNCTEX_DISABLED_MASK 0x80000000
+/* if the SYNCTEX_DISABLED_MASK bit of SYNCTEX_OPTIONS is set, the
+ * synchronization is definitely disabled. */
+# define SYNCTEX_IGNORE_CLI_MASK 0x40000000
+/* if the SYNCTEX_IGNORE_CLI_MASK bit of SYNCTEX_OPTIONS is set, the option
+ * given from the command line is ignored. */
+
+/* glue code: really define the main memory,
+ * this is exactly the same "mem" as in *tex.web. */
+# define mem zmem
+/* glue code: synctexoffset is a global integer variable defined in *tex.web
+ * it is set to the offset where the primitive \synctex reads and writes its
+ * value. */
+# define SYNCTEX_IS_ENABLED zeqtb[synctexoffset].cint
+/* if there were a mean to share the value of synctex_code between pdftex.web
+ * and this file, it would be great. */
+
+/* synctex_dot_open ensures that the foo.synctex file is open.
+ * In case of problem, it definitely disables synchronization.
+ * Now all the synchronization info is gathered in only one file.
+ * It is possible to split this info into as many different output files as sheets
+ * plus 1 for the control but the overall benefits are not so clear.
+ * For example foo-i.synctex would contain input synchronization
+ * information for page i alone.
+*/
+static FILE *synctex_dot_open(void)
+{
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nwarning: Synchronize DEBUG: synctex_dot_open\n");
+ fprintf(stdout, "\nwarning: SYNCTEX_IS_ENABLED=%0X\n", SYNCTEX_IS_ENABLED);
+ fprintf(stdout, "\nwarning: SYNCTEX_OPTIONS=%0X\n", SYNCTEX_OPTIONS);
+# endif
+ if (0 != (SYNCTEX_OPTIONS & SYNCTEX_DISABLED_MASK)) {
+ return 0; /* synchronization is definitely disabled: do nothing */
+ }
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nwarning: Synchronize DEBUG: synctex_dot_open 1\n");
+# endif
+ if (NULL == synctex_ctxt.file) {
+ /* this is the first time we are asked to open the file
+ this part of code is executed only once:
+ either synctex_ctxt.file is nonnegative or synchronization is
+ definitely disabled. */
+ static char *suffix = ".synctex";
+ /* jobname was set by the \jobname command on the *TeX side */
+ char *tmp = gettexstring(jobname);
+ /* jobname was set by the \jobname command on the *TeX side */
+ char *the_syncname = xmalloc(strlen(tmp) + strlen(suffix) + 1);
+ strcpy(the_syncname, tmp);
+ xfree(tmp);
+ strcat(the_syncname, suffix);
+ synctex_ctxt.file = xfopen(the_syncname, FOPEN_W_MODE);
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nwarning: Synchronize DEBUG: synctex_dot_open 2\n");
+# endif
+ if (NULL != synctex_ctxt.file) {
+ /* synctex_ctxt.name was NULL before, it now owns the_syncname */
+ synctex_ctxt.name = the_syncname;
+ /* print the preamble, this is an UTF8 file */
+ fprintf(synctex_ctxt.file, "SyncTeX\nversion:%d\n",
+ SYNCTEX_VERSION);
+ if (NULL != synctex_ctxt.root_name) {
+ fprintf(synctex_ctxt.file, "i:1:%s\n", synctex_ctxt.root_name);
+ xfree(synctex_ctxt.root_name);
+ synctex_ctxt.root_name = NULL;
+ }
+# if SYNCTEX_DEBUG
+ fprintf(stdout,
+ "\nwarning: Synchronize DEBUG: synctex_dot_open SYNCTEX AVAILABLE\n");
+# endif
+ } else {
+ /* no .synctex file available, so disable synchronization */
+ SYNCTEX_OPTIONS = SYNCTEX_DISABLED_MASK;
+ /* and free the_syncname */
+ xfree(the_syncname);
+ the_syncname = NULL;
+# if SYNCTEX_DEBUG
+ fprintf(stdout,
+ "\nwarning: Synchronize DEBUG: synctex_dot_open SYNCTEX DISABLED\n");
+# endif
+ }
+ }
+ return synctex_ctxt.file;
+}
+
+/* Each time TeX opens a file, it sends a syncstartinput message and enters
+ * this function. Here, a new synchronization tag is created and stored in
+ * the synctex_tag_field of the TeX current input context. Each synchronized
+ * TeX node will record this tag instead of the file name. syncstartinput
+ * writes the mapping synctag <-> file name to the .synctex file. A client
+ * will read the .synctex file and retrieve this mapping, it will be able to
+ * open the correct file just knowing its tag. If the same file is read
+ * multiple times, it might be associated to different tags. Synchronization
+ * controller, either in viewers, editors or standalone should be prepared to
+ * handle this situation and take the appropriate action of they want to
+ * optimize memory. No two different files will have the same positive tag.
+ * It is not advisable to definitely store the file names here. If the file
+ * names ever have to be stored, it should definitely be done at the TeX level
+ * just like src-specials do such that other components of the program can use
+ * it. This function does not make any difference between the files, it
+ * treats the same way .tex, .aux, .sty ... files, even if many of them do not
+ * contain any material meant to be typeset.
+*/
+void synctexstartinput(void)
+{
+ static unsigned int synctex_tag_counter = 0;
+
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nwarning: Synchronize DEBUG: synctexstartinput %i\n",
+ synctex_tag_counter);
+ fprintf(stdout, "\nwarning: SYNCTEX_IS_ENABLED=%i\n", SYNCTEX_IS_ENABLED);
+ fprintf(stdout, "\nwarning: SYNCTEX_OPTIONS=%0X\n", SYNCTEX_OPTIONS);
+ fprintf(stdout, "\nwarning: SYNCTEX_DISABLED_MASK=%0X\n",
+ SYNCTEX_DISABLED_MASK);
+# endif
+
+ if (0 != (SYNCTEX_OPTIONS & SYNCTEX_DISABLED_MASK)) {
+ /* this is where we disable synchronization -synchronization=-1 */
+ return;
+ }
+ /* synctex_tag_counter is a counter uniquely identifying the file actually
+ * open each time tex opens a new file, syncstartinput will increment this
+ * counter */
+ if (~synctex_tag_counter > 0) {
+ ++synctex_tag_counter;
+ } else {
+ /* we have reached the limit, subsequent files will be softly ignored
+ * this makes a lot of files... even in 32 bits */
+ curinput.synctextagfield = 0;
+ return;
+ }
+
+ if (0 == (SYNCTEX_OPTIONS & SYNCTEX_IGNORE_CLI_MASK)) {
+ /* the command line options are not ignored */
+ SYNCTEX_IS_ENABLED = MAX(SYNCTEX_OPTIONS, SYNCTEX_IS_ENABLED);
+ SYNCTEX_OPTIONS |= SYNCTEX_IGNORE_CLI_MASK;
+ /* the command line options will be ignored from now on. Every
+ * subsequent call of syncstartinput won't get there SYNCTEX_OPTIONS
+ * is now the list of option flags */
+ }
+
+ curinput.synctextagfield = synctex_tag_counter; /* -> *TeX.web */
+ if (synctex_tag_counter == 1) {
+ /* this is the first file TeX ever opens, in general \jobname.tex we
+ * do not know yet if synchronization will ever be enabled so we have
+ * to store the file name, because we will need it later This is
+ * certainly not necessary due to \jobname */
+ synctex_ctxt.root_name = gettexstring(curinput.namefield);
+ return;
+ }
+ if ((NULL != synctex_ctxt.file)
+ || ((SYNCTEX_IS_ENABLED && synctex_dot_open()) != 0)) {
+ char *tmp = gettexstring(curinput.namefield);
+ fprintf(synctex_ctxt.file,"i:%u:%s\n",curinput.synctextagfield,tmp);
+ xfree(tmp);
+ }
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nwarning: Synchronize DEBUG: synctexstartinput END\n");
+# endif
+ return;
+}
+
+/* All the synctex... functions below have the smallest set of parameters. It
+ * appears to be either the address of a node, or nothing at all. Using zmem,
+ * which is the place where all the nodes are stored, one can retrieve every
+ * information about a node. The other information is obtained through the
+ * global context variable.
+*/
+
+/* Recording the "s:..." line. In *tex.web, use synctex_sheet(pdf_output) at
+ * the very beginning of the ship_out procedure.
+*/
+void synctexsheet(integer mag)
+{
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctexsheet %i\n",mag);
+# endif
+ if (0 != (SYNCTEX_OPTIONS & SYNCTEX_DISABLED_MASK)) {
+ return;
+ }
+ if ((synctex_ctxt.file != NULL)
+ || ((SYNCTEX_IS_ENABLED != 0) && (synctex_dot_open() != 0))) {
+ /* tries to open the .synctex, useful if synchronization was enabled
+ * from the source file and not from the CLI
+ * totalpages is defined in tex.web */
+ synctex_ctxt.count = 0;
+ if (totalpages == 0) {
+ if (SYNCTEX_IS_PDF != 0) {
+ fprintf(synctex_ctxt.file, ">:pdf\n");
+ }
+ /* Now it is time to properly set up the scale factor.
+ * Depending on the output mode
+ * dvi and pdf, don't start from the same origin.
+ * dvi starts at (1in,1in) from the top left corner
+ * pdf starts exactly from the top left corner.
+ * mag is a global TeX variable. */
+ if(mag>0) {
+ synctex_ctxt.scale = 8192000/mag;
+ }
+ else {
+ synctex_ctxt.scale = 8192;
+ }
+ fprintf(synctex_ctxt.file, "z:%ld\n", ((SYNCTEX_IS_PDF != 0) ? 0 : 578));
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctex_ctxt.scale:%u\n",synctex_ctxt.scale);
+# endif
+ }
+ fprintf(synctex_ctxt.file, "s:%ld\n", (long int) totalpages + 1);
+ ++synctex_ctxt.count;
+ }
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctexsheet END\n");
+# endif
+ return;
+}
+
+# define UNIT / synctex_ctxt.scale
+/* UNIT is the scale. TeX coordinates are very accurate and client won't need
+ * that, at leat in a first step. 1.0 <-> 2^16 = 65536.
+ * The TeX unit is sp (scaled point) or pt/65536 which means that the scale
+ * factor to retrieve a bp unit (a postscript) is 72/72.27/65536 =
+ * 1/4096/16.06 = 1/8192/8.03
+ * Here we use 1/8192 as scale factor, then we can limit ourselves to
+ * integers. This default value assumes that TeX magnification factor is 1000.
+ * The real TeX magnification factor is used to fine tune the synctex context
+ * scale in the synctex_dot_open function.
+ * IMPORTANT: We can say that the natural unit of .synctex files is 8192 sp.
+ * To retrieve the proper bp unit, we'll have to divide by 8.03. To reduce
+ * rounding errors, we'll certainly have to add 0.5 for non negative integers
+ * and ±0.5 for negative integers. This trick is mainly to gain speed and
+ * size. A binary file would be more appropriate in that respect, but I guess
+ * that some clients like auctex would not like it very much. we cannot use
+ * "<<13" instead of "/8192" because the integers are signed and we do not
+ * want the sign bit to be propagated. The origin of the coordinates is at
+ * the top left corner of the page. For pdf mode, it is straightforward, but
+ * for dvi mode, we'll have to record the 1in offset in both directions,
+ * eventually modified by the magnification.
+*/
+
+/* WARNING:
+ The 5 definitions below must be in sync with their eponym declarations in *tex.web
+*/
+# ifdef XeTeX
+# define synchronization_field_size 1
+# else
+# define synchronization_field_size 2
+# endif
+
+# define box_node_size (7+synchronization_field_size)
+/* see: @d box_node_size=... */
+# define width_offset 1
+/* see: @d width_offset=... */
+# define depth_offset 2
+/* see: @d depth_offset=... */
+# define height_offset 3
+/* see: @d height_offset=... */
+
+/* Now define the local version of width(##), height(##) and depth(##) macros
+ These only depend on the macros above. */
+# define SYNCTEX_WIDTH(NODE) mem[NODE+width_offset].cint
+# define SYNCTEX_DEPTH(NODE) mem[NODE+depth_offset].cint
+# define SYNCTEX_HEIGHT(NODE) mem[NODE+height_offset].cint
+
+# ifdef XeTeX
+/* in XeTeX, "halfword" fields are at least 32 bits, so we'll use those for
+ * tag and line so that the sync field size is only one memory_word. */
+# define SYNCTEX_TAG(NODE) mem[NODE+box_node_size-1].hh.lhfield
+# define SYNCTEX_LINE(NODE) mem[NODE+box_node_size-1].hh.rh
+# else
+/* The tag and the line are just the two last words of the node. This is a
+ * very handy design but this is not strictly required by the concept. If
+ * really necessary, one can define other storage rules. */
+# define SYNCTEX_TAG(NODE) mem[NODE+box_node_size-2].cint
+# define SYNCTEX_LINE(NODE) mem[NODE+box_node_size-1].cint
+#endif
+
+/* When an hlist ships out, it can contain many different kern nodes with
+ * exactly the same sync tag and line. To reduce the size of the .synctex
+ * file, we only display a kern node sync info when either the sync tag or the
+ * line changes. Also, we try ro reduce the distance between the chosen nodes
+ * in order to improve accuracy. It means that we display information for
+ * consecutive nodes, as far as possible. This tricky part uses a "recorder",
+ * which is the address of the routine that knows how to write the
+ * synchronization info to the .synctex file. It also uses criteria to detect
+ * a change in the context, this is the macro SYNCTEX_CONTEXT_DID_CHANGE The
+ * SYNCTEX_IGNORE macro is used to detect unproperly initialized nodes. See
+ * details in the implementation of the functions below. */
+# define SYNCTEX_IGNORE(NODE) (0 != (SYNCTEX_OPTIONS & SYNCTEX_DISABLED_MASK) ) \
+ || (SYNCTEX_IS_ENABLED == 0) \
+ || (synctex_ctxt.file == 0)
+
+/* Recording a "h:..." line */
+void synctex_hlist_recorder(halfword p)
+{
+ fprintf(synctex_ctxt.file, "h:%u:%u(%i,%i,%i,%i,%i)\n",
+ SYNCTEX_TAG(p), SYNCTEX_LINE(p),
+ curh UNIT,
+ curv UNIT,
+ SYNCTEX_WIDTH(p) UNIT,
+ SYNCTEX_HEIGHT(p) UNIT,
+ SYNCTEX_DEPTH(p) UNIT);
+ ++synctex_ctxt.count;
+}
+
+/* This message is sent when an hlist will be shipped out, more precisely at
+ * the beginning of the hlist_out procedure in *TeX.web. It will be balanced
+ * by a synctex_tsilh, sent at the end of the hlist_out procedure. p is the
+ * address of the hlist We assume that p is really an hlist node! */
+void synctexhlist(halfword p)
+{
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctexhlist\n");
+# endif
+ if (SYNCTEX_IGNORE(p)) {
+ return;
+ }
+ synctex_ctxt.p = 0; /* reset */
+ synctex_ctxt.recorder = NULL; /* reset */
+ synctex_hlist_recorder(p);
+}
+
+/* Recording a "e" line ending an hbox this message is sent whenever an hlist
+ * has been shipped out it is used to close the hlist nesting level. It is
+ * sent at the end of the hlist_out procedure in *TeX.web to balance a former
+ * synctex_hlist sent at the beginning of that procedure. */
+void synctextsilh(halfword p)
+{
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctextsilh\n");
+# endif
+ if (SYNCTEX_IGNORE(p)) {
+ return;
+ }
+ /* is there a pending info to be recorded */
+ if (NULL != synctex_ctxt.recorder) {
+ /* synctex_ctxt node is set and must be recorded as last node */
+ (*synctex_ctxt.recorder) (synctex_ctxt.p);
+ synctex_ctxt.p = 0; /* force next node to be recorded! */
+ synctex_ctxt.recorder = NULL;
+ }
+ fputs("e\n", synctex_ctxt.file);
+}
+
+# undef SYNCTEX_IGNORE
+# define SYNCTEX_IGNORE(NODE) (0 != (SYNCTEX_OPTIONS & SYNCTEX_DISABLED_MASK) ) \
+ || (0 == SYNCTEX_IS_ENABLED) \
+ || (0 >= SYNCTEX_TAG(NODE)) \
+ || (0 >= SYNCTEX_LINE(NODE)) \
+ || (0 == synctex_ctxt.file)
+# undef SYNCTEX_TAG
+# undef SYNCTEX_LINE
+/* glue code: these only work with nodes of size medium_node_size */
+# define small_node_size 2
+/* see: @d small_node_size=2 {number of words to allocate for most node types} */
+# define medium_node_size (small_node_size+synchronization_field_size)
+# ifdef XeTeX
+# define SYNCTEX_TAG(NODE) mem[NODE+medium_node_size-1].hh.lhfield
+# define SYNCTEX_LINE(NODE) mem[NODE+medium_node_size-1].hh.rh
+# else
+# define SYNCTEX_TAG(NODE) mem[NODE+medium_node_size-2].cint
+# define SYNCTEX_LINE(NODE) mem[NODE+medium_node_size-1].cint
+# endif
+
+/* This macro will detect a change in the synchronization context. As long as
+ * the synchronization context remains the same, there is no need to write
+ * synchronization info: it would not help more. The synchronization context
+ * has changed when either the line number or the file tag has changed. */
+# define SYNCTEX_CONTEXT_DID_CHANGE ((0 == synctex_ctxt.p)\
+ || (SYNCTEX_TAG(p) != SYNCTEX_TAG(synctex_ctxt.p))\
+ || (SYNCTEX_LINE(p) != SYNCTEX_LINE(synctex_ctxt.p)))
+
+/* Recording a "$:..." line */
+void synctex_math_recorder(halfword p)
+{
+ fprintf(synctex_ctxt.file, "$:%u:%u(%i,%i)\n",
+ SYNCTEX_TAG(p), SYNCTEX_LINE(p),
+ synctex_ctxt.h UNIT,
+ synctex_ctxt.v UNIT);
+ ++synctex_ctxt.count;
+}
+
+/* glue code this message is sent whenever an inline math node will ship out
+ See: @ @<Output the non-|char_node| |p| for... */
+void synctexmath(halfword p)
+{
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctexmath\n");
+# endif
+ if (SYNCTEX_IGNORE(p)) {
+ return;
+ }
+ if ((synctex_ctxt.recorder != NULL) && SYNCTEX_CONTEXT_DID_CHANGE) {
+ /* the sync context did change */
+ (*synctex_ctxt.recorder) (synctex_ctxt.p);
+ }
+ synctex_ctxt.h = curh;
+ synctex_ctxt.v = curv;
+ synctex_ctxt.p = p;
+ synctex_ctxt.recorder = NULL;/* no need to record once more */
+ synctex_math_recorder(p);/* always record */
+}
+
+/* Recording a "g:..." line */
+void synctex_glue_recorder(halfword p)
+{
+ fprintf(synctex_ctxt.file, "g:%u:%u(%i,%i)\n",
+ SYNCTEX_TAG(p), SYNCTEX_LINE(p),
+ synctex_ctxt.h UNIT,
+ synctex_ctxt.v UNIT);
+ ++synctex_ctxt.count;
+}
+
+/* this message is sent whenever a glue node ships out
+ See: @ @<Output the non-|char_node| |p| for... */
+void synctexglue(halfword p)
+{
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctexglue\n");
+# endif
+ if (SYNCTEX_IGNORE(p)) {
+ return;
+ }
+ if (SYNCTEX_CONTEXT_DID_CHANGE) {
+ /* the sync context has changed */
+ if (synctex_ctxt.recorder != NULL) {
+ /* but was not yet recorded */
+ (*synctex_ctxt.recorder) (synctex_ctxt.p);
+ }
+ synctex_ctxt.h = curh;
+ synctex_ctxt.v = curv;
+ synctex_ctxt.p = p;
+ synctex_ctxt.recorder = NULL;
+ /* always record when the context has just changed */
+ synctex_glue_recorder(p);
+ } else {
+ /* just update the geometry and type (for future improvements) */
+ synctex_ctxt.h = curh;
+ synctex_ctxt.v = curv;
+ synctex_ctxt.p = p;
+ synctex_ctxt.recorder = &synctex_glue_recorder;
+ }
+}
+
+/* Recording a "k:..." line */
+void synctex_kern_recorder(halfword p)
+{
+ fprintf(synctex_ctxt.file, "k:%u:%u(%i,%i,%i)\n",
+ SYNCTEX_TAG(p), SYNCTEX_LINE(p),
+ synctex_ctxt.h UNIT,
+ synctex_ctxt.v UNIT,
+ SYNCTEX_WIDTH(p) UNIT);
+ ++synctex_ctxt.count;
+}
+
+/* this message is sent whenever a kern node ships out
+ See: @ @<Output the non-|char_node| |p| for... */
+void synctexkern(halfword p)
+{
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctexkern\n");
+# endif
+ if (SYNCTEX_IGNORE(p)) {
+ return;
+ }
+ if (SYNCTEX_CONTEXT_DID_CHANGE || (SYNCTEX_WIDTH(p)<0)) {
+ /* the sync context has changed */
+ if (synctex_ctxt.recorder != NULL) {
+ /* but was not yet recorded */
+ (*synctex_ctxt.recorder) (synctex_ctxt.p);
+ }
+ synctex_ctxt.h = curh;
+ synctex_ctxt.v = curv;
+ synctex_ctxt.p = p;
+ synctex_ctxt.recorder = NULL;
+ /* always record when the context has just changed */
+ synctex_kern_recorder(p);
+ } else {
+ /* just update the geometry and type (for future improvements) */
+ synctex_ctxt.h = curh;
+ synctex_ctxt.v = curv;
+ synctex_ctxt.p = p;
+ synctex_ctxt.recorder = &synctex_kern_recorder;
+ }
+}
+
+/* Free all memory used and close the file, sent by utils.c */
+void synctex_terminate(void)
+{
+# if SYNCTEX_DEBUG
+ fprintf(stdout, "\nSynchronize DEBUG: synctex_terminate\n");
+# endif
+ if (synctex_ctxt.file != NULL) {
+ fprintf(synctex_ctxt.file, "#:%u\n",synctex_ctxt.count);
+ xfclose(synctex_ctxt.file, synctex_ctxt.name);
+ xfree(synctex_ctxt.name);
+ }
+ xfree(synctex_ctxt.root_name);
+}
+
+#endif
diff --git a/Build/source/texk/web2c/synctex/synctex.ch b/Build/source/texk/web2c/synctex/synctex.ch
new file mode 100644
index 00000000000..cd207ffe55f
--- /dev/null
+++ b/Build/source/texk/web2c/synctex/synctex.ch
@@ -0,0 +1,860 @@
+Copyright (c) 2008 jerome DOT laurens AT u-bourgogne DOT fr
+
+This file is part of the SyncTeX package.
+
+License:
+--------
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included 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 WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE
+
+Except 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.
+
+Notice:
+-------
+This file contains TeX changes for core synctex support.
+It is missing some implementation details that are deferred to either
+sync-pdftex.ch or sync-xetex.ch
+synctex.ch is based on tex.web after the eTeX changes have been applied.
+So it might not apply as is to pdftex.web due to some typographical changes.
+In the building process, one may have to apply some suitable tex.ch0 first.
+See pdftexdir for details.
+
+@x
+found: link(r):=null; {this node is now nonempty}
+@!stat var_used:=var_used+s; {maintain usage statistics}
+tats@;@/
+get_node:=r;
+exit:end;
+@y
+found: link(r):=null; {this node is now nonempty}
+@!stat var_used:=var_used+s; {maintain usage statistics}
+tats@;@/
+@<Initialize bigger nodes with {\sl synctex} information@>;
+get_node:=r;
+exit:end;
+@z
+
+The |synctex_field_size| depends on the TeX implementation.
+pdfTeX uses 2 additional words whereas XeTeX will only use one,
+because it naturally has bigger words of memory.
+@x
+@d hlist_node=0 {|type| of hlist nodes}
+@d box_node_size=7 {number of words to allocate for a box node}
+@y
+@d synctex_engine_pdftex=0
+@d synctex_engine_xetex=1
+@d synctex_field_size=MISSING IMPLEMENTATION
+
+@d hlist_node=0 {|type| of hlist nodes}
+@d box_node_size=7+synctex_field_size {number of words to allocate for a box node}
+@z
+
+@x
+@d small_node_size=2 {number of words to allocate for most node types}
+@y
+@d small_node_size=2 {number of words to allocate for most node types}
+@d medium_node_size=small_node_size+synctex_field_size {number of words to
+ allocate for synchronized node types like math, kern and glue nodes}
+@z
+
+@x
+@p function new_math(@!w:scaled;@!s:small_number):pointer;
+var p:pointer; {the new node}
+begin p:=get_node(small_node_size); type(p):=math_node;
+subtype(p):=s; width(p):=w; new_math:=p;
+end;
+@y
+@p function new_math(@!w:scaled;@!s:small_number):pointer;
+var p:pointer; {the new node}
+begin p:=get_node(medium_node_size); type(p):=math_node;
+ {{\sl synctex} node size watch point: proper size}
+subtype(p):=s; width(p):=w; new_math:=p;
+end;
+@z
+
+@x
+@p function new_param_glue(@!n:small_number):pointer;
+var p:pointer; {the new node}
+@!q:pointer; {the glue specification}
+begin p:=get_node(small_node_size); type(p):=glue_node; subtype(p):=n+1;
+@y
+@p function new_param_glue(@!n:small_number):pointer;
+var p:pointer; {the new node}
+@!q:pointer; {the glue specification}
+begin p:=get_node(medium_node_size); type(p):=glue_node; subtype(p):=n+1;
+ {{\sl synctex} watch point: proper size}
+@z
+
+
+@x
+@p function new_glue(@!q:pointer):pointer;
+var p:pointer; {the new node}
+begin p:=get_node(small_node_size); type(p):=glue_node; subtype(p):=normal;
+@y
+@p function new_glue(@!q:pointer):pointer;
+var p:pointer; {the new node}
+begin p:=get_node(medium_node_size); type(p):=glue_node; subtype(p):=normal;
+ {{\sl synctex} watch point: proper size}
+@z
+
+
+@x
+@p function new_kern(@!w:scaled):pointer;
+var p:pointer; {the new node}
+begin p:=get_node(small_node_size); type(p):=kern_node;
+@y
+@p function new_kern(@!w:scaled):pointer;
+var p:pointer; {the new node}
+begin p:=get_node(medium_node_size); type(p):=kern_node;
+ {{\sl synctex} whatch point: proper |kern_node| size}
+@z
+
+
+@x
+ glue_node: begin fast_delete_glue_ref(glue_ptr(p));
+ if leader_ptr(p)<>null then flush_node_list(leader_ptr(p));
+ end;
+ kern_node,math_node,penalty_node: do_nothing;
+@y
+ glue_node: begin fast_delete_glue_ref(glue_ptr(p));
+ if leader_ptr(p)<>null then flush_node_list(leader_ptr(p));
+ free_node(p, medium_node_size); {{\sl synctex} watch point: proper size}
+ goto done;
+ end;
+ kern_node,math_node:begin
+ free_node(p, medium_node_size); {{\sl synctex} watch point: proper size}
+ goto done;
+ end;
+ penalty_node: do_nothing;
+@z
+
+
+@x
+@ @<Case statement to copy...@>=
+case type(p) of
+hlist_node,vlist_node,unset_node: begin r:=get_node(box_node_size);
+@y
+@ @<Case statement to copy...@>=
+case type(p) of
+hlist_node,vlist_node,unset_node: begin r:=get_node(box_node_size);
+ @<Copy the box {\sl synctex} information@>;
+@z
+
+
+@x
+glue_node: begin r:=get_node(small_node_size); add_glue_ref(glue_ptr(p));
+ glue_ptr(r):=glue_ptr(p); leader_ptr(r):=copy_node_list(leader_ptr(p));
+ end;
+kern_node,math_node,penalty_node: begin r:=get_node(small_node_size);
+ words:=small_node_size;
+ end;
+@y
+glue_node: begin r:=get_node(medium_node_size); add_glue_ref(glue_ptr(p));
+ {{\sl synctex} node size watch point: proper size}
+ @<Copy the glue {\sl synctex} information@>;
+ glue_ptr(r):=glue_ptr(p); leader_ptr(r):=copy_node_list(leader_ptr(p));
+ end;
+kern_node,math_node:
+begin
+ words:=medium_node_size;
+ {{\sl synctex}: proper size, do not copy the {\sl synctex} information}
+ r:=get_node(words);
+end;
+penalty_node: begin r:=get_node(small_node_size);
+ words:=small_node_size;
+ end;
+@z
+
+next change is etex based
+@x
+@d etex_int_pars=eTeX_state_code+eTeX_states {total number of \eTeX's integer parameters}
+@#
+@d int_pars=etex_int_pars {total number of integer parameters}
+@y
+@d etex_int_pars=eTeX_state_code+eTeX_states {total number of \eTeX's integer parameters}
+@#
+@d synctex_code=etex_int_pars {{\sl synctex}: for the \.{\\synctex} macro}
+@d synctex_int_pars=synctex_code+1 {total number of \TeX's integer parameters}
+@#
+@d int_pars=synctex_int_pars {total number of integer parameters}
+@z
+
+next change is etex based
+@x
+@d tracing_assigns==int_par(tracing_assigns_code)
+@y
+@d synctex == int_par(synctex_code)
+@#
+@d tracing_assigns==int_par(tracing_assigns_code)
+@z
+
+next change is etex based
+@x
+@/@<Cases for |print_param|@>@/
+othercases print("[unknown integer parameter!]")
+endcases;
+@y
+@/@<synctex case for |print_param|@>@/
+@/@<Cases for |print_param|@>@/
+othercases print("[unknown integer parameter!]")
+endcases;
+@z
+
+@x
+@!in_state_record = record
+ @!state_field, @!index_field: quarterword;
+ @!start_field,@!loc_field, @!limit_field, @!name_field: halfword;
+ end;
+@y
+@!in_state_record = record
+ @!state_field, @!index_field: quarterword;
+ @!start_field,@!loc_field, @!limit_field, @!name_field: halfword;
+ @!synctex_tag_field: integer; {stack the tag of the current file}
+ end;
+@z
+
+@x
+@d name==cur_input.name_field {name of the current file}
+@y
+@d name==cur_input.name_field {name of the current file}
+@d synctex_tag==cur_input.synctex_tag_field {{\sl synctex} tag of the current file}
+@z
+
+
+@x
+name:=0; {|terminal_input| is now |true|}
+end;
+@y
+name:=0; {|terminal_input| is now |true|}
+@<Prepare terminal input {\sl synctex} information@>;
+end;
+@z
+
+
+@x
+@<Read the first line of the new file@>;
+end;
+@y
+@<Prepare new file {\sl synctex} information@>;
+@<Read the first line of the new file@>;
+end;
+@z
+
+next change is etex based
+@x
+@<Initialize |hlist_out| for mixed direction typesetting@>;
+left_edge:=cur_h;
+while p<>null do @<Output node |p| for |hlist_out| and move to the next node,
+ maintaining the condition |cur_v=base_line|@>;
+@<Finish |hlist_out| for mixed direction typesetting@>;
+@y
+@<Initialize |hlist_out| for mixed direction typesetting@>;
+left_edge:=cur_h;
+@<Start hlist {\sl synctex} information record@>;
+while p<>null do @<Output node |p| for |hlist_out| and move to the next node,
+ maintaining the condition |cur_v=base_line|@>;
+@<Finish hlist {\sl synctex} information record@>;
+@<Finish |hlist_out| for mixed direction typesetting@>;
+@z
+
+@x
+whatsit_node: @<Output the whatsit node |p| in an hlist@>;
+glue_node: @<Move right or output leaders@>;
+@y
+whatsit_node: @<Output the whatsit node |p| in an hlist@>;
+glue_node: begin
+ @<Record |glue_node| {\sl synctex} information@>
+ @<Move right or output leaders@>;
+end;
+@z
+
+next change is etex based
+@x
+kern_node:cur_h:=cur_h+width(p);
+math_node: @<Handle a math node in |hlist_out|@>;
+@y
+kern_node: begin
+ @<Record |kern_node| {\sl synctex} information@>;
+ cur_h:=cur_h+width(p);
+end;
+math_node: begin
+ @<Record |math_node| {\sl synctex} information@>;
+ @<Handle a math node in |hlist_out|@>;
+end;
+@z
+
+@x
+@!old_setting:0..max_selector; {saved |selector| setting}
+begin if tracing_output>0 then
+ begin print_nl(""); print_ln;
+ print("Completed box being shipped out");
+@.Completed box...@>
+@y
+@!old_setting:0..max_selector; {saved |selector| setting}
+begin
+@<Record sheet {\sl synctex} information@>
+if tracing_output>0 then
+ begin print_nl(""); print_ln;
+ print("Completed box being shipped out");
+@.Completed box...@>
+@z
+
+@x
+ if r<>null then if link(r)=null then if not is_char_node(r) then
+ if type(r)=kern_node then {unneeded italic correction}
+ begin free_node(r,small_node_size); link(q):=null;
+ end;
+ end
+@y
+ if r<>null then if link(r)=null then if not is_char_node(r) then
+ if type(r)=kern_node then {unneeded italic correction}
+ begin free_node(r,medium_node_size); link(q):=null; {{\sl synctex}: r is a |kern_node|}
+ end;
+ end
+@z
+
+
+@x
+ p:=lig_stack; lig_stack:=link(p); free_node(p,small_node_size);
+@y
+ p:=lig_stack; lig_stack:=link(p);
+ free_node(p,small_node_size); {{\sl synctex} node size watch point: proper size!}
+@z
+
+@x
+if w<>0 then
+ begin link(t):=new_kern(w); t:=link(t); w:=0;
+ end;
+@y
+if w<>0 then
+ begin link(t):=new_kern(w); t:=link(t); w:=0;
+ MISSING IMPLEMENTATION: 0 synctag for medium sized node at mem[t]
+ end;
+@z
+
+@x
+@<Initialize the special list...@>=
+type(page_head):=glue_node; subtype(page_head):=normal;
+@y
+@<Initialize the special list...@>=
+type(page_head):=glue_node; subtype(page_head):=normal;
+ {{\sl synctex} watch point: box(|page_head|) size >= |glue_node| size}
+@z
+
+@x
+@<Move the cursor past a pseudo-ligature...@>=
+main_p:=lig_ptr(lig_stack);
+if main_p>null then tail_append(main_p);
+temp_ptr:=lig_stack; lig_stack:=link(temp_ptr);
+free_node(temp_ptr,small_node_size);
+@y
+@<Move the cursor past a pseudo-ligature...@>=
+main_p:=lig_ptr(lig_stack);
+if main_p>null then tail_append(main_p);
+temp_ptr:=lig_stack; lig_stack:=link(temp_ptr);
+free_node(temp_ptr,small_node_size); {{\sl synctex} node size watch point: proper size!}
+@z
+
+next change is etex based
+@x
+ if subtype(p)<a_leaders then
+ begin type(p):=kern_node; width(p):=rule_wd;
+ end
+@y
+ if subtype(p)<a_leaders then
+ begin type(p):=kern_node; width(p):=rule_wd;
+ {{\sl synctex} node size watch point: |glue_node| size == |kern_node| size}
+ end
+@z
+
+next change is etex based
+@x
+ if (type(tail)=math_node)and(subtype(tail)=begin_M_code) then
+ begin free_node(LR_temp,small_node_size); p:=head;
+ while link(p)<>tail do p:=link(p);
+ free_node(tail,small_node_size); link(p):=null; tail:=p; goto done;
+ end;
+@y
+ if (type(tail)=math_node)and(subtype(tail)=begin_M_code) then
+ begin free_node(LR_temp,small_node_size); p:=head;
+ while link(p)<>tail do p:=link(p);
+ free_node(tail,medium_node_size); link(p):=null; tail:=p; goto done;
+ {{\sl synctex} node size watch point: proper size for |math_node|}
+ end;
+@z
+
+next change is etex based
+@x
+@ @<Adjust \(t)the LR stack for the |hp...@>=
+if end_LR(p) then
+ if info(LR_ptr)=end_LR_type(p) then pop_LR
+ else begin incr(LR_problems); type(p):=kern_node; subtype(p):=explicit;
+ end
+else push_LR(p)
+@y
+@ @<Adjust \(t)the LR stack for the |hp...@>=
+if end_LR(p) then
+ if info(LR_ptr)=end_LR_type(p) then pop_LR
+ else begin incr(LR_problems); type(p):=kern_node; subtype(p):=explicit;
+ {{\sl synctex} node size watch point: |math_node| size == |kern_node| size}
+ end
+else push_LR(p)
+@z
+
+next change is etex based
+@x
+ if LR_dir(p)<>cur_dir then
+ @<Reverse an hlist segment and |goto reswitch|@>;
+ end;
+type(p):=kern_node;
+end
+@y
+ if LR_dir(p)<>cur_dir then
+ @<Reverse an hlist segment and |goto reswitch|@>;
+ end;
+type(p):=kern_node;
+ {{\sl synctex} node size watch point: |math_node| size == |kern_node| size}
+end
+@z
+
+next change is etex based
+@x
+@<Reverse the complete hlist...@>=
+begin save_h:=cur_h; temp_ptr:=p; p:=new_kern(0); link(prev_p):=p;
+@y
+@<Reverse the complete hlist...@>=
+begin save_h:=cur_h; temp_ptr:=p; p:=new_kern(0);
+MISSING IMPLEMENTATION: 0 synctag for medium sized node at mem[p]
+link(prev_p):=p;
+@z
+
+next change is etex based
+@x
+@<Reverse an hlist segment...@>=
+begin save_h:=cur_h; temp_ptr:=link(p); rule_wd:=width(p);
+free_node(p,small_node_size);
+@y
+@<Reverse an hlist segment...@>=
+begin save_h:=cur_h; temp_ptr:=link(p); rule_wd:=width(p);
+free_node(p,medium_node_size); {{\sl synctex}: p is a |math_node|}
+@z
+
+next change is etex based
+@x
+if type(p)=kern_node then if (rule_wd=0)or(l=null) then
+ begin free_node(p,small_node_size); p:=l;
+ end;
+@y
+if type(p)=kern_node then if (rule_wd=0)or(l=null) then
+ begin free_node(p,medium_node_size); p:=l;
+ {{\sl synctex} node size watch: proper size for |kern_node|}
+ end;
+@z
+
+next change is etex based
+@x
+math_node: begin rule_wd:=width(p);
+if end_LR(p) then
+ if info(LR_ptr)<>end_LR_type(p) then
+ begin type(p):=kern_node; incr(LR_problems);
+ end
+ else begin pop_LR;
+ if n>min_halfword then
+ begin decr(n); decr(subtype(p)); {change |after| into |before|}
+ end
+ else begin type(p):=kern_node;
+ if m>min_halfword then decr(m)
+ else @<Finish the reversed hlist segment and |goto done|@>;
+ end;
+@y
+math_node: begin rule_wd:=width(p);
+if end_LR(p) then
+ if info(LR_ptr)<>end_LR_type(p) then
+ begin type(p):=kern_node; incr(LR_problems);
+ {{\sl synctex} node size watch point: |math_node| size == |kern_node| size}
+ end
+ else begin pop_LR;
+ if n>min_halfword then
+ begin decr(n); decr(subtype(p)); {change |after| into |before|}
+ end
+ else begin type(p):=kern_node;
+ {{\sl synctex} node size watch point: |math_node| size == |kern_node| size}
+ if m>min_halfword then decr(m)
+ else @<Finish the reversed hlist segment and |goto done|@>;
+ end;
+@z
+
+next change is etex based
+@x
+ if (n>min_halfword)or(LR_dir(p)<>cur_dir) then
+ begin incr(n); incr(subtype(p)); {change |before| into |after|}
+ end
+ else begin type(p):=kern_node; incr(m);
+ end;
+ end;
+end;
+@y
+ if (n>min_halfword)or(LR_dir(p)<>cur_dir) then
+ begin incr(n); incr(subtype(p)); {change |before| into |after|}
+ end
+ else begin type(p):=kern_node; incr(m);
+ {{\sl synctex} node size watch point: |math_node| size == |kern_node| size}
+ end;
+ end;
+end;
+@z
+
+
+next change is etex based
+@x
+@<Finish the reversed...@>=
+begin free_node(p,small_node_size);
+link(t):=q; width(t):=rule_wd; edge_dist(t):=-cur_h-rule_wd; goto done;
+end
+@y
+@<Finish the reversed...@>=
+begin free_node(p,medium_node_size); {{\sl synctex}: p is a |kern_node|}
+link(t):=q; width(t):=rule_wd; edge_dist(t):=-cur_h-rule_wd; goto done;
+end
+@z
+
+next change is etex based
+@x
+ if is_char_node(p) then r:=get_avail
+ else case type(p) of
+ hlist_node,vlist_node: begin r:=get_node(box_node_size);
+ mem[r+6]:=mem[p+6]; mem[r+5]:=mem[p+5]; {copy the last two words}
+ words:=5; list_ptr(r):=null; {this affects |mem[r+5]|}
+ end;
+@y
+ if is_char_node(p) then r:=get_avail
+ else case type(p) of
+ hlist_node,vlist_node: begin r:=get_node(box_node_size);
+ @<Copy the box {\sl synctex} information@>;
+ mem[r+6]:=mem[p+6]; mem[r+5]:=mem[p+5]; {copy the last two words}
+ words:=5; list_ptr(r):=null; {this affects |mem[r+5]|}
+ end;
+@z
+
+next change is etex based
+@x
+ kern_node,math_node: begin r:=get_node(small_node_size);
+ words:=small_node_size;
+ end;
+ glue_node: begin r:=get_node(small_node_size); add_glue_ref(glue_ptr(p));
+ glue_ptr(r):=glue_ptr(p); leader_ptr(r):=null;
+ end;
+@y
+ kern_node,math_node: begin
+ words:=medium_node_size; {{\sl synctex}: proper size for math and kern}
+ r:=get_node(words);
+ end;
+ glue_node: begin r:=get_node(medium_node_size); add_glue_ref(glue_ptr(p));
+ {{\sl synctex}: proper size for glue}
+ @<Copy the glue {\sl synctex} information@>;
+ glue_ptr(r):=glue_ptr(p); leader_ptr(r):=null;
+ end;
+@z
+
+next change is etex based
+@x
+found:width(t):=width(p); link(t):=q; free_node(p,small_node_size);
+done:link(temp_head):=l;
+end;
+
+@ @<Adjust \(t)the LR stack for the |j...@>=
+if end_LR(p) then
+ if info(LR_ptr)<>end_LR_type(p) then
+ begin type(p):=kern_node; incr(LR_problems);
+ end
+ else begin pop_LR;
+ if n>min_halfword then
+ begin decr(n); decr(subtype(p)); {change |after| into |before|}
+ end
+ else begin if m>min_halfword then decr(m)@+else goto found;
+ type(p):=kern_node;
+ end;
+ end
+else begin push_LR(p);
+ if (n>min_halfword)or(LR_dir(p)<>cur_dir) then
+ begin incr(n); incr(subtype(p)); {change |before| into |after|}
+ end
+ else begin type(p):=kern_node; incr(m);
+ end;
+ end
+@y
+found:width(t):=width(p); link(t):=q; free_node(p,small_node_size);
+ {{\sl synctex}: Unused label, see below}
+done:link(temp_head):=l;
+end;
+
+@ @<Adjust \(t)the LR stack for the |j...@>=
+if end_LR(p) then
+ if info(LR_ptr)<>end_LR_type(p) then
+ begin type(p):=kern_node; incr(LR_problems);
+ {{\sl synctex} node size watch point: |math_node| size == |kern_node| size}
+ end
+ else begin pop_LR;
+ if n>min_halfword then
+ begin decr(n); decr(subtype(p)); {change |after| into |before|}
+ end
+ else begin if m>min_halfword then decr(m)@+else begin
+ width(t):=width(p); link(t):=q; free_node(p,medium_node_size);
+ {{\sl synctex}: no more "goto found", and proper node size}
+ goto done;
+ end;
+ type(p):=kern_node;
+ {{\sl synctex} node size watch point: |math_node| size == |kern_node| size}
+ end;
+ end
+else begin push_LR(p);
+ if (n>min_halfword)or(LR_dir(p)<>cur_dir) then
+ begin incr(n); incr(subtype(p)); {change |before| into |after|}
+ end
+ else begin type(p):=kern_node; incr(m);
+ {{\sl synctex} node size watch point: |math_node| size == |kern_node| size}
+ end;
+ end
+@z
+
+next change is etex based
+@x
+if tracing_scan_tokens>0 then
+ begin if term_offset>max_print_line-3 then print_ln
+ else if (term_offset>0)or(file_offset>0) then print_char(" ");
+ name:=19; print("( "); incr(open_parens); update_terminal;
+ end
+else name:=18
+@y
+if tracing_scan_tokens>0 then
+ begin if term_offset>max_print_line-3 then print_ln
+ else if (term_offset>0)or(file_offset>0) then print_char(" ");
+ name:=19; print("( "); incr(open_parens); update_terminal;
+ end
+else begin
+ name:=18;
+ @<Prepare pseudo file {\sl synctex} information@>;
+end
+@z
+
+@x
+@* \[54] System-dependent changes.
+This section should be replaced, if necessary, by any special
+modifications of the program
+@y
+@* \[53b] The {\sl synchronize texnology}.
+This section is devoted to the {\sl synchronize texnology}
+- or simply {\sl synctex} - used to synchronize between input and output.
+This section explains how synchronization basics are implemented.
+Before we enter into more technical details,
+let us recall in a few words what is synchronization.
+
+\TeX\ typesetting system clearly separates the input and the output material,
+and synchronization will provide a new link between both that can help
+text editors and viewers to work together.
+More precisely, forwards synchronization is the ability,
+given a location in the input source file,
+to find what is the corresponding place in the output.
+Backwards synchronization just performs the opposite:
+given a location in the output,
+retrieve the corresponding material in the input source file.
+
+For better code management and maintainance, we adopt a naming convention.
+Throughout this program, code related to the {\sl synchronize texnology} is tagged
+with the {\sl synctex} key word. Any code extract where {\sl synctex} plays
+its part, either explicitly or implicitly, (should) contain the string {\sl synctex}.
+This naming convention also holds for external files.
+Moreover, all the code related to {\sl synctex} is gathered in this section,
+except the definitions.
+
+Synchronization is achieved with the help of an auxiliary file named
+`\.{{\sl jobname}.synctex}' ({\sl jobname} is the contents of the
+\.{\\jobname} macro), where a {\sl synctex} controller implemented
+in the external |synctex.c| file will store geometrical information.
+This {\sl synctex} controller will take care of every technical details
+concerning the {\sl synctex} file, we will only focus on the messages
+the controller will receive from the \TeX\ program.
+
+The most accurate synchronization information should allow to map
+any character of the input source file to the corresponding location
+in the output, if relevant.
+Ideally, the synchronization information of the input material consists of
+the file name, the line and column numbers of every character.
+The synchronization information in the output is simply the page number and
+either point coordinates, or box dimensions and position.
+The problem is that the mapping between these informations is only known at
+ship out time, which means that we must keep track of the input
+synchronization information until the pages ship out.
+
+As \TeX\ only knows about file names and line numbers,
+but forgets the column numbers, we only consider a
+restricted input synchronization information called {\sl synctex information}.
+It consists of a unique file name identifier, the {\sl synctex file tag},
+and the line number.
+
+Keeping track of such information,
+should be different whether characters or nodes are involved.
+Actually, only certain nodes are involved in {\sl synctex},
+we call them {\sl synchronized nodes}.
+Synchronized nodes store the {\sl synctex} information in their last two words:
+the first one contains a {\sl synctex file tag} uniquely identifying
+the input file, and the second one contains the current line number,
+as returned by the \.{\\inputlineno} primitive.
+The |synctex_field_size| macro contains the necessary size to store
+the {\sl synctex} information in a node.
+
+When declaring the size of a new node, it is recommanded to use the following
+convention: if the node is synchronized, use a definition similar to
+|my_synchronized_node_size|={\sl xxx}+|synctex_field_size|.
+Moreover, one should expect that the {\sl synctex} information is always stored
+in the last two words of a synchronized node.
+
+@ By default, every node with a sufficiently big size is initialized
+at creation time in the |get_node| routine with the current
+{\sl synctex} information, whether or not the node is synchronized.
+One purpose is to set this information very early in order to minimize code
+dependencies, including forthcoming extensions.
+Another purpose is to avoid the assumption that every node type has a dedicated getter,
+where initialization should take place. Actually, it appears that some nodes are created
+using directly the |get_node| routine and not the dedicated constructor.
+And finally, initializing the node at only one place is less error prone.
+
+@ @<Initialize bigger nodes with {\sl synctex} information@>=
+if s>=medium_node_size then
+begin
+ MISSING IMPLEMENTATION: update the synctex information for node at mem[r] with size s
+end;
+
+@ Instead of storing the input file name, it is better to store just an identifier.
+Each time \TeX\ opens a new file, it notifies the {\sl synctex} controller with
+a |synctex_start_input| message.
+This controller will create a new {\sl synctex} file tag and
+will update the current input state record accordingly.
+If the input comes from the terminal or a pseudo file, the |synctex_tag| is set to 0.
+It results in automatically disabling synchronization for material
+input from the terminal or pseudo files.
+
+@ @<Prepare new file {\sl synctex} information@>=
+synctex_start_input; {Give control to the {\sl synctex} controller}
+
+@ @<Prepare terminal input {\sl synctex} information@>=
+synctex_tag:=0;
+
+@ @<Prepare pseudo file {\sl synctex} information@>=
+synctex_tag:=0;
+
+@ Synchronized nodes are boxes, math, kern and glue nodes.
+Other nodes should be synchronized too, in particular math noads.
+\TeX\ assumes that math, kern and glue nodes have the same size,
+this is why both are synchronized.
+{\sl In fine}, only horizontal lists are really used in {\sl synctex},
+but all box nodes are considered the same with respect to synchronization,
+because a box node type is allowed to change at execution time.
+
+The next sections are the various messages sent to the {\sl synctex} controller.
+The argument is either the box or the node currently shipped out.
+
+@ @<Start hlist {\sl synctex} information record@>=
+synctex_hlist(this_box);
+
+@ @<Finish hlist {\sl synctex} information record@>=
+synctex_tsilh(this_box);
+
+@ @<Record |glue_node| {\sl synctex} information@>=
+synctex_glue(p);
+
+@ @<Record |kern_node| {\sl synctex} information@>=
+synctex_kern(p);
+
+@ @<Record |math_node| {\sl synctex} information@>=
+synctex_math(p);
+
+@ @<Record sheet {\sl synctex} information@>=
+synctex_sheet(mag);
+
+@ When making a copy of a synchronized node, we might also have to duplicate
+the {\sl synctex} information by copying the two last words.
+This is the case for a |box_node| and for a |glue_node|,
+but not for a |math_node| nor a |kern_node|. These last two nodes always keep
+the {\sl synctex} information they received at creation time.
+
+@ @<Copy the box {\sl synctex} information@>=
+MISSING IMPLEMENTATION: copy the synctex information for box node at mem[r] from node at mem[p]
+
+@ @<Copy the glue {\sl synctex} information@>=
+MISSING IMPLEMENTATION: copy the synctex information for glue node at mem[r] from node at mem[p]
+
+@ Enabling synchronization should be performed from the command line,
+|synctexoption| is used for that purpose.
+This global integer variable is declared here but it is not used here.
+This is just a placeholder where the command line controller will put
+the {\sl {\sl synctex}} related options, and the {\sl synctex} controller will read them.
+
+@ @<Glob...@>=
+@!synctexoption:integer;
+
+@ A convenient primitive is provided:
+\.{\\synctex=1} in the input source file enables synchronization whereas
+\.{\\synctex=0} disables it.
+Its memory address is |synctex_code|.
+
+@ @<Put each...@>=
+primitive("synctex",assign_int,int_base+synctex_code);@/
+@!@:synctex_}{\.{\\synctex} primitive@>
+
+@ @<synctex case for |print_param|@>=
+synctex_code: print_esc("synctex");
+
+@ In order to give the {\sl synctex} controller read and write access to
+the contents of the \.{\\synctex} primitive, we declare |synctexoffset|,
+such that |mem[synctexoffset]| and \.{\\synctex} correpond to
+the same memory storage. |synctexoffset| is initialized to
+the correct value when quite everything is initialized.
+
+@ @<Glob...@>=
+@!synctexoffset:integer; {holds the true value of |synctex_code|}
+
+@ @<Initialize whatever...@>=
+synctexoffset:=int_base+synctex_code;
+
+@ {\sl Nota Bene:}
+The {\sl synctex} code is very close to the memory model.
+It is not connected to any other part of the code,
+except for memory management. It is possible to neutralize the {\sl synctex} code
+rather simply. The first step is to define a null |synctex_field_size|.
+The second step is to comment out the code in ``Initialize bigger nodes...'' and every
+``Copy ... {\sl synctex} information''.
+The last step will be to comment out the |synctex_tag_field| related code in the
+definition of |synctex_tag| and the various ``Prepare ... {\sl synctex} information''.
+Then all the remaining code should be just harmless.
+The resulting program would behave exactly the same as if absolutely no {\sl synctex}
+related code was there, including memory management.
+Of course, all this assumes that {\sl synctex} is turned off from the command line.
+@^synctex@>
+@^synchronization@>
+
+@* \[54] System-dependent changes.
+This section should be replaced, if necessary, by any special
+modifications of the program
+@z
diff --git a/Build/source/texk/web2c/synctex/synctex.defines b/Build/source/texk/web2c/synctex/synctex.defines
new file mode 100644
index 00000000000..357c77f5e8a
--- /dev/null
+++ b/Build/source/texk/web2c/synctex/synctex.defines
@@ -0,0 +1,49 @@
+{
+Copyright (c) 2008 jerome DOT laurens AT u-bourgogne DOT fr
+
+This file is part of the SyncTeX package.
+
+License:
+--------
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included 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 WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE
+
+Except 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.
+
+Notice:
+-------
+This file is an interface to the synctex system for web2c.
+}
+
+{ functions from the synctex controller in synctex.h }
+@define procedure synctexstartinput;
+@define procedure synctexsheet();
+@define procedure synctexhlist();
+@define procedure synctextsilh();
+@define procedure synctexmath();
+@define procedure synctexkern();
+@define procedure synctexglue();
+
+{ end of synctex.defines }
+{ vim: set syntax=web : }
diff --git a/Build/source/texk/web2c/synctex/synctex.h b/Build/source/texk/web2c/synctex/synctex.h
new file mode 100644
index 00000000000..98fcc29664f
--- /dev/null
+++ b/Build/source/texk/web2c/synctex/synctex.h
@@ -0,0 +1,61 @@
+/* synctex.h
+
+This file is part of the SyncTeX package.
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included 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 WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE
+
+*/
+
+# ifndef __SYNCTEX_HEADER__
+# define __SYNCTEX_HEADER__
+
+/* Send this message when starting a new input. */
+extern void synctexstartinput(void);
+
+/* Recording the "s:..." line. In *tex.web, use synctex_sheet(pdf_output) at
+ * the very beginning of the ship_out procedure.
+*/
+extern void synctexsheet(integer pdf_output);
+
+/* Send this message when an hlist will be shipped out, more precisely at
+ * the beginning of the hlist_out procedure in *TeX.web. It must be balanced
+ * by a synctex_tsilh, sent at the end of the hlist_out procedure. p is the
+ * address of the hlist. */
+extern void synctexhlist(halfword p);
+
+/* Sent this message at the end of the hlist_out procedure in *TeX.web
+ * to balance a former synctex_hlist. */
+extern void synctextsilh(halfword p);
+
+/* Send this message whenever an inline math node will ship out. */
+extern void synctexmath(halfword p);
+
+/* Send this message whenever a glue node will ship out. */
+extern void synctexglue(halfword p);
+
+/* Send this message whenever a kern node will ship out. */
+extern void synctexkern(halfword p);
+
+/* Send this message to clean memory. */
+extern void synctex_terminate(void);
+
+# endif \ No newline at end of file
diff --git a/Build/source/texk/web2c/synctex/synctex.mk b/Build/source/texk/web2c/synctex/synctex.mk
new file mode 100644
index 00000000000..5d77fddd5f3
--- /dev/null
+++ b/Build/source/texk/web2c/synctex/synctex.mk
@@ -0,0 +1,50 @@
+# Copyright (c) 2008 jerome DOT laurens AT u-bourgogne DOT fr
+#
+# This file is part of the SyncTeX package.
+#
+# License:
+# --------
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation
+# files (the "Software"), to deal in the Software without
+# restriction, including without limitation the rights to use,
+# copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following
+# conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included 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 WARRANTIES
+# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE
+#
+# Except 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.
+#
+# Notice:
+# -------
+# Makefile fragment for synctex.
+# It is included in web2c/Makefile.in
+
+# The C sources and headers
+synctex_o = synctex.o
+synctex.h: $(top_srcdir)/synctex/synctex.h
+ cat $(top_srcdir)/synctex/synctex.h >$@
+synctex.c: synctex.h $(top_srcdir)/synctex/synctex.c
+ cat $(top_srcdir)/synctex/synctex.c >$@
+
+# Cleaning up.
+clean:: synctex-clean
+synctex-clean:
+ -rm synctex.o synctex.h synctex.c
+
+# end of synctex.mk