iTeXMac on the WEB
SourceForge Logo
-
iTeXMac2 News
-
iTeXMac News
-
What is iTeXMac
-
Screen Shots
-
The pdfsync page
Screenshot
Download
Specifications
Example
Credits
-
Download Section
-
iTM Resources
-
iTM FAQ
-
Lists
-
iTM Bug reporter
-
iTM's future
-
iTM's developer section
-
Localize section
-
TeX section
-
Credits
 


This is the official pdfsync page.

This is the patch for embedding pdfsync into pdftex

Index: trunk/source/src/texk/web2c/lib/texmfmp.c
===================================================================
--- trunk/source/src/texk/web2c/lib/texmfmp.c	(revision 347)
+++ trunk/source/src/texk/web2c/lib/texmfmp.c	(working copy)
@@ -191,6 +191,10 @@
   kpse_record_input = recorder_record_input;
   kpse_record_output = recorder_record_output;
 
+#if defined (pdfTeX) || defined(__synchronize___)
+  synchronizeoption = 0;// means no synchronization
+#endif
+
 #if defined(pdfTeX)
   ptexbanner = BANNER;
 #endif
@@ -895,6 +899,9 @@
       { "no-shell-escape",           0, &shellenabledp, -1 },
       { "debug-format",              0, &debugformatfile, 1 },
       { "src-specials",              2, 0, 0 },
+#if defined(pdfTeX) || defined(__synchronize__)
+      { "synchronize",               1, 0, 0 },//Synchronization: just like interaction above
+#endif
 #endif /* TeX */
 #if defined (TeX) || defined (MF) || defined (MP)
       { "file-line-error-style",     0, &filelineerrorstylep, 1 },
@@ -1073,6 +1080,10 @@
     } else if (ARGUMENT_IS ("help")) {
         usagehelp (PROGRAM_HELP, BUG_ADDRESS);
 
+#if defined (pdfTeX) || defined(__synchronize___)
+    } else if (ARGUMENT_IS ("synchronize")) {
+		synchronizeoption = (int) strtoul(optarg, NULL, 0);// Synchronization: catching the command line option as an unsigned long
+ #endif
     } else if (ARGUMENT_IS ("version")) {
         char *versions;
 #if defined (pdfTeX) || defined(XeTeX)
Index: trunk/source/src/texk/web2c/pdftexdir/utils.c
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/utils.c	(revision 347)
+++ trunk/source/src/texk/web2c/pdftexdir/utils.c	(working copy)
@@ -441,6 +441,7 @@
     sfd_free();
     glyph_unicode_free();
     zip_free();
+    sync_terminate();
 }
 
 /* Converts any string given in in in an allowed PDF string which can be
Index: trunk/source/src/texk/web2c/pdftexdir/Makefile.in
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/Makefile.in	(revision 347)
+++ trunk/source/src/texk/web2c/pdftexdir/Makefile.in	(working copy)
@@ -47,7 +47,7 @@
 OBJS = epdf.o mapfile.o utils.o vfpacket.o pkin.o \
 writefont.o writet1.o writet3.o writezip.o writeenc.o writettf.o \
 writejpg.o writejbig2.o writepng.o writeimg.o pdftoepdf.o avl.o \
-avlstuff.o subfont.o tounicode.o pdflib.o
+avlstuff.o subfont.o tounicode.o pdflib.o synchronize.o
 
 all: libpdf.a makecpool
 
Index: trunk/source/src/texk/web2c/pdftexdir/synchronize.c
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/synchronize.c	(revision 0)
+++ trunk/source/src/texk/web2c/pdftexdir/synchronize.c	(revision 0)
@@ -0,0 +1,425 @@
+/*
+Copyright (c) 2008 Jerome.Laurens AT u-bourgogne.fr
+
+This file is part of pdfTeX.
+
+pdfTeX is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+pdfTeX is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with pdfTeX; if not, write to the Free Software Foundation, Inc., 51
+Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "ptexlib.h"
+
+/* Synchronization is explained in greater details in synchronization.readme/synchronize+Frames.pdf.*/
+
+#if defined(pdfTeX) || defined(__synchronize__)
+
+#define SYNC_DEBUG 0
+
+// Here are all the local variables
+
+static struct
+{
+	FILE *file; // the foo.sync I/O identifier
+	char *name; // the real "foo.sync" name
+	char *root_name; // in general jobname.tex
+	// 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
+	integer h, v; // its coordinates
+	integer offset; // the offset of the origin / the topleft of the page in both directions
+} sync_ctxt = {NULL,NULL,NULL,0,NULL,0,0,0};
+
+#define sync_version 1
+
+// 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 sync_ prefix prevents name conflicts, it is some kind of namespace
+#warning These structures MUST be kept in synchronization with the main program
+// synchronizeoption is a global integer variable defined in *tex.web
+// it is set to 1 by texmfmp.c if the command line has the '-synchronize' option.
+#define sync_options synchronizeoption
+#define sync_disabled_mask 0x80000000
+// if the sync_disabled_mask bit of sync_options is set, the synchronization is definitely disabled
+#define sync_ignore_cli_mask 0x40000000
+// if the sync_ignore_cli_mask bit of sync_options is set, the option given from the command line is ignored
+
+// glue code: really define the main memory
+#define mem zmem
+// glue code: synchronizeoffset is a global integer variable defined in *tex.web
+// it is set to the offset where the primitive \synchronize reads and writes its value.
+#define sync_is_enabled zeqtb[synchronizeoffset].cint
+// if there were a mean to share the value of synchronize_code between pdftex.web and this file, it would be great
+
+// sync_dot_open ensures that the foo.sync file is open.
+// In case of problem, it disables definitely synchronization
+// Now all the synchronization info is in one page.
+// It is possible to split this info into as many different files as sheets plus the 1
+// but the overall benefits are not so clear.
+static FILE * sync_dot_open(void)
+{
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open\n");
+		fprintf(stdout,"\nwarning: sync_is_enabled=%i\n",sync_is_enabled);
+		fprintf(stdout,"\nwarning: sync_options=%i\n",sync_options);
+	#endif
+	if(sync_options & sync_disabled_mask)
+		return 0;// synchronization is definitely disabled: do nothing
+
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open 1\n");
+	#endif
+    if (!sync_ctxt.file)
+	{
+		// this is the first time we are asked to open the file
+		// this part of code is executed only once:
+		// either sync_ctxt.file is nonnegative or synchronization is definitely disabled.
+		static char *suffix = ".sync";
+		char *s = makecstring(jobname);
+		char *j = xstrdup(s);
+		check_buf(strlen(s) + strlen(suffix) + 1, MAX_CSTRING_LEN);
+		strcat(s, suffix);
+		sync_ctxt.name = xstrdup(s);
+		sync_ctxt.file = xfopen(sync_ctxt.name, FOPEN_W_MODE);
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open 2\n");
+	#endif
+		if(sync_ctxt.file)
+		{
+			// print the preamble
+			fprintf(sync_ctxt.file,"synchronize\nversion:1\n",sync_version);
+			if(sync_ctxt.root_name)
+			{
+				fprintf(sync_ctxt.file,"i:1:%s\n",sync_ctxt.root_name);
+				xfree(sync_ctxt.root_name);
+				sync_ctxt.root_name = NULL;
+			}
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open 3-a\n");
+	#endif
+		}
+		else
+		{
+			sync_options = sync_disabled_mask;
+			// no .sync file available, disable synchronization
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nwarning: Synchronize DEBUG:sync_dot_open 3-b\n");
+	#endif
+		}
+		xfree(j);
+	}
+	return sync_ctxt.file;
+}
+
+// Each time TeX opens a file, it sends syncstartinput.
+// A new synchronization tag is created and stored in the synctag_field of the TeX current input context.
+// each node will record this tag instead of the file name
+// syncstartinput writes the mapping synctag <-> file name to the .sync file
+// a client will read the .sync file and retrieve this mapping
+// it will be able to open the correct file just knowing its tag.
+// If the same file is read more than once, it might be associated to different tags.
+// Viewers should be prepared to handle this situation.
+// 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
+// such that other components of the program can use it.
+void syncstartinput(void)
+{
+	static unsigned int synctag_counter = 0;
+
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nwarning: Synchronize DEBUG:syncstartinput %i\n",synctag_counter);
+		fprintf(stdout,"\nwarning: sync_is_enabled=%i\n",sync_is_enabled);
+		fprintf(stdout,"\nwarning: sync_options=%i\n",sync_options);
+		fprintf(stdout,"\nwarning: sync_disabled_mask=%i\n",sync_disabled_mask);
+	#endif
+
+	if((sync_options & sync_disabled_mask) != 0)
+	{
+		// this is where we disable synchronization -synchronization=-1
+		return;
+	}
+	// synctag_counter is a counter uniquely identifying the file actually open
+	// each time tex opens a new file, syncstartinput will increment this counter
+	if(~synctag_counter>0)
+	{
+		++synctag_counter;
+	}
+	else
+	{
+		// we have reached the limit, subsequent files will be softly ignored
+		// this makes a lot of files... even in 32 bits
+		curinput.synctagfield = 0;
+		return;
+	}
+	
+	if(0 == (sync_options & sync_ignore_cli_mask))
+	{
+		// the command line options are not ignored
+		sync_is_enabled = MAX(sync_options,sync_is_enabled);
+		sync_options |= sync_ignore_cli_mask;
+		// the command line options will be ignored from now on.
+		// every subsequent call of syncstartinput won't get there
+		// sync_options is now the list of option flags
+	}
+	
+	curinput.synctagfield = synctag_counter;// -> *TeX.web
+	if(synctag_counter==1)
+	{
+		// this is the first file TeX 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 dur to \jobname
+		sync_ctxt.root_name = xstrdup(makecstring(curinput.namefield));
+		return;
+	}
+	if(sync_ctxt.file || ((sync_is_enabled && sync_dot_open()) != 0))
+	{
+		fprintf(sync_ctxt.file,"i:%u:%s\n",curinput.synctagfield,makecstring(curinput.namefield));
+	}
+	return;
+}
+
+// All the sync... 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 global variables.
+// 
+
+// Recording the "s:..." line
+void syncsheet(integer pdf_output)
+{
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nSynchronize DEBUG:syncsheet\n");
+	#endif
+	if((sync_options & sync_disabled_mask) != 0)
+	{
+		return;
+	}
+	// update the offsets, depending on the output mode
+	sync_ctxt.offset = pdf_output?0:4736286;
+	if((sync_ctxt.file != 0) || ((sync_is_enabled && sync_dot_open()) != 0)) // tries to open the .sync, useful if synchronization was enabled from the source file and not from the CLI
+	{
+		if((totalpages == 0) && (pdf_output == 0))
+			fprintf(sync_ctxt.file,">:no pdf\n");
+		fprintf(sync_ctxt.file,"s:%u\n",(long int)totalpages+1);
+	}
+}
+
+#define UNIT / 8192
+// UNIT is the scale. TeX coordinates are very accurate and client won't need that 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.
+// IMPORTANT: We can say that the natural unit of .sync 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 is mainly to gain speed and size
+// maybe 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 point of the page
+// for pdftex, it is straightforward, but for dvi, we'll have to add the 1in offset in both directions.
+
+#warning This should be in sync with the eponym declarations in *tex.web
+#define box_node_size 9
+#define sync_width(NODE) mem[NODE+1].cint
+#define sync_depth(NODE) mem[NODE+2].cint
+#define sync_height(NODE) mem[NODE+3].cint
+#define sync_tag(NODE) mem[NODE+box_node_size-2].cint
+#define sync_line(NODE) mem[NODE+box_node_size-1].cint
+
+// 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 .sync file, we only display ker 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.
+// See details in the implementation of the functions below.
+
+#define SYNC_IGNORE(NODE) ((sync_options & sync_disabled_mask) != 0) \
+						|| (sync_is_enabled == 0) \
+						|| (sync_ctxt.file == 0)
+
+// Recording a "h:..." line
+void sync_hlist_recorder(halfword p)
+{
+    fprintf(sync_ctxt.file,"h:%u:%u(%i,%i,%i,%i)%i\n",
+		sync_tag(p), sync_line(p),
+			(curh + sync_ctxt.offset) UNIT, (curv+sync_depth(p) + sync_ctxt.offset) UNIT,
+				sync_width(p) UNIT, (sync_height(p)+sync_depth(p)) UNIT,
+					sync_depth(p) UNIT);
+}
+// This message is sent when an hlist will be shipped out.
+// p is the address of the hlist
+// We assume that p is really an hlist node!
+void synchlist(halfword p)
+{
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nSynchronize DEBUG:synchlist\n");
+	#endif
+	if(SYNC_IGNORE(p))
+		return;
+	sync_ctxt.p = 0;// reset
+	sync_ctxt.recorder = NULL;// reset
+	sync_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
+void synctsilh(halfword p)
+{
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nSynchronize DEBUG:synctsilh\n");
+	#endif
+	if(SYNC_IGNORE(p))
+		return;
+	// is there a pending info to be recorded
+	if(sync_ctxt.recorder)
+	{
+		// sync_ctxt node is set and must be recorded as last node
+		(*sync_ctxt.recorder)(sync_ctxt.p);
+		sync_ctxt.p = 0;// force next node to be recorded!
+		sync_ctxt.recorder = NULL;
+	} 
+	fputs("e\n", sync_ctxt.file);
+}
+
+#undef SYNC_IGNORE
+#define SYNC_IGNORE(NODE) ((sync_options & sync_disabled_mask) != 0) \
+						|| (sync_is_enabled == 0) \
+						|| (sync_tag(NODE)<=0) \
+						|| (sync_line(NODE)<=0) \
+						|| (sync_ctxt.file == 0)
+#undef sync_tag
+#undef sync_line
+// glue code: these only work with nodes of size medium_node_size
+#define medium_node_size 4
+#define sync_tag(NODE) mem[NODE+medium_node_size-2].cint
+#define sync_line(NODE) mem[NODE+medium_node_size-1].cint
+
+#define SYNC_CONTEXT_DID_CHANGE ((sync_ctxt.p == 0)\
+								|| (sync_tag(p) != sync_tag(sync_ctxt.p))\
+								|| (sync_line(p) != sync_line(sync_ctxt.p)))
+// Recording a "$:..." line
+void sync_math_recorder(halfword p)
+{
+	fprintf(sync_ctxt.file,"$:%u:%u(%i,%i)\n",
+		sync_tag(p), sync_line(p),
+			(sync_ctxt.h + sync_ctxt.offset) UNIT, (sync_ctxt.v + sync_ctxt.offset) UNIT);
+}
+// glue code this message is sent whenever an inline math node will ship out
+void syncmath(halfword p)
+{
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nSynchronize DEBUG:syncmath\n");
+	#endif
+	if(SYNC_IGNORE(p))
+		return;
+	if((sync_ctxt.recorder!=NULL) && SYNC_CONTEXT_DID_CHANGE)// the sync context did change
+		(*sync_ctxt.recorder)(sync_ctxt.p);
+	sync_ctxt.h = curh;
+	sync_ctxt.v = curv;
+	sync_ctxt.p = p;
+	sync_ctxt.recorder = NULL;// no need to record once more
+	sync_math_recorder(p);// always record
+}
+
+// Recording a "g:..." line
+void sync_glue_recorder(halfword p)
+{
+	fprintf(sync_ctxt.file,"g:%u:%u(%i,%i)\n",
+		sync_tag(p), sync_line(p),
+			(sync_ctxt.h + sync_ctxt.offset) UNIT, (sync_ctxt.v + sync_ctxt.offset) UNIT);
+}
+// this message is sent whenever a glue node ships out
+void syncglue(halfword p)
+{
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nSynchronize DEBUG:syncglue\n");
+	#endif
+	if(SYNC_IGNORE(p))
+		return;
+	if(SYNC_CONTEXT_DID_CHANGE)// the sync context has changed
+	{
+		if(sync_ctxt.recorder!=NULL) // was not recorded
+			(*sync_ctxt.recorder)(sync_ctxt.p);
+		sync_ctxt.h = curh;
+		sync_ctxt.v = curv;
+		sync_ctxt.p = p;
+		sync_ctxt.recorder = NULL;
+		sync_glue_recorder(p);// always record
+	}
+	else
+	{
+		// just update the geometry and type (for future improvements)
+		sync_ctxt.h = curh;
+		sync_ctxt.v = curv;
+		sync_ctxt.p = p;
+		sync_ctxt.recorder = &sync_glue_recorder;
+	}
+}
+
+// Recording a "k:..." line
+void sync_kern_recorder(halfword p)
+{
+	fprintf(sync_ctxt.file,"k:%u:%u(%i,%i)\n",
+		sync_tag(p), sync_line(p),
+			(sync_ctxt.h + sync_ctxt.offset) UNIT, (sync_ctxt.v + sync_ctxt.offset) UNIT);
+}
+// this message is sent whenever a kern node or a glue node ships out
+void synckern(halfword p)
+{
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nSynchronize DEBUG:synckern\n");
+	#endif
+	if(SYNC_IGNORE(p))
+		return;
+	if(SYNC_CONTEXT_DID_CHANGE)// the sync context has changed
+	{
+		if(sync_ctxt.recorder!=NULL) // was not recorded
+			(*sync_ctxt.recorder)(sync_ctxt.p);
+		sync_ctxt.h = curh;
+		sync_ctxt.v = curv;
+		sync_ctxt.p = p;
+		sync_ctxt.recorder = NULL;
+		sync_kern_recorder(p);
+	}
+	else
+	{
+		// just update the geometry and type (for future improvements)
+		sync_ctxt.h = curh;
+		sync_ctxt.v = curv;
+		sync_ctxt.p = p;
+		sync_ctxt.recorder = &sync_kern_recorder;
+	}
+}
+
+// Free all memory used and close the file
+// sent by utils.c
+void sync_terminate(void)
+{
+	#if SYNC_DEBUG
+		fprintf(stdout,"\nSynchronize DEBUG:sync_terminate\n");
+	#endif
+    if (sync_ctxt.file != NULL) {
+        xfclose(sync_ctxt.file, sync_ctxt.name);
+        xfree(sync_ctxt.name);
+    }
+	xfree(sync_ctxt.root_name);
+}
+
+#endif

Property changes on: trunk/source/src/texk/web2c/pdftexdir/synchronize.c
___________________________________________________________________
Name: svn:eol-style
   + native

Index: trunk/source/src/texk/web2c/pdftexdir/pdftex.defines
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/pdftex.defines	(revision 347)
+++ trunk/source/src/texk/web2c/pdftexdir/pdftex.defines	(working copy)
@@ -151,5 +151,14 @@
 { loadpdftexpool }
 @define function loadpoolstrings();
 
+{ functions from synchronize.c }
+@define procedure syncstartinput;
+@define procedure syncsheet();
+@define procedure synchlist();
+@define procedure synctsilh();
+@define procedure syncmath();
+@define procedure synckern();
+@define procedure syncglue();
+
 { end of pdftex.defines }
 { vim: set syntax=web : }
Index: trunk/source/src/texk/web2c/pdftexdir/pdftex.web
===================================================================
--- trunk/source/src/texk/web2c/pdftexdir/pdftex.web	(revision 347)
+++ trunk/source/src/texk/web2c/pdftexdir/pdftex.web	(working copy)
@@ -3188,6 +3188,11 @@
 found: link(r):=null; {this node is now nonempty}
 @!stat var_used:=var_used+s; {maintain usage statistics}
 tats@;@/
+if s>3 then {Synchronization: default initialization of the two last words to the current sync info}
+begin
+  mem[r+s-2].int := synctag;
+  mem[r+s-1].int := line;
+end;
 get_node:=r;
 exit:end;
 
@@ -3367,7 +3372,7 @@
 |fil|, |fill|, or |filll|). The |subtype| field is not used.
 
 @d hlist_node=0 {|type| of hlist nodes}
-@d box_node_size=7 {number of words to allocate for a box node}
+@d box_node_size=7+2 {number of words to allocate for a box node, Synchronization hook: +2 integers for synctag and line}
 @d width_offset=1 {position of |width| field in a box node}
 @d depth_offset=2 {position of |depth| field in a box node}
 @d height_offset=3 {position of |height| field in a box node}
@@ -3453,6 +3458,7 @@
 
 @d mark_node=4 {|type| of a mark node}
 @d small_node_size=2 {number of words to allocate for most node types}
+@d medium_node_size=small_node_size+2 {Synchonization: +2 integers for sync info in math_node, kern_node and glue_node}
 @d mark_ptr(#)==link(#+1) {head of the token list for a mark}
 @d mark_class(#)==info(#+1) {the mark class}
 
@@ -3585,8 +3591,9 @@
 
 @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;
+begin p:=get_node(medium_node_size); type(p):=math_node; {Synchronization: proper size}
+subtype(p):=s; width(p):=w;
+new_math:=p;
 end;
 
 @ \TeX\ makes use of the fact that |hlist_node|, |vlist_node|,
@@ -3681,7 +3688,7 @@
 @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;
+begin p:=get_node(medium_node_size); type(p):=glue_node; subtype(p):=n+1; {Synchronization: proper size}
 leader_ptr(p):=null;@/
 q:=@@t@>;
 glue_ptr(p):=q; incr(glue_ref_count(q));
@@ -3693,7 +3700,7 @@
 
 @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;
+begin p:=get_node(medium_node_size); type(p):=glue_node; subtype(p):=normal; {Synchronization: proper size}
 leader_ptr(p):=null; glue_ptr(p):=q; incr(glue_ref_count(q));
 new_glue:=p;
 end;
@@ -3760,7 +3767,7 @@
 
 @p function new_kern(@!w:scaled):pointer;
 var p:pointer; {the new node}
-begin p:=get_node(small_node_size); type(p):=kern_node;
+begin p:=get_node(medium_node_size); type(p):=kern_node; { Synchronization: proper size}
 subtype(p):=normal;
 width(p):=w;
 new_kern:=p;
@@ -4508,9 +4515,15 @@
       end;
     whatsit_node: @;
     glue_node: begin fast_delete_glue_ref(glue_ptr(p));
-      if leader_ptr(p)<>null then flush_node_list(leader_ptr(p));
+        if leader_ptr(p)<>null then flush_node_list(leader_ptr(p));
+        free_node(p, medium_node_size); {Synchronization: proper size}
+        goto done;
       end;
-    kern_node,math_node,penalty_node: do_nothing;
+    kern_node,math_node:begin
+        free_node(p, medium_node_size); {Synchronization: proper size}
+        goto done;
+      end;
+    penalty_node: do_nothing;
     margin_kern_node: begin
         free_avail(margin_char(p));
         free_node(p, margin_kern_node_size);
@@ -4583,6 +4596,7 @@
 @ @=
 case type(p) of
 hlist_node,vlist_node,unset_node: begin r:=get_node(box_node_size);
+  mem[r+7].int:=mem[p+7].int;mem[r+8].int:=mem[p+8].int; {Synchronization: copy the sync words}
   mem[r+6]:=mem[p+6]; mem[r+5]:=mem[p+5]; {copy the last two words}
   list_ptr(r):=copy_node_list(list_ptr(p)); {this affects |mem[r+5]|}
   words:=5;
@@ -4596,10 +4610,16 @@
   end;
 whatsit_node:@;
-glue_node: begin r:=get_node(small_node_size); add_glue_ref(glue_ptr(p));
+glue_node: begin r:=get_node(medium_node_size); add_glue_ref(glue_ptr(p)); {Synchronization: proper size}
+  mem[r+2].int:=mem[p+2].int;mem[r+3].int:=mem[p+3].int; {Synchronization: copy the sync words}
   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);
+kern_node,math_node:
+begin
+  words:=medium_node_size; {Synchronization: 2 integers more}
+  r:=get_node(words);
+end;
+penalty_node: begin r:=get_node(small_node_size);
   words:=small_node_size;
   end;
 margin_kern_node: begin
@@ -5675,7 +5695,10 @@
 @d eTeX_state_code=etex_int_base+10 {\eTeX\ state variables}
 @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}
+@d synchronize_code=etex_int_pars {Synchronization: generate extra info for source/output synchronization? the 2 next lines are modified too}
+@d sync_int_pars=synchronize_code+1 {total number of \TeX's integer parameters}
+@#
+@d int_pars=sync_int_pars {total number of integer parameters}
 @d count_base=int_base+int_pars {256 user \.{\\count} registers}
 @d del_code_base=count_base+256 {256 delimiter code mappings}
 @d dimen_base=del_code_base+256 {beginning of region 6}
@@ -5768,6 +5791,8 @@
 @d pdf_draftmode        == int_par(pdf_draftmode_code)
 @d pdf_inclusion_copy_font == int_par(pdf_inclusion_copy_font_code)
 @#
+@d synchronize == int_par(synchronize_code) {Synchronization}
+@#
 @d tracing_assigns==int_par(tracing_assigns_code)
 @d tracing_groups==int_par(tracing_groups_code)
 @d tracing_ifs==int_par(tracing_ifs_code)
@@ -5871,6 +5896,7 @@
 pdf_gen_tounicode_code:    print_esc("pdfgentounicode");
 pdf_draftmode_code:        print_esc("pdfdraftmode");
 pdf_inclusion_copy_font_code:    print_esc("pdfinclusioncopyfonts");
+synchronize_code:    print_esc("synchronize"); {Synchronization}
 @/@@/
 othercases print("[unknown integer parameter!]")
 endcases;
@@ -6051,6 +6077,14 @@
 primitive("pdfinclusioncopyfonts",assign_int,int_base+pdf_inclusion_copy_font_code);@/
 @!@:pdf_inclusion_copy_font_}{\.{\\pdfinclusioncopyfonts} primitive@>
 
+@ @=
+primitive("synchronize",assign_int,int_base+synchronize_code);@/{Synchronization}
+@!@:synchronize_}{\.{\\synchronize} primitive@>
+
+@ @=
+@!synchronizeoption:integer; {Synchronization glue: set from the command line, see below}
+@!synchronizeoffset:integer; {Synchronization glue: holds the true value of synchronize_code}
+
 @ @=
 assign_int: if chr_code=
@@ -7546,6 +7581,7 @@
 @d start==cur_input.start_field {starting position in |buffer|}
 @d limit==cur_input.limit_field {end of current line in |buffer|}
 @d name==cur_input.name_field {name of the current file}
+@d synctag==cur_input.synctag_field {Synchronization:tag of the current file}
 
 @ Let's look more closely now at the control variables
 (|state|,~|index|,~|start|,~|loc|,~|limit|,~|name|),
@@ -8164,6 +8200,7 @@
 grp_stack[index]:=cur_boundary; if_stack[index]:=cond_ptr;
 line_stack[index]:=line; start:=first; state:=mid_line;
 name:=0; {|terminal_input| is now |true|}
+synctag:=0; {Synchronization}
 end;
 
 @ Conversely, the variables must be downdated when such a level of input
@@ -12400,6 +12437,8 @@
 if name=str_ptr-1 then {we can conserve string pool space now}
   begin flush_string; name:=cur_name;
   end;
+synchronizeoffset:=int_base+synchronize_code; {Synchronization glue code}
+sync_start_input; {Synchronization hook: Take the appropriate actions before reading a new file}
 @;
 end;
 
@@ -14438,8 +14477,10 @@
 prev_p:=this_box+list_offset;
 @;
 left_edge:=cur_h;
+sync_hlist(this_box); {Synchronization hook: write info, descend one level}
 while p<>null do @;
+sync_tsilh(this_box); {Synchronization hook: write info, ascend one level}
 @;
 prune_movements(save_loc);
 if cur_s>0 then dvi_pop(save_loc);
@@ -14485,10 +14526,19 @@
   goto fin_rule;
   end;
 whatsit_node: @;
-glue_node: @;
-margin_kern_node,
-kern_node:cur_h:=cur_h+width(p);
-math_node: @;
+glue_node: begin
+  sync_glue(p); {Synchronization dvi hook: output glue info}
+  @;
+end;
+margin_kern_node:cur_h:=cur_h+width(p);
+kern_node: begin
+  sync_kern(p); {Synchronization dvi hook: output kern info}
+  cur_h:=cur_h+width(p);
+end;
+math_node: begin
+  sync_math(p); {Synchronization dvi hook: output math related info}
+  @;
+end;
 ligature_node: @;
 @/@@;
 othercases do_nothing
@@ -14789,7 +14839,9 @@
 @!j,@!k:0..9; {indices to first ten count registers}
 @!s:pool_pointer; {index into |str_pool|}
 @!old_setting:0..max_selector; {saved |selector| setting}
-begin if tracing_output>0 then
+begin
+  sync_sheet(pdf_output,h_offset,v_offset); {Synchronization dvi hook: write info for a new sheet}
+  if tracing_output>0 then
   begin print_nl(""); print_ln;
   print("Completed box being shipped out");
 @.Completed box...@>
@@ -18346,9 +18398,11 @@
 @;
 left_edge:=cur_h;
 @;
+sync_hlist(this_box); {Synchronization dvi hook: write info, descend one level}
 while p<>null do
     @;
+sync_tsilh(this_box); {Synchronization dvi hook: write info, ascend one level}
 @;
 decr(cur_s);
 end;
@@ -18383,10 +18437,19 @@
   goto fin_rule;
   end;
 whatsit_node: @;
-glue_node: @<(\pdfTeX) Move right or output leaders@>;
-margin_kern_node,
-kern_node:cur_h:=cur_h+width(p);
-math_node: @;
+glue_node: begin
+  sync_glue(p); {Synchronization hook: output glue info}
+  @<(\pdfTeX) Move right or output leaders@>;
+end;
+margin_kern_node:cur_h:=cur_h+width(p);
+kern_node: begin
+  sync_kern(p); {Synchronization hook: output kern info}
+  cur_h:=cur_h+width(p);
+end;
+math_node: begin
+  sync_math(p); {Synchronization hook: output math related info}
+  @;
+end;
 ligature_node: @;
 @/@@;
 othercases do_nothing
@@ -18657,7 +18720,9 @@
 save_image_procset: integer;  {to save |pdf_image_procset|}
 save_text_procset: integer;  {to save |pdf_text_procset|}
 pdf_last_resources: integer; {pointer to most recently generated Resources object}
-begin if tracing_output>0 then
+begin 
+  sync_sheet(pdf_output,h_offset,v_offset); {Synchronization hook: write info for a new sheet}
+  if tracing_output>0 then
   begin print_nl(""); print_ln;
   print("Completed box being shipped out");
 @.Completed box...@>
@@ -20456,7 +20521,7 @@
             update_adjust_list(pre_adjust_tail)
         else
             update_adjust_list(adjust_tail);
-        p := link(p); free_node(link(q), small_node_size);
+        p := link(p); free_node(link(q), small_node_size); {Synchronization watch point: p is not a synchronized node}
     end
 else  begin link(adjust_tail):=p; adjust_tail:=p; p:=link(p);
   end;
@@ -21670,7 +21735,7 @@
   begin r:=link(q);
   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;
+    begin free_node(r,medium_node_size); link(q):=null; {Synchronization: r is a kern_node}
     end;
   end
 
@@ -25871,7 +25936,8 @@
     begin link(t):=lig_ptr(lig_stack); {this is a charnode for |hu[j+1]|}
     t:=link(t); incr(j);
     end;
-  p:=lig_stack; lig_stack:=link(p); free_node(p,small_node_size);
+  p:=lig_stack; lig_stack:=link(p);
+  free_node(p,small_node_size); {Synchronization watch point: proper size!}
   if lig_stack=null then set_cur_r@+else cur_r:=character(lig_stack);
   end {if |lig_stack| isn't |null| we have |cur_rh=non_char|}
 
@@ -25879,6 +25945,7 @@
 wrap_lig(rt_hit);
 if w<>0 then
   begin link(t):=new_kern(w); t:=link(t); w:=0;
+  mem[t+2].int:=0; {Synchronization: do not synchronize, it is too late}
   end;
 if lig_stack>null then
   begin cur_q:=t; cur_l:=character(lig_stack); ligature_present:=true;
@@ -27363,7 +27430,7 @@
 the current page will not be considered a valid breakpoint.
 
 @=
-type(page_head):=glue_node; subtype(page_head):=normal;
+type(page_head):=glue_node; subtype(page_head):=normal; {Synchronization watch point: box(page_head) size >= glue_node size}
 
 @ The global variable |output_active| is true during the time the
 user's output routine is driving \TeX.
@@ -28251,7 +28318,7 @@
 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);
+free_node(temp_ptr,small_node_size); {Synchronization watch point: proper size!}
 main_i:=char_info(main_f)(cur_l); ligature_present:=true;
 if lig_stack=null then
   if main_p>null then goto main_loop_lookahead
@@ -36671,7 +36738,7 @@
     ((g_sign=shrinking) and (shrink_order(g)=g_order))) then
   begin fast_delete_glue_ref(g);
   if subtype(p)tail do p:=link(p);
-  free_node(tail,small_node_size); link(p):=null; tail:=p; goto done;
+  free_node(tail,medium_node_size); link(p):=null; tail:=p; goto done; {Synchronization: proper size for math_node}
   end;
 link(tail):=LR_temp; tail:=LR_temp;
 done: LR_temp:=null;
@@ -36862,7 +36929,7 @@
 @ @=
 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;
+  else  begin incr(LR_problems); type(p):=kern_node; subtype(p):=explicit; {Synchronization watch point: math_node size == kern_node size}
     end
 else push_LR(p)
 
@@ -36928,7 +36995,7 @@
   if LR_dir(p)<>cur_dir then
     @;
   end;
-type(p):=kern_node;
+type(p):=kern_node; {Synchronization watch point: math_node size == kern_node size}
 end
 
 @ @=
@@ -36962,7 +37029,9 @@
 append the reversed list, and set the width of the kern node.
 
 @=
-begin save_h:=cur_h; temp_ptr:=p; p:=new_kern(0); link(prev_p):=p;
+begin save_h:=cur_h; temp_ptr:=p; p:=new_kern(0);
+mem[p+2].int:=0; {Synchronization: do not synchronize this, it's too late}
+link(prev_p):=p;
 cur_h:=0; link(p):=reverse(this_box,null,cur_g,cur_glue); width(p):=-cur_h;
 cur_h:=save_h; subtype(this_box):=reversed;
 end
@@ -36974,7 +37043,7 @@
 
 @=
 begin save_h:=cur_h; temp_ptr:=link(p); rule_wd:=width(p);
-free_node(p,small_node_size);
+free_node(p,medium_node_size); {Synchronization: p is a math_node}
 cur_dir:=reflected; p:=new_edge(cur_dir,rule_wd); link(prev_p):=p;
 cur_h:=cur_h-left_edge+rule_wd;
 link(p):=reverse(this_box,new_edge(reflected,0),cur_g,cur_glue);
@@ -37033,7 +37102,7 @@
 cur_h:=cur_h+rule_wd;
 next_p: link(p):=l;
 if type(p)=kern_node then if (rule_wd=0)or(l=null) then
-  begin free_node(p,small_node_size); p:=l;
+  begin free_node(p,medium_node_size); p:=l; {Synchronization hook: proper size for kern_node}
   end;
 l:=p; p:=q;
 end
@@ -37060,13 +37129,13 @@
 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);
+    begin type(p):=kern_node; incr(LR_problems); {Synchronization 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;
+    else  begin type(p):=kern_node; {Synchronization watch point: math_node size == kern_node size}
       if m>min_halfword then decr(m)
       else @;
       end;
@@ -37075,7 +37144,7 @@
   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);
+  else  begin type(p):=kern_node; incr(m); {Synchronization watch point: math_node size == kern_node size}
     end;
   end;
 end;
@@ -37085,7 +37154,7 @@
 edge node terminating the reversed segment.
 
 @=
-begin free_node(p,small_node_size);
+begin free_node(p,medium_node_size); {Synchronization: p is a kern_node}
 link(t):=q; width(t):=rule_wd; edge_dist(t):=-cur_h-rule_wd; goto done;
 end
 
@@ -37125,6 +37194,7 @@
   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+7].int:=mem[p+7].int;mem[r+8].int:=mem[p+8].int; {Synchronization hook: copy the sync words}
     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;
@@ -37133,10 +37203,12 @@
   ligature_node: begin r:=get_avail; {only |font| and |character| are needed}
     mem[r]:=mem[lig_char(p)]; goto found;
     end;
-  kern_node,math_node: begin r:=get_node(small_node_size);
-    words:=small_node_size;
+  kern_node,math_node: begin
+      words:=medium_node_size; {Synchronization: proper size for math and kern}
+	  r:=get_node(words);
     end;
-  glue_node: begin r:=get_node(small_node_size); add_glue_ref(glue_ptr(p));
+  glue_node: begin r:=get_node(medium_node_size); add_glue_ref(glue_ptr(p)); {Synchronization: proper size for glue}
+    mem[r+2].int:=mem[p+2].int;mem[r+3].int:=mem[p+3].int; {Synchronization: copy the sync words}
     glue_ptr(r):=glue_ptr(p); leader_ptr(r):=null;
     end;
   whatsit_node:@;
@@ -37232,28 +37304,31 @@
     link(p):=l; l:=p;
     end;
 goto done;
-found:width(t):=width(p); link(t):=q; free_node(p,small_node_size);
+found:width(t):=width(p); link(t):=q; free_node(p,small_node_size); {Synchronization: Unused label, see below}
 done:link(temp_head):=l;
 end;
 
 @ @=
 if end_LR(p) then
   if info(LR_ptr)<>end_LR_type(p) then
-    begin type(p):=kern_node; incr(LR_problems);
+    begin type(p):=kern_node; incr(LR_problems); {Synchronization 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 goto found;
-      type(p):=kern_node;
+    else  begin if m>min_halfword then decr(m)@+else begin
+	    width(t):=width(p); link(t):=q; free_node(p,medium_node_size);{Synchronization: no more "goto found", proper size}
+	    goto done;
+	  end;
+	  type(p):=kern_node; {Synchronization 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);
+  else  begin type(p):=kern_node; incr(m); {Synchronization watch point: math_node size == kern_node size}
     end;
   end
 
@@ -37462,7 +37537,10 @@
   else if (term_offset>0)or(file_offset>0) then print_char(" ");
   name:=19; print("( "); incr(open_parens); update_terminal;
   end
-else name:=18
+else begin
+    name:=18;
+	synctag := 0; {Synchronization: no tag for the current file}
+end
 
 @ Here we read a line from the current pseudo file into |buffer|.
 			
-
Copyright 2004 jlaurens@users.sourceforge.net
Last update Tue Jan 13 08:56:03 GMT 2004
[News][What is it?][Screen shots][Download][Resources]
[FAQ][Lists][Bug][Next][Developer][Localize][TeX][Credits][top]