Das Dokument beschreibt die Synchronisation von Dokumenten mit Hilfe der priint:comet Plugins.

Ausgangspunkt sind ein sogenanntes Musterdokument (master) und beliebig viele Varianten (variants) des Musterdokumentes. Mit Hilfe der Synchronisation können dann nachträgliche Änderungen an der Musterdatei in die Varianten ünernommen werden, ohne dass dabei Änderungen in den Varianten überschrieben werden.

Die folgenden Änderungen im Musterdokument können synchronisiert werden:

Die Implementierung der Synchronisation wurde auf der Grundlage einen allgemeinen Situationsbeschreibung von Muster und Varianten und dem Arbeitsablauf damit gemacht. Zum Zeitpunkt der Implementierung standen keinerlei Testdokumente oder UseCases zur Verfügung. Wir haben die Implementierung daher "nach bestem Wissen und Gewissen" so gemacht, wie es die Anforderung nahelegt. Konfliktsituationen, die erst bei der Implementierung aufgefallen sind, haben wir versucht, bestmöglich zu lösen. Einzelheiten entnehmen Sie bitte den folgenden Beschreibungen.

Nicht enthalten sind in der Implementierung Wünsche nach Teil-Synchronisationen. Aus den vorliegenden Beschreibungen konnten wir dazu leider keine belastbaren Anforderungen ausfiltern.

Bewußt nicht implemtentiert haben wir die Übernahme von Freistellpfaden und anderer bild-relevanter Optionen von Bildrahmen. Wir gehen hier davon aus, dass Muster und Variante in aller Regel unterschiedliche Bilder enthalten, bei denen es sicher mehr schaden als nutzen würde, bildbezogene Daten zu übertragen. Sollte diese Option trotzdem gewünscht sein, kann das mit Hilfe von cScript-Funktionen auch von Drittanbietern direkt im mitgelieferten Sync-Skript angepasst werden. Eine plugin-seitig gezielte Registrierung von lokalen Änderungen an Bildeinstellungen und Freistellpfaden (wie bei den Doumentrahmen) ist aber leider nicht möglich.

Bitte beachten Sie, dass die folgenden Änderungen an der Musterdatei mit Ausnahme bei der Anlage neuer Rahmen von der Synchronisation nicht übernommen werden:

Neue Rahmen des Musterdokumentes werden vollständig und mit allen eingestellten Attriuten und Inhalten in die Varianten übernommen.

Gleichzeitige Änderungen an Bildern und Texten in Muster und Varianten können, wie leicht vorstellbar ist, zu Konflikten beim Synchronisieren führen, die nicht (oder jedenfalls nicht automatisch) zu lösen sind. Im Interesse einer automatischen Synchronisation werden Änderungen an Bildern und Texten daher seitens WERK II auch in möglichen Ausbaustufen der Synchronisation nicht implementiert werden. Für die automatische Pflege von Texten und Bildern sollten daher in jedem Fall die priint:comet Platzhalter verwendet werden!

Die gezielte Übernahme von Änderungen an den Rahmengestaltungen sind prinzipiell möglich, erfordern aber einen nicht unerheblichen Aufwand seitens WERK II und können daher nur nach gesonderter (und kostenpflichtiger) Beauftragung implementiert werden.

Weitere Informationen zur automatischen Auflösung auftretender Konflikte finden Sie in den Beschreibungen der einzelnen Schritte der Synchronisation.

Bitte beachten Sie ausserdem, dass bei der Synchronisation die folgenden Änderungen in der Variante überschrieben werden, wenn es gleichzeitig ein entsprechendes Objekt in der Musterdatei gibt. Objekte, die nur in der Variante existieren, bleiben unverändert (und werden auch nicht gelöscht!).

Die o.g. Änderungen in den Varianten werden auch dann überschrieben, wenn Sie im Musterdoukement gar nicht geändert wurden! Hintergrund ist, dass verschiedene Varianten zu verschiedenen Zeitpunkten und verschieden oft synchronisiert worden sein können und dadurch gar nicht klar ist, was aus Sicht der jeweiligen Variante eine Änderung ist und was nicht.

Auf Grund des kaum absehbaren Aufwandes gibt es seitens WERK II keinerlei Überlegungen, die generelle und vollständige Übernahme der o.g. Daten aus dem Musterdokument zu ändern.

Weitere Informationen zur automatischen Auflösung auftretender Konflikte finden Sie in den Beschreibungen der einzelnen Schritte der Synchronisation.

Als Musterdokument kann jedes beliebige InDesign® Dokument verwendet werden. Damit es später als Musterdokument erkannt werden kann, müssen lediglich zwei Elemente im Root-Element der XML-Struktur des Dokumentes angelegt werden:

Hier ein Screenshot:

Um die XML-Dokumentstruktur zu öffnen, wählen Sie das Menü Ansicht -> Struktur -> Struktur einblenden.

Varianten eines Musterdokumentes haben die gleiche documentID wie das Musterdokument und im Element priint_syncDocType den Wert variant. Hier ein Screenshot einer Variante:

Um zu prüfen, ob ein Dokument eine Variante eines Musterdokumentes ist, kann die Skriptfunktion document::sync::possible verwendet werden.

In den Seiten der Varianten werden die UIDs der originalen Seiten im Musterdokument hinterlegt. Direkt nach dem Anlegen einer Variante sind die UID einer Seite der Variante und die Original-UID gleich. Durch den unterschiedlichen "Verbrauch" an UIDs können diese UIDs aber später erheblich voneinander abweichen. Wird bei Synchronisationen eine neue Seite in einer Variante angelegt, muss die UID der Originalseite in der neuen Seite der Variante eingetragen werden.

Lokal in Varianten angelegte Seiten werden mit der Original-UID 0 markiert. Die 0-Markierung erfolgt automatisch durch die priint:comet Plugins und wird auch beim Duplizieren von Seiten oder Druckbögen gemacht.

Die Originalseite einer Seite wird zusammen mit dem Seitentemplate links oben in der Dokumentseite gezeigt:

Um die Seitentemplates im Dokument anzuzeigen, aktivieren Sie das Menü Ansicht -> Seitentemplates anzeigen.

Zum Setzen und Abfragen der Originalseite können die folgenden Funktionen verwendet werden:

In den Rahmen der Varianten werden die UIDs der originalen Rahmen im Musterdokument im ScriptTag prrint_syncOrigin (ACHTUNG: Falsche Schreibweise) hinterlegt.

Manuelle Änderungen an der Original-UID können zu Fehlern bei der Synchronsation bis hin zum Absturz von InDesign® führen!

Direkt nach dem Anlegen einer Variante sind die UID der Rahmen der Variante und die Original-UID gleich. Durch den unterschiedlichen "Verbrauch" an UIDs können diese UIDs aber später erheblich voneinander abweichen. Wird bei Synchronisationen ein neuer Rahmen in einer Variante angelegt, muss die UID des Originalrahmens im neuen Rahmen der Variante eingetragen werden.

Lokal in Varianten angelegte Rahmen werden mit der Original-UID 0 markiert. Die 0-Markierung erfolgt automatisch durch die priint:comet Plugins und wird auch beim Duplizieren von Rahmen und bei allen Rahmen von duplizierten Seiten und Ebenen gemacht.

Werden die Rahmennummern im Dokument angezeigt, wird die Original-UID hinter der Rahmen-UID gezeigt. Bei Rahmen ohne oder mit leerer Original-UID fehlt die Anzeige der zweiten UID:

So schalten Sie die Anzeige der Rahmen-UIDs an:

    - Kontextmenü Nägel & Magneten -> Zeigen
    - Kontextmenü Nägel & Magneten -> Rahmennummern zeigen

Achtung : Sie müssen beide Menüs aktivieren!

Zum Setzen und Abfragen der Originalseite können die folgenden Funktionen verwendet werden:

Das Anlegen einer Variante geschieht mit der Skriptfunktion document::sync::create_variant. Die Funktion erwartet als Eingabe das Musterdokument und einen Pfad für die Variante. Ist der Zielpfad leer oder 0, wird die Variante mit der Namensendung _variant neben die Musterdatei gelegt. Alle oben beschriebenen Original-Zuweisungen für spätere Synchronisationen Seiten- und Rahmeninformationen sind eingefügt.

Der Befehl document::sync::create_variant ist lediglich ein Shortcut für zur bequemen Anlage von Varianten. Mit den oben beschriebenen Zusammenhängen und Funktionen können Sie diese Funktionalität auch leicht selbst programmieren.

Die Synchronisation erfolgt in mehreren Schritten:

Farbfelder müssen dokumentweit eindeutige Namen haben. Das betrifft auch Farbfelder, die in Farbfeldgruppen zusammengefasst sind. Für die Synchronisation werden daher die Namen der Farbfelder verwendet.

Die Synchronisation betrifft die eigentlichen Farbfelder, Farbtonfelder, Verläufe usw.. Wir verwenden dafür hier den Begriff Farben. Folgende Schritte zur Synchronisation werden ausgeführt:

  1. Anlegen aller Farben, die im Musterdokument definiert sind aber in der Variante fehlen
  2. Übernahme aller (mglw. spezifischer) Einstellungen der Farben, die in Muster und Variante definert sind. Lokale Änderungen in der Variante werden dabei überschrieben!
  3. Wiederherstellen der Farbgruppen in der Variante
  4. Übertragen zusätzlicher Farbgruppen aus dem Muster. Ist eine Farbe in Muster und Variante in verschiedenen Farbgruppen, wird die Farbgruppe der Variante verwendet.

Durch die Synchronisation kann sich die Reihenfolge der Farbfelder ändern.

Farbfelder, die nur in der Variante definiert sind, bleiben erhalten (werden also nicht gelöscht!).

Für die Synchronisation der Farben kann die Skriptfunktion document::sync::swatches verwendet werden.

Ebenen müssen dokumentweit eindeutige Namen haben. Zur Synchronisation der Ebenen werden daher die Namen der Ebenen verwendet.

Bitte beachten Sie: Bei der Synchronisation der Ebenen werden keine Inhalte übertragen. Es werden lediglich die Namen, Positionen und Eigenschaften (Farbe, Sichtbarkeit, Sperrung, Druckbarkeit,Textumfluß, Hilfslinien-Sichtbarkeit, Hilfslinien-Sperrung) aktualisiert. Die Inhalte der Ebenen werden beim Synchronisieren der Rahmen übertragen.

Die Synchronsation wird in mehreren Schritten gemacht:

  1. Alle Ebenen der Musterdatei werden der Reihe nach in der Variante angelegt oder aktualiert und an die gleiche Position wie im Muster verschoben.
  2. Alle übrigen Ebenen werden der Reihe nach so verschoben, dass sie wieder hinter der gleichen Ebene liegen wie vor Schritt 1.
  3. Neue Ebenen (die also noch keinen Vorgänger in der Variante hatten) kommen ans Ende der Liste.

Die Tabelle zeigt das Verfahren an einem Beispiel, in dem die Musterdatei die Ebenen A, B und C und die Variante die Ebenen C, B, 1, 2, 3 und A haben:

Muster Variante Schritt 1 Schritte 2 und 3
A C A A A A
B B B B B B
C 1 C 1 1 1
2 1 C 2 2
3 2 2 C 3
A 3 3 3 C

Dass Ebenen, die nur in der Variante definiert sind, nicht gelöscht werden, bedeutet auch, dass Ebenen, die im Musterdokument gelöscht wurden, in den Varianten nicht mehr gelöscht werden!

Für die Synchronisation der Ebenen kann die Skriptfunktion document::sync::layers verwendet werden.

Alle Stildefinitionen des Musterdokumentes werden vollständig in die Varianten übernommen. Lokale Änderungen den Stildefinitionen der Varianten werden dabei überschrieben.

Alle von InDesign® unterstützen Stilklassen werden synchronisiert:

Definttionen, die von anderen Stilen verwendet werden, werden dabei zuerst übertragen.

Auf Grund der möglichen Abhängigkeiten zwischen Stildefinitionen ist es nicht möglich, nur einzelne Stildefinitionen zu übertragen.

Die Übernahme einzelner Stileigenschaften, z.B. nur der Schriftgröße eines Zeichenstiles, wird nicht unterstützt.
Auf Grund des kaum abschätzbaren Aufwandes gibt es seitens WERK II auch keinerlei dahingehende Überlegungen.

Für die Synchronisation der Stildefinitionen kann die Skriptfunktion document::sync::styles verwendet werden.

Alle Musterseiten des Musterdokumentes werden vollständig in die Varianten übernommen. Lokale Änderungen der Mustereiten in den Varianten werden dabei überschrieben. Musterseiten, die von anderen Musterseiten verwendet werden, werden dabei zuerst übertragen.

Auf Grund der möglichen Abhängigkeiten zwischen Musterseiten ist es nicht möglich, nur einzelne Musterseiten zu übertragen.

Die Einzel-Übernahme von Rahmen oder Einstellungen von Musterseiten (wie z.B. eine geänderte Seitengröße) wird nicht unterstützt.
Auf Grund des kaum abschätzbaren Aufwandes gibt es seitens WERK II auch keinerlei dahingehende Überlegungen.

Für die Synchronisation der Musterseiten kann die Skriptfunktion document::sync::masterspreads verwendet werden.

Die Zuordnung von Seiten der Varianten zu Seiten des Musterdokumentes erfolgt über eine zusätzlich in den Seiten hinterlegte Original-UID der Seite. Hier finden Sie eine vollständige Beschreibung inkl. aller nötigen Skriptfunktionen.

Bitte beachten Sie: Bei der Synchronisation der Seiten werden keine Inhalte übertragen. Es werden lediglich die Seiteneigenschaften (Größe, Bindung, Hilfslinien, Position, Musterseite, ...) aktualisiert. Die Inhalte der Seiten werden beim Synchronisieren der Rahmen übertragen.

Mit Hilfe der Original-UIDs der Seiten der Variante kann die Synchronisation der Seiten wie folgt ausgeführt werden:

  1. Alle Seiten der Musterdatei werden der Reihe nach in der Variante angelegt oder aktualiert und an die gleiche Position wie im Muster verschoben.
  2. Alle übrigen Seiten werden der Reihe nach so verschoben, dass sie wieder hinter der gleichen Seite liegen wie vor Schritt 1.
  3. Neue Seiten (die also noch keinen Vorgänger in der Variante hatten) kommen an den Anfang des Dokumentes
  4. Im Master gelöschte Seiten werden in der Variante gelöscht. Die Seiten werden auch dann gelöscht, wenn sie lokale Änderungen oder lokal in der Variante angelegte Rahmen enthalten!

Die Tabelle zeigt das Verfahren an einem Beispiel, in dem die Musterdatei die Seiten A, B und C und die Variante die Seiten 4, C, B, 1, 2, 3 und A haben:

Muster Variante Schritt 1 Schritte 2 und 3
A 4 A A A A 4
B C B B B B A
C B C 1 1 1 B
1 4 C 2 2 1
2 1 4 C 3 2
3 2 2 4 C 3
A 3 3 3 4 C

Für die Synchronisation der Seiten kann die Skriptfunktion document::sync::pages verwendet werden.

Alle Rahmen des Musterdokumentes werden in die Variante übernommen oder dort aktualisiert. Folgende Rahmeneingeschaften können aktualisiert werden:

Nach Änderungen an der Rahmengeometrie oder der Seite werden die Gestaltungsregeln "Nach Laden" und "Nach Geometrieänderungen" des Rahmens ausgeführt!

Wurde ein Rahmen in einer der oben genannten Eigenschaften in der Variante geändert, werden Änderungen der gleichen Eigenschaft im Musterdokument ignoriert. Bitte beachten Sie, dass nach der Änderung einer Geometrie-Eigenschaft (z.B. der Position)  auch alle anderen Geometrie-Änderungen (z.B. Größenänderungen) des Rahmens im Musterdokument ignoriert werden!

Eine einmal gesetzte Änderungsmarkierug wird nicht wieder zurückgesetzt - auch dann nicht, wenn der ursprüngliche Wert wieder eingestellt wird.

Bitte beachten Sie die folgenden Hinweise!

Textrahmen können so eingestellt sein, dass sich ihre Größe und Position automatisch an den Inhalt anpassen (Textrahmenoptionen -> Automatisch Größe ändern). Diese Einstellung steht im direkten Widerspruch zu dem Wunsch, Geometrie-Änderungen aus der Musterdatei 1:1 in die Varianten zu übernehmen. Wir übernehmen Änderungen der Rahmengeometrie im Muster trotzdem in die Varianten. Danach wird InDesign aber Rahmengröße und -position gemäß den aktuellen Einstellungen am Rahmen nochmals korrigieren!

Ein weiteres Problem bei Textrahmen mit automatischer Größenanpassung ist, dass wir den Auslöser der Geometrieänderung nicht erkennen können und die automatische Anpassung damit jedesmal zu lokalen Geometrieänderungen am Rahmen führen würde. Um das zu vermeiden, werden bei Rahmen mit automatischer Größenanpassung Geometrieänderungen generell ignoriert. Sollten Sie eine lokale Geometrieänderung trotzdem registrieren wollen, muss dabei die CMD-Taste (STRG bei Windows) gehalten werden.

Die Z-Order von Rahmen kann nicht wiederhergestellt werden und auf keinen Fall können die Z-Sortierungen von Muster und Variante synchronisiert werden. Für Rahmenüberdeckungen können Ebenen verwendet werden.

Bei Größenänderungen von Rahmen kann nicht festgestellt werden, an welcher Ecke oder Seite die Größenänderung gemacht wurde. Bei Bildrahmen können dadurch unterschiedliche Bildausschnitte in Muster und Varianten entstehen. Um das Problem möglichst klein zu halten, werden Bildpositionen automatisch angepasst, wenn die folgenden Bedingungen alle erfüllt sind:

Bitte beachten Sie, dass es durch die automatische Positionsanpassung gleicher Bilder nicht möglich ist, in einer Variante lediglich die Bildposition zu ändern. Diese Änderung wird bei der nächsten Synchronisation zurückgesetzt werden.

Lokale Änderungen an Rahmen einer Variante werden von den priint:comet Plugins automatisch registriert und im Script-Tags priint_syncChanged des Rahmens hinterlegt. Die automatische Registrierung erfolgt ausschließlich in Dokumenten, die als Varianten gekennzeichnet sind.

Zur bequemeren Benutzbarkeit der Palette Rahmen-Etiketten ist geplant, die Werte-Felder der Palette typabhängig zu gestalten. Der Wert von priint_syncChanged könnte dann durch das Aktivieren einer einfachen Checkbox in der Liste geändert werden. Dieses Feature ist nicht Teil der aktuellen Beauftragung für die Synchronisation.

Zusätzlich können Rahmen generell von der Synchronisation ausgeschlossen werden. Setzen Sie dazu das Script-Tag priint_syncDisabled auf den Wert 1. Die Änderung dieses Wertes erfolgt manuell! Alternativ können Sie sich dazu ein Skript erstellen (lassen) und dort den Wert mit Hilfe der Skriptfunktion frame::set_script_tag ändern.

Script-Tags werden in der Palette Fenster -> Comet Admin -> Rahmen-Etiketten angezeigt und können dort auch manuell verändert werden. Folgende Werte sind möglich:

Key Value Icon Beschreibung
priint_syncDisabled 0 | 1

1 : Der Rahmen wird vollständig von der Synchronisation ausgeschlossen und auch nicht gelöscht, wenn das Original gelöscht wurde.

0 : Der Rahmen wird, mit Einschränkung eventuell gemachter lokaler Änderungen, synchronisiert.

priint_syncChanged geometry

Geometrieänderungen:

  • Position
  • Größe
  • Skalierung
  • Drehung
  • Scherung (skew)
page

Der Rahmen wurde auf eine andere Seite verschoben.

layer

Der Rahmen wurde auf eine andere Ebene verschoben.

style

Der Objektstil des Rahmens wurde geändert.

Bitte beachten Sie: Die Druckbarkeit eines Rahmens ist Teil der Objektstile. Bei Änderung des Objektstiles wird die Markierung print entfernt und erst wieder gesetzt, wenn explizit die Druckbarkeit geändert wird.

lock

Die Rahmensperrung wurde geändert.

visibility

Die Sichtbarkeit des Rahmens wurde geändert.

print

Die Druckbarkeit des Rahmens wurde geändert.

Bitte beachten Sie: Die Druckbarkeit eines Rahmens ist Teil der Objektstile. Bei Änderung des Objektstiles wird die Markierung print entfernt und erst wieder gesetzt, wenn explizit die Druckbarkeit geändert wird.

Die Werte können in der Palette Rahmen-Etiketten manuell geändert oder entfernt werden.

Beachten Sie bitte, dass der Wert von print_syncOrigin niemals manuell geändert werden darf!

Der Wert von print_syncPagenum wird intern verwendet. Er widerspiegelt nicht in jedem Fall dieaktuelle Seitennummer des Rahmens!

Lokale Änderungen in den Varianten werden bei sichtbaren Rahmen-UIDs hinter der Original-UID des Rahmens gezeigt.

So schalten Sie die Anzeige der Rahmen-UIDs an:

    - Kontextmenü Nägel & Magneten -> Zeigen
    - Kontextmenü Nägel & Magneten -> Rahmennummern zeigen

Achtung : Sie müssen beide Menüs aktivieren!

Eine Liste, die alle manuell geänderten oder gesperrten Rahmen des Dokumentes oder der aktuellen Seite zeigt, ist ausdrücklich nicht Teil der aktuellen Anforderung für die Synchronisation gewesen und wurde deshalb auch nicht implementiert. Wir könnten uns aber (nach einer gesonderten Beauftragung) vorstellen, die Palette priint:adjust Rahmenliste dafür zu erweitern.

Das InDesign®-Standardverhalten beim Kopieren von Rahmen aus Textketten ist, dass Rahmen mit Fortsetzung nur den aktuell sichtbaren Textteil erhalten. Der letzte Rahmen der Kette dagegen erhält zusätzlich noch den geamten Text des Übersatzes.

Hier ein Beispiel einer Textkette mit dem Text "A B C D" bei der das Zeichen "D" im Übersatz verschwindet:

Dupliziert man den blauen Rahmen, wird ein blauer Rahmen mit dem Text "A" (und nicht mehr) entstehen. Beim Duplizieren des grünen Rahmens wird der Text "B" übernommen. Der rote Rahmen dagegen wird den Text "C D" enhalten (und wieder einen Übersatz haben).

Dieses Verhalten entspricht sicher dem, was man erwartet. Für die Synchronisation ist es fatal, wie die folgenden zwei Fälle anhand des obigen Beispieles zeigen:

  1. Auflösen des Übersatzes im Muserdokument:
    1. Anlegen eines weiteren Rahmens hinter dem roten Rahmen, in dem der Text "D" aus dem Übersatz gezeigt werden kann .
    2. Bei der nächsten Synchronisation wird dieser Rahmen (als neuer Rahmen im Muster) in die Variante übernommen werden - und zwar mit seinem Textinhalt "D".
    3. Danach wird Rahmen an die Textkette in der Variante angefügt, die bereits den Text "A B C D" enthält.
    4. Die Textkette enthält jetzt den Text "A B C DD".
  2. Auflösen des Übersatzes in der Variante:
    1. Entfernen des roten Rahmens
    2. Vergrößern des grünen Rahmens bis der Übersatz beseigt ist.
    3. Bei der nächsten Synchronisation wird der rote Rahmen erneut angelegt werden. Als letzter Rahmen der Kette enthält der Rahmen den Text "C D".
    4. Jetzt wird der rote Rahmen wieder an die Textkette mit dem Text "A B C D" angehangen.
    5. Die Textkette enthält jetzt den Text "A B C DC D".

Das für die Synchronisation mitgelieferte cScript löst diese Probleme und Textketten werden gemäß der Textkette im Muster wiederhergestellt.

Zusätzlich in der Variante angelegte Textverkettungen werden an das Ende der aus dem Musterdokument übernommen Kette angehangen.

Für alle Rahmen der Variante, die einen Originalrahmen im Musterdokument haben, wird geprüft, ob dieser Rahmen noch existiert. Kann der Rahmen nicht (mehr) im Musterdokument gefunden werden, wird er auch in der Variante gelöscht. Ist der Rahmen Teil einer Textkette, wird die Kette bei Bedarf wieder neu verbunden.

Auch Rahmen mit manuellen Änderungen werden gelöscht!

Rahmen, die von der Synchronisation ausgeschlossen sind (siehe hier), werden nicht gelöscht!

In diesem Schritt werden die Rahmen-Gruppen wiederhergestellt:

  1. Alle Rahmen mit einem Original werden, wenn sie in einer Gruppe enthalten, aus diesen Gruppen entfernt.
  2. Wiederherstellen aller Gruppen und Untergruppen wie im Original

Gruppen des Musterdokumentes haben also Vorrang vor Gruppen der Variante!

Alle lokal angelegten Seiten ohne Inhalt werden aus der Variante entfernt. Eine Seite ist leer, wenn sie:

  1. Weder lokal in der Variante angelegte Rahmen noch solche aus dem Musterdokument enthält
  2. Keine lokalisierten Musterseiten-Einträge mehr enthält.

Dagegen dürfen Seiten natürlich nicht-lokalisierte Musterseiten-Rahmen zeigen (sonst könnte keine Seite mit Musterseiten-Rahmen gelöscht werden).

Alle Ebenen ohne Inhalt, die nicht auch im Master definiert sind, werden aus der Variante entfernt. Eine Ebene ist leer, wenn sie:

  1. Weder lokal in der Varaiante angelegte Rahmen noch solche aus dem Musterdokument enthält
  2. Keine lokalisierten Musterseiten-Einträge mehr enthält.

Dagegen dürfen Ebenen natürlich nicht-lokalisierte Musterseiten-Rahmen zeigen (sonst könnte keine Ebene mit Musterseiten-Rahmen gelöscht werden).

Hier ein vollständiges Skript zur Synchronisation.

#pragma plain

// Author			: Paul Seidel
// Date				: 28.09.2019
// Coypright (c)	: WERK II GmbH, 2019
//

//***************************************************************************

#include "internal/types.h"

//***************************************************************************

String 	stErrorMessage	= 0;
int 	stResult		= 1;			

//***************************************************************************

// Get the page index that a frame of the master must have in the variant.
//
int get_pnum (ItemRef master, ItemRef fm, IDTypeList origns, int * pnum_v)
{
    int 	pnum_m 	= page::get (fm, 1);				// page number in master
    int 	puid 	= page::get_uid (master, pnum_m);	// UID of page in master

    if (!puid)	
    {
    	// page not found in master
    	string::append (stErrorMessage, "I see that frame %d is on page %d of the master, but I can't find this page.\n\n", item::getint (fm), pnum_m);
        return 1;	    
    }

    *pnum_v	= idtypelist::find_id2 (origns, puid);
    if (*pnum_v < 1)	
    {
    	// page not found in variant
    	string::append (stErrorMessage, "The page %d of the master cannot be found in the variant.\n\n", pnum_m);
    	return 2;
    }

    return 0;
}

//***************************************************************************

// Move a frame to the center of the page. 
// We do this to prevent frames from falling off the pasteboard 
// during geometry changes. The following size changes are then
//always carried out with the frame center as reference point.
//
int center_frame_in_page (ItemRef fr)
{
    int 		pnum	= page::get (fr);
    ItemRef		docRef	= item::alloc ();
    float 		pl, pt, pr, pb;
    float 		l, t, r, b;
    
    item::define (docRef, fr, 1);  
    page::get_size (pnum, &pl, &pt, &pr, &pb, 0, docRef);
    frame::bbox (fr, &l, &t, &r, &b);
            
    frame::moveto (fr, ((pr-pl) - (r-l))/2.0, ((pb-pt) - (b-t))/2.0);

    return 0;
}

//***************************************************************************

// Helper function for determining the frame center in one call
//    direction 1 : x
//    direction 2 : y
// 
float get_center (ItemRef fr, int direction)
{
    float 		l, t, r, b;

    frame::bbox (fr, &l, &t, &r, &b);
    if (direction == 1)	return (r-l)/2.0;
    else 		return (b-t)/2.0;
    
}

//***************************************************************************

// The string #changes# consists of a list of local changes:
//
// 	page
// 	geometry
// 	layer
// 	style
// 	lock
// 	visibility
// 	print
//
// if one change is NOT included, the corresponding value(s)
// must be taken from the master.
//
int must_update (String changes, char * what)
{
    if (string::find (changes, what) == -1) return 1;
    return 0;
}

//***************************************************************************

// Update an existing frame in the variant
// 
// Which local changes we are not allowed to change 
// can be found in the ScriptTag priint_syncChanged.
//
// pnum is the expected 1-based page number in variant!
//
int update_frame (ItemRef fv, ItemRef fm, int pnum)
{
    int  		result 		= 0;
    String 		changes		= string::alloc ();
    String 		disabled	= string::alloc ();
    float 		lm, tm, rm, bm;
    float 		lv, tv, rv, bv;
    float 		w, h, sx, sy, skew, rota;
    int 		applyRules	= 0;
    int 		pgv;
    String 		sm			= string::alloc ();
    String 		sv			= string::alloc ();
    int 		im, iv;
    ItemRef 	group 		= item::alloc ();
    ItemList 	groupFrames = 0;
    int 		lockm, lockv;
    
    while (1)
    {
    	string::set (disabled, frame::get_script_tag (fv, "priint_syncDisabled"));
    	if (string::compare (disabled, "1") == 0)
    	{
            break;
    	}
        
    	// Which local changes we are not allowed to change 
    	// can be found in the ScriptTag priint_syncChanged
    	//
    	string::set (changes, frame::get_script_tag (fv, "priint_syncChanged"));

    	// Remember my current xy position
    	//
    	frame::bbox (fm, &lm, &tm, &rm, &bm);
    	frame::bbox (fv, &lv, &tv, &rv, &bv);
    
    	if (must_update (changes, "geometry"))
    	{
            // Get the current frame settings of fm
            //
            frame::get_size (fm, &w, &h);
            frame::get_scale (fm, &sx, &sy);
            skew = frame::get_skew (fm);
            rota = frame::get_rotate (fm);
    
            // To be sure that the frame does not fall from the pasteboard, 
            // we first move it to the middle of the page.
            //
            center_frame_in_page (fv);
    
            result = frame::resize 	(fv, w, h, 0, kRefPointCenter, 0.0, 0.0, applyRules);			if (result) break;
   
            result = frame::rotate 	(fv, rota, 0.0, 0.0, applyRules, kRefPointCenter);			if (result) break;
            result = frame::scale 	(fv, sx, sy, get_center (fv, 1), get_center (fv, 2), applyRules);	if (result) break;
            result = frame::skew 	(fv, skew, get_center (fv, 1), get_center (fv, 2), applyRules);		if (result) break;
    
            // Move back to the old position
            frame::moveto (fv, lm, tm, -1, 0, applyRules);
            frame::apply_layout_rules (fv, 10);
    	}
    	else
    	{
            frame::moveto (fv, lv, tv, -1, 0, applyRules);
    	}
    	if (result) 
    	{
            string::append (stErrorMessage, "The geometry setting of frame %d of the master could not be applied to the corresponding frame %d of the variant (Error %d).\n\n", item::getint (fm), item::getint (fv), result);
            break;
    	}

    	// The position is okay now
    	// Fix the page if needed
    	//
    	if (must_update (changes, "page"))
    	{
            pgv = page::get (fv);
            if (pgv != pnum)
            {
                // If fv belongs to an InDesign group, we have to release
                // this group and re-group it without fv then if possible.
                //
                item::define (group, fv, 0);
                frame::get_group (fv, group);
                if (item::getint (group))
                {
                    itemlist::alloc (groupFrames);
                    frame::ungroup (group, groupFrames);
            
                    itemlist::remove (groupFrames, fv);
                    if (itemlist::length (groupFrames) > 1)
                    {
                    	frame::group (groupFrames);
                    }
                    itemlist::release (groupFrames);
                }
    	
                frame::bbox (fv, &lv, &tv, &rv, &bv);
                result 	= frame::moveto (fv, lv, tv, pnum, 0, applyRules);
                frame::apply_layout_rules (fv, 10);
            }
    	}		
    	if (result) 
    	{
            string::append (stErrorMessage, "The frame %d could not be moved to the page %d (Error %d).\n\n", item::getint (fv), pnum, result);
            break;
    	}

    	// Fix the layer
    	//		
    	if (must_update (changes, "layer"))
    	{
            frame::get_layer (fm, sm);
            frame::get_layer (fv, sv);
    
            if (string::compare (sm, sv) != 0)
            {
                // Neither of the two layers must be locked.
                //
                lockm = layer::get_lock (sm);
                lockv = layer::get_lock (sv);
                if (lockm) layer::unlock (sm);
                if (lockv) layer::unlock (sv);
    	
                // Move the frame to the desired layer
                //
                result = frame::move_to_layer (fv, sm, 1);
    	
                // Lock layers again
                //
                if (lockm) layer::lock (sm);
                if (lockv) layer::lock (sv);
            }
    
    	}		
    	if (result) 
    	{
            string::append (stErrorMessage, "The frame %d could not be moved to the layer '%s' (Error %d).\n\n", item::getint (fv), sm, result);
            break;
    	}

    	// Fix the style
    	//
    	if (must_update (changes, "style"))
    	{
            string::set (sm, frame::get_objectstyle (fm));
            string::set (sv, frame::get_objectstyle (fv));
    
            if (string::compare (sm, sv) != 0)
            {
                result = frame::set_objectstyle (fv, sm, 0, 1);
            }
    	}
    	if (result) 
    	{
            string::append (stErrorMessage, "Could not apply object style '%s to frame %d (Error %d).\n\n", sm, item::getint (fv), result);
            break;
    	}

    	// Fix lock state
    	//
    	if (must_update (changes, "lock"))
    	{
            im = frame::is_locked (fm);
            iv = frame::is_locked (fv);
    
            if (im != iv)
            {
                if (im)	result = frame::lock (fv);
                else	result = frame::unlock (fv);
            }
    	}
    	if (result) 
    	{
            if (im)	string::append (stErrorMessage, "Could not lock frame %d (Error %d).\n\n", sm, item::getint (fv), result);
            else 	string::append (stErrorMessage, "Could not unlock frame %d (Error %d).\n\n", sm, item::getint (fv), result);
            break;
    	}

    	// Fix visibilty state
    	//
    	if (must_update (changes, "visibility"))
    	{
            im = frame::is_hidden (fm);
            iv = frame::is_hidden (fv);
    
            if (im != iv)
            {
                if (im)	result = frame::hide (fv);
                else	result = frame::show (fv);
            }

    	}
    	if (result) 
    	{
            if (im)	string::append (stErrorMessage, "Could not hide frame %d (Error %d).\n\n", sm, item::getint (fv), result);
            else 	string::append (stErrorMessage, "Could not show frame %d (Error %d).\n\n", sm, item::getint (fv), result);
            break;
    	}

    	// Fix print state
    	//
    	if (must_update (changes, "print"))
    	{
            im = frame::get_printable (fm);
            iv = frame::get_printable (fv);
    
            if (im != iv)
            {
                result = frame::set_printable (fv, im);
            }
    	}
    	if (result) 
    	{
            string::append (stErrorMessage, "Could not change printablitiy of frame %d (Error %d).\n\n", sm, item::getint (fv), result);
            break;
    	}
    	
    	break;
    }
    
    string::release (changes);
    string::release (sm);
    string::release (sv);
    item::release (group);
    
    return result;
}

//***************************************************************************

// Add the minimum sync information to all frames on 
// new pages of the master.
// pp2
//
int prepare_master (ItemRef variant, ItemRef master)
{
    IDTypeList 		originsPages	= idtypelist::alloc ();
    int				i, j, id, puid;						
    ItemRef 		fv				= item::alloc ();
    ItemList		fvl;
    char 			istr [256];
    
    // Get the list of all pages in the variant watched by an origin
    // The list contains the key:value pairs
    //
    //	id 			id2
    //	----------------------------------
    //	origin_in_master 	index_in_variant
    //
    for (i = 0; i < document::pages (variant); i++)
    {
    	page::get_info (variant, i+1, "origin", &id);
    	if (id)	
        {
        	idtypelist::append (originsPages, id, i+1, 0, "");
        }
    }
    
    // Walk through all pages of the master. If we do not
    // find it in the variant, it must be a new page.
    // In this case take all frames of the new page and
    // add the minimum sync information to these frames  
    //
    for (i = 1; i <= document::pages (master); i++)
    {
    	puid	= page::get_uid (master, i);
    	if (idtypelist::find (originsPages, puid) < 0)
    	{
            fvl = itemlist::pageframes_of_doc (master, i. 1);
            
            for (j = 0; j < itemlist::length (fvl); j++)
            {
                itemlist::get (fvl, fv, j);
                sprintf (istr, "%d", item::getint (fv));
                frame::set_script_tag (fv, "0", "priint_syncDisabled");
                frame::set_script_tag (fv, istr, "prrint_syncOrigin");
            }
    
            itemlist::release (fvl);
    	}
    }
    
    idtypelist::release (originsPages);
    item::release (fv);
    return 0;
}

//***************************************************************************

// Run through all the frames of the master and find the corresponding 
// frames in the variant.
//
// if the frame is not found in the variant, a copy of the frame is created
// in the variant. Otherwise, the settings of the frame in the master are 
// copied to the variant.
//
int sync_frames (ItemRef variant, ItemRef master)
{
    ItemList		FV 				= itemlist::allframes_of_doc (variant, 1, 0, "", 0, 1);
    ItemList		FM 				= itemlist::allframes_of_doc (master, 1, 0, "", 0, 1);
    ItemList 		chained;
    ItemRef 		fv 				= item::alloc ();
    ItemRef 		fm 				= item::alloc ();
    ItemRef 		ch 				= item::alloc ();
    ItemRef 		next 			= item::alloc ();
    IDTypeList 		origins			= idtypelist::alloc ();
    IDTypeList 		originsPages	= idtypelist::alloc ();
    int 			i, j, id, pg_v, must_relink;	
    float 			l, t, r, b;
    String 			lay				= string::alloc ();
    int				result			= 0;

    // Get a list of all frames in the variant watched by an origin
    // The list contains the key:value pairs
    //
    //	id 			id2
    //	----------------------------------
    //	origin_in_master 	uid_in_variant
    //
    for (i = 0; i < itemlist::length (FV); i++)
    {
    	fv 	= itemlist::get (FV, fv, i);
    	id 	= frame::get_origin (fv);
    	
    	if (id)	idtypelist::append (origins, id, item::getint (fv), 0, "");
    }
    
    // Get the list of all pages in the variant watched by an origin
    // The list contains the key:value pairs
    //
    //	id 			id2
    //	----------------------------------
    //	origin_in_master 	index_in_variant
    //
    for (i = 0; i < document::pages (variant); i++)
    {
    	result = page::get_info (variant, i+1, "origin", &id);
    	if (id)	
        {
        	idtypelist::append (originsPages, id, i+1, 0, "");
        }
    }
    
    // Walk through all frames of the master and create/update the frames
    //
    for (i = 0; i < itemlist::length (FM); i++)
    {
    	fm 	= itemlist::get (FM, fm, i);
    	
    	// Get the frame UID of fm in variant by searching the master UID in the origins.
    	// 
    	// 	- If we don't find the master UID in the origins, we have to duplicate the frame
    	// 	- If we find the UID in the origins, we need to update the corresponding frame of the variant
    	//
    	id	 = idtypelist::find_id2 (origins, item::getint (fm));
    	
    	if (id == -1)
    	{
            // Create frame fm in variant
            //
            result	= get_pnum (master, fm, originsPages, &pg_v); 	// expected page index in variant
            if (result) break;

            frame::bbox (fm, &l, &t, &r, &b);			// position and size
            frame::get_layer (fm, lay);				// layer

            // For frames in text chains, only the text content that is 
            // currently visible in the frame is copied during duplication.
            // This is of course very annoying when frames have changed in size.
            // we will either lose text and get some parts multiple times.
            //
            // We therefore break the chain before duplicating frames from a chain.
            // After duplicating, the chain is rebuilt.
            //
            must_relink	= 0;
            chained 	= itemlist::chained (fm);
            if (chained && itemlist::length (chained) > 1)
            {
                itemlist::get (chained, ch, 0);
                frame::link (ch, 0);				// unlink the frame
                must_relink = 1;
            }

            // Duplicate the frame
            //
            result = frame::duplicate (fv, fm, l, t, variant, pg_v, lay, 0);

            // Relink frames
            //
            if (must_relink) 
            {
                for (j = 0; j < itemlist::length (chained) - 1; j++)
                {
                    itemlist::get (chained, ch, j);
                    itemlist::get (chained, next, j+1);
                    frame::link (ch, next);
                }
            }
            itemlist::release (chained);

            if (result)	string::append (stErrorMessage, "The frame % could not be copied to the variant to pg %d and layer '%s' at posistion [%f %f], (Error %d).\n\n", item::getint (fm), pg_v, lay, l, t, result);

            frame::set_origin (fv, item::getint (fm));
    	}
    	else
    	{
            // Get the expected page index of fm in the variant.
            // To do that, we first have to query the page in the master.
            // Then we have to look into the map originsPages to
            // find the index there.
            //
            result	= get_pnum (master, fm, originsPages, &pg_v); 
            if (result) break;

            // Update frame fm in variant
            //
            item::define (fv, variant, id);
            result = update_frame (fv, fm, pg_v);
    	}
        
    	if (result) break;
    }
    
    // Clean up
    //
    itemlist::release (FV);	
    itemlist::release (FM);
    item::release (fv);
    item::release (fm);
    item::release (ch);
    item::release (next);
    idtypelist::release (origins);
    idtypelist::release (originsPages);
    string::release (lay);

    // Ready
    //
    return result;
}

//***************************************************************************

int remove_superflous_frames (ItemRef variant, ItemRef master)
{
    ItemList		FV 			= itemlist::allframes_of_doc (variant, 1, 0, "", 0, 1);
    ItemRef 		fv 			= item::alloc ();
    ItemRef 		fm 			= item::alloc ();
    String 			disabled 	= string::alloc ();
    int 			i, origin;
    
    for (i = 0; i < itemlist::length (FV); i++)
    {
    	fv 	= itemlist::get (FV, fv, i);
    	origin	= frame::get_origin (fv);

    	string::set (disabled, frame::get_script_tag (fv, "priint_syncDisabled"));
    	if (string::length (disabled) == 0 || string::compare (disabled, "0") == 0)
    	{
            if (origin)
            {        
                item::define (fm, master, origin, 0);
    	
                if (!frame::is_valid (fm))
                {        		
                    frame::remove (fv);
                }
            }
    	}
    }
    
    // Clean up
    //
    itemlist::release (FV);
    item::release (fv);
    item::release (fm);
    string::release (disabled);

    return 0;
}

//***************************************************************************

// Rebuild text chains
// The text links of the master file are restored. Further text links in the 
// variant are attached to the end of the updated chain.
// 
int rebuild_text_chains (ItemRef variant, ItemRef master)
{
    ItemList		FV 		= itemlist::allframes_of_doc (variant, 1, 0, "", 0, 1);
    ItemList		FM 		= itemlist::allframes_of_doc (master, 1, 0, "", 0, 1);
    ItemRef 		fv 		= item::alloc ();
    ItemRef 		fm 		= item::alloc ();
    IDTypeList 		origins	= idtypelist::alloc ();
    IDTypeList 		dones	= idtypelist::alloc ();
    ItemList		chain 	= 0;
    ItemRef 		ch1 	= item::alloc ();
    ItemRef 		ch2 	= item::alloc ();
    ItemRef 		de1 	= item::alloc ();
    ItemRef 		de2 	= item::alloc ();
    int				result	= 0;
    int 			i, j, p, id1, id2;

    // Get a list of all frames in the variant watched by an origin
    // The list contains the key:value pairs
    //
    //	id 			id2
    //	----------------------------------
    //	origin_in_master 	uid_in_variant
    //
    for (i = 0; i < itemlist::length (FV); i++)
    {
    	itemlist::get (FV, fv, i);
    	id1 = frame::get_origin (fv);
    	
    	if (id1)	idtypelist::append (origins, id1, item::getint (fv), 0, "");
    }
    
    // Walk through all frames of the master and relink text chains
    //
    for (i = 0; i < itemlist::length (FM); i++)
    {
    	itemlist::get (FM, fm, i);
                
    	// Get the complete chain of the current frame
    	//
    	if (chain)
    	{
            itemlist::release (chain);
            chain = 0;
    	}
    	chain = itemlist::chained (fm);
        
    	// Recreate the chain if any
    	//
    	if (chain && itemlist::length (chain) > 1)
    	{
            // Check whether we handled the chain already
            //
            itemlist::get (chain, ch1, 0);
            p = idtypelist::find (dones, item::getint (ch1));
    
            if (p == -1)
            {
                // Rebuild the chain step by step
                //
                for (j = 0; j < itemlist::length (chain) - 1; j++)
                {
                    itemlist::get (chain, ch1, j);
                    itemlist::get (chain, ch2, j+1);
            
                    id1	 	= idtypelist::find_id2 (origins, item::getint (ch1));
                    id2	 	= idtypelist::find_id2 (origins, item::getint (ch2));
            
                    if (id1 == -1)	
                    {
                    	string::append (stErrorMessage, "Relinking %d and %d of master, but cannot find first frame in variant.\n\n", item::getint (ch1), item::getint (ch2));
                    	result = 4;
                    }
                    else if (id2 == -1)	
                    {
                    	string::append (stErrorMessage, "Relinking %d and %d of master, but cannot find second frame in variant.\n\n", item::getint (ch1), item::getint (ch2));
                    	result = 4;
                    }
                    else
                    {
                    	item::define (de1, variant, id1);
                    	item::define (de2, variant, id2);
                    	result = frame::link (de1, de2);
                    	if (result) string::append (stErrorMessage, "Cannot link together frames %d and %d in variant.\n\n", item::getint (ch1), item::getint (ch2));
                    }
                    if (result) break;
                }
                if (result) break;
    	
                // All frames of chain are relinked now.
                // Insert them into the dones list.
                //
                for (j = 0; j < itemlist::length (chain); j++)
                {
                    itemlist::get (chain, ch1, 0);
                    idtypelist::append (dones, item::getint (ch1), 0, 0, "");
                }
            }
    	}
    }

    // Clean up
    //
    itemlist::release (chain);
    itemlist::release (FV);	
    itemlist::release (FM);	
    itemlist::release (ch1);
    itemlist::release (ch2);
    itemlist::release (de1);
    itemlist::release (de2);
    item::release (fv);
    item::release (fm);
    idtypelist::release (origins);

    return result;
}

//***************************************************************************

// All functions of the Sync have the same call parameters. 
// We can therefore execute them all with the same stack call.
// 
int apply (int fn, ItemRef variant, ItemRef master, int step)
{
    int 	result;
    String 	m 	= string::alloc ();

    // MAIN WORK IS DONE HERE
    //
    wlog ("", "# %s ... ", symname (fn, 1));
    result = fn (variant, master);

    // Error handlings
    //
    if (result) 
    {
    	wlog ("", "ERROR %d\n", result);
    	wlog ("", "%s", stErrorMessage);

    	string::set (m, "SYNCHRONISATION FAILED\n");

    	if (step == 1)			string::append (m, "\nUpdating swatches failed with error %d.\n", result);
    	else if (step == 2)		string::append (m, "\nUpdating layers failed with error %d.\n", result);
    	else if (step == 3)		string::append (m, "\nUpdating styles failed with error %d.\n", result);
    	else if (step == 4)		string::append (m, "\nUpdating master spreads failed with error %d.\n", result);
    	else if (step == 5)		string::append (m, "\nUpdating page settings failed with error %d.\n", result);
    	else if (step == 6)		string::append (m, "\nUpdating frames failed with error %d.\n", result);
    	else if (step == 7)		string::append (m, "\nRemoving superflous frames failed with error %d.\n", result);
    	else if (step == 8)		string::append (m, "\nRebuilding text chains failed with error %d.\n", result);
    	else if (step == 9)		string::append (m, "\nRemoving InDesign groups failed with error %d.\n", result);
    	else if (step == 10)	string::append (m, "\nRemoving superflous pages failed with error %d.\n", result);
    	else if (step == 11)	string::append (m, "\nRemoving superflous layers failed with error %d.\n", result);

    	if (string::length (stErrorMessage))
    	{
            string::append (m, "\n%s", stErrorMessage);
    	}

    	showerror (m);
    }
    else
    {
    	wlog ("", "done with no errors\n");
    }

    stResult = result;
    return result;
}

//***************************************************************************

int main ()
{
    String 		path		= string::alloc ();
    String 		lang		= string::alloc ();
    String 		country		= string::alloc ();
    String 		vlang		= string::alloc ();
    String 		vcountry	= string::alloc ();
    String 		name		= string::alloc ();
    ItemRef 	variant		= document::get_front ();
    ItemRef 	master		= 0;
    int 		wasOpen		= 0;
    
    if (gRun > 1)	return 0;
    if (system::shiftkey ())
    {
    	// Ask for language and country. We put it temporarily into the Master.
    	// This means that the new variant does not have to be opened separately.
    	// At the end the old values are reset again.
    	//
    	xml::get_document_attribute (0, "Language", lang);
    	xml::get_document_attribute (0, "Country", country);
    	string::set (vlang, lang);
    	string::set (vcountry, country);
    	
    	if (!askstring2 (vlang, "Language", 1, vcountry, "Country", 1, 0, 0, 0, 0, 0, 0, "Language Settings of Variant")) return 0;
    	
    	xml::set_document_attribute (0, "Language", vlang);
    	xml::set_document_attribute (0, "Country", vcountry);
    	
    	// The real work is done here: Create the sync next to the master.
    	// You can change this according to your requirements!
    	//
    	document::sync::create_variant (0, "");
    	
    	// Resetting the Master
    	//
    	xml::set_document_attribute (0, "Language", lang);
    	xml::set_document_attribute (0, "Country", country);
    	
    	return 0;
    }

    stErrorMessage	= string::alloc ();
    stResult		= 0;

    // Select the master, open it and set the varaint as to be the front document again
    //
    document::folder (path, 0);		// Get the folder of the variant to open the dialog there
    if (file::select_file (path, "Select Master Document") != 0) return 0;
    wasOpen	= document::is_opened (path);
    master 	= document::open (path);
    document::path (path, master);	
    if (!master || string::length (path) == 0)
    {
    	showerror ("Cannot open master document\n\n%s", master);
    	if (string::length (path) == 0) 
    	if (!wasOpen) document::close (master, 0);
    	return 0;
    }
    document::select (variant);
    
    // Check if a sync of both documents is possible
    //
    if (!document::sync::possible (variant, master))
    {
    	showerror ("Your document is not a variant or the selected document is not a master of it.\n\nBe sure to have documents with same documentID and priint_syncDocType set to 'master' resp. 'variant'.");
    	if (!wasOpen) document::close (master, 0);
    	return 0;
    }
    
    // Write some time stamped log
    //
    wtlog ("", "# STARTING SYNC:\n");
    document::path (path, master);	wlog ("", "	Master 	: '%s'\n", path);
    document::path (path, variant);	wlog ("", "	Variant	: '%s'\n\n", path);
    
    // Prepare the sync
    //
    document::sync::before (variant);
    
    // Do the several sync steps
    //
    while (1)
    {
    	if (apply (prepare_master, variant, master, 13) != 0) break;
    	
    	if (apply (document::sync::swatches, variant, master, 1) != 0) break;
    	if (apply (document::sync::layers, variant, master, 2) != 0) break;
    	
    	if (apply (document::sync::styles, variant, master, 3) != 0) break;
    	if (apply (document::sync::masterspreads, variant, master, 4) != 0) break;
    	if (apply (document::sync::pages, variant, master, 5) != 0) break;
    	
    	if (apply (sync_frames,  variant, master, 6) != 0) break;
    	if (apply (remove_superflous_frames, variant, master, 7) != 0) break;
    	if (apply (rebuild_text_chains, variant, master, 8) != 0) break;
    	if (apply (document::sync::groups, variant, master, 9) != 0) break;
    	
    	if (apply (document::sync::remove_empty_pages, variant, master, 10) != 0) break;
    	if (apply (document::sync::remove_empty_layers, variant, master, 11) != 0) break;
    	if (apply (document::sync::cleanup, variant, master, 12) != 0) break;
        
    	break;
    }
    
    //
    // Clean up
    // PLZ note : We do not save the variant here!
    //
    document::sync::after (variant);
    if (!wasOpen) document::close (master, 0);
    
    wlog ("", "\n");
    if (!stResult)	wtlog ("", "# SYNC FINISHED successfully\n\n");
    else 			wtlog ("", "# SYNC FINISHED with error %d\n\n", stResult);
    
    item::release (master);
    item::release (variant);
    string::release (lang);
    string::release (country);
    string::release (vlang);
    string::release (vcountry);
    string::release (name);
    
    return 0;
}