The comet plugins support creating and updating cross references in documents and books. Cross references can show page numbers and names, document names and paths, and other information, down to the X/Y-coordinates of the referenced object.

This documnet shows you how to define cross references and keep them up to date.

Cross references consist of a definition and any number of references to that definition. Definitions and references do not have to be in the same document, though they have to be in the same book.

Reference definitons are created with the help of InDesign® hyper links.

Cross references are a special type of comet placeholder. In these placeholders' loadscripts you can search the book's or document's reference definitons and insert the contained elements into the document.

By keeping the names as clear as possible, you ensure that references find the correct reference definitions. Of course, that is not always easy, which is why we help you with that : In addition to the name, you can supply a comet ID (consisting of up to three numbers and some text) to identify a reference. These IDs are used in product research, for example. When searching for references, you can usually omit the name altogether and search only by comet ID.

In the document, reference definitons are inserted as hyperlinks. You can view all hyperlinks in a documnet in the Hyperlinks panel, which is included with InDesign®, and can be opened from the menu Window:Interactive:Hyperlinks. It is, however, not needed when creating cross references.

In the hyperlink panel you can see the names of cross references and - when hovering over an entry with your mouse pointer for a while - their comet IDs.

Even with comet IDs, the possibility of multiple reference definitions conflicting cannot be ruled out. InDesign® therefore renames definitons with the same name with a counter, e.g. Paul, Paul 1, Paul 2 usw.. When searching for references, these counters are ignored.

There are four ways to make a new reference Definiton :

In any case, bear in mind that InDesign® does not support nested hyperlinks. This means that you cannot nest reference definitons, either. When inserting a new reference definiton, all hyperlinks touching the new definiton's area are removed from the documnent.

To prevent errors, reference definitons can only be placed entirely inside or entirely outside of comet placeholders, meaning they cannot overlap.

Reference definitons can be highlighted. InDesign® offers multiple frames around the text. These will not be printed! Comet cross references are highlighted with a dashed orange frame by default :

            

InDesign® may delete the ending highlight of a reference (here: after the l in "...ziel") without deleting the opening highlight. When that happens, InDesign® will crash soon, damaging your document file. To prevent that, only define references to a single glyph:

              

This first example is a script that will insert a reference definiton into the document. The reference will be layered on top of the current selection and gets its name from that text. The creation of a cross reference is handled by the textmodel::insert_crossref function.

int main ()
{
    ItemRef      frame      = item::alloc();
    String       str        = string::alloc ();
    Table        t          = table::alloc ();
    List         prod       = list::alloc (3,2,1);
    List         prod2      = list::alloc (3,2,2);
    List         prod3      = list::alloc (3,2,3);
    StringList   prodsid    = stringlist::alloc (3, 2);
    int          start, len, col, row;
    int          res;

    // Validate procuct selection
    if (list::length (prod) == 0)
    {
        showmessage ("No product selected");
        return 0;
    }

    // Fetch document selection
    textmodel::selection (&start, &len, frame, 0, t, &col, &row);
    if (len > 0) textmodel::gettext (str, start, len);

    // Insert reference definition
    res = textmodel::insert_crossref (
            start, len,
            string::get (str),
            3,
            list::get (prod, 0),
            list::get (prod2, 0),
            list::get (prod3, 0),
            stringlist::get (prodsid, 0),
            1, // Visible
            3, // 1-3 frame width
            3, // 1 Invert, 2 Inset, 3 Outline
            1, // 0 Solid, 2 Dashed
            100.0, 0.0, 0.0, -1.0
            0);

    return 0;
}

The next example is for a valid w2cross tag :

<w2cross:
    ''
    3
    14 1 2008 'Paul'
    0
    1
    1
    Outline
    Dashed
    100.0 50.0 0.0 -1.0
    1 >

Cross references are implemented as regular placeholders of the "crossref" type. The following table shows which placeholder attribute you need to set to get a cross reference placeholder.

Attribute Value Environment
type crossref XML and SOAP
RelatedToID 9 ODBC and Oracle

Cross references have their own icon () in the placeholder panel.

        

A similar icon is also used to highlight references in the document. :

       

The definiton of a cross reference placeholder in XML looks like this:

<placeholder>
    <id>123470</id>
    <name>Cross-Reference</name>
    <description></description>
    <type>crossref</type>
    <domain>Tutorial</domain>
    <domainid>2000</domainid>
    <class>3</class>
    <load>2027</load>
    <sync></sync>
    <store>0</store>
    <lov>0</lov>
    <color name="">
        <id>6</id>
    </color>
    <style></style>
    <styleid>0</styleid>
    <syncstateinvisible>0</syncstateinvisible>
    <loadconstraint>0</loadconstraint>
    <active>1</active>
</placeholder>

There are three color variations of the icon, signifying different states:

Color Meaning Automation
Green Okay / 0 set after successful load
Yellow Ambiguous / 2
Changed / -1
set after link with an object
Red Other none

The state is only automatically set in the specific situations explained in the table. In particular, the state is not automatically set to yellow when the document or a document in the book is changed.

Naturally, you can set the state in the load and sync scripts. Please bear in mind, though, that the state is still only set to yellow if the placeholder is modified - it may still be green, despite the document or book changing, which may also affect the reference, undermining the meaning of the green state.

Cross referencs are updated as a consequence of the following actions. In those situations only cross references are reloaded. Other placeholders are ignored.

Please note that cross references are not updated automatically.

Most of the work in cross references is actually done in their loadscripts. You can determine whether the script should execute normally or update cross references by checking the global variable gRepagination: If gRepagination equals 0, you're in a normal load call. Here you can set a (default) set for a reference. If gRepagination equals 1, cross references should be updated and you can search the document / book for the reference definition and store the result in the placeholder.

We considered running cross reference scripts in regular load mode. We went with this option because it allows users to load cross referencses individually, set their state or whatever else may please them.

In the placeholders' loadscript, use the script functions hyperlink::find1 or hyperlink::find to search for the desired reference definiton (or a lost of those reference definitions), and insert the desired text into the document (e.g. with textmodel::replace). Usually, the function find1 will suffice, because it fetches exactly one piece of information about a reference definition as a string and inserts it directly.

If you want to insert multiple pieces of information (from the same reference, too), it is better to use the find function instead. Find1 would have to search the entire book once for each piece, in this scenario.

This example searches for the first definiton of the current placeholder object and inserts its page number and document name into the document. Attentive readers will notice that the script has at least three weaknesses:

1. It is executed during normal loads.
2. It does not define any behaviour for the case when no definition is found.
3. find1 is called twice.

Before using this script, please have a look at the following example.

int main ()
{
    char pg [512];

    wlog ("", "Cross refed called, placeholder %d (%d)\n",
                gPlaceholderID, gRepagination);

    strcpy (pg, "Page ");
    strcat (pg, hyperlink::find1 (
                0,     // (unused) return variable
                "Page",// Value name
                0,     // First reference definition
                0,     // Current document or its book
                "",    // Do not test reference name
                3,     // object class "Product"
                gRecordID, gRecordID2, gRecordID3, gRecordStringID,
                1));   // Search the entire book

    strcat (pg, " (<CharStyle:Italic>");
    strcat (pg, hyperlink::find1 (
                0,
                "DocName",
0, 0, "",
                3, gRecordID, gRecordID2, gRecordID3, gRecordStringID,
                1, 1, 1, 1, 1));
    strcat (pg, "<CharStyle:>)");

    textmodel::replace (pg);
   
    return 0;
}

The following example is more clever. It also fetches the values from the first reference definition. But then the document text from the definiton's location is also fetched and copied into the reference. Bear in mind that text is fetched from one character after the definition's location. There's an InDesign® hyperlink symbol at the actual location.

Furthermore, this script also takes its execution context into account; in normal load mode, it will set the placeholder's state to 'changed'. If the cross reference fails to be resolved, the state is set to 'error' instead.

int find_word (String str, char * result)
{
    char * abbrev = 0;

    *result = 0;
    if (!str || !string::length (str)) return 1;
    abbrev = string::get (str);

    if (strtokencount (abbrev, ' ') < 2) strcpy (result, abbrev);
    else
    {
        strcat (result, strword (abbrev, 0));
        strcat (result, strword (abbrev, 1));
        strcat (result, strword (abbrev, 2));
    }

    return 0;
}

int main ()
{
    LinkList    lks = 0;
    int         res = 0;
    Link        lk  = 0;
    char        txt [2000];
    String      str = 0;

    wlog ("", "Cross refed called, placeholder %d (%d)\n",
                gPlaceholderID, gRepagination);

    // Regular load call
    if (!gRepagination)
    {
          // Set state to "changed"
        placeholder::set_sync (-1);
        *gSyncChanged = 1;
        return 0;
    }

    // Find the reference definition
    lks = linklist::alloc ();
    res = hyperlink::find (
              lks,        // Result list
              0,          // Current document
              "",         // Ignore the reference name
              3,          // object class "Product"
              gRecordID, gRecordID2, gRecordID3, gRecordStringID,
              1,          // Search the entire book
              1, 1, 1, 1, // page name formatting
              1);         // Calculate XY-coordinates of the cross reference
    if (res != 0)
    {
        // Set the state to "error"
        wlog ("", "# Error %d while searching cross references\n", res);

        linklist::release (lks);
        placeholder::set_sync (-4);
        *gSyncChanged = 1;

        return 0;
    }

    // Text of the cross reference
    if (linklist::length (lks) == 0)
    {
        sprintf (txt, "Reference not found [%d, %d, %d, '%s']",
              gRecordID, gRecordID2, gRecordID3, gRecordStringID);
    }
    else
    {
        lk = linklist::first (lks);

        // Fetch text after the definition location
        str = string::alloc ();
        frame::gettext (
              link::crossref::frame (lk),
              str,
              link::crossref::pos (lk)+1, 200);

        sprintf (txt, "Seite %d [%fx%f]",
              link::crossref::page (lk, 0),
              link::crossref::x (lk),
              link::crossref::y (lk));

         if (string::length (str))
         {
             char word[2000];

             find_word (str, word);
             strcat (txt, " (");
             strcat (txt, word);
             strcat (txt, ")");
             string::release (str);
         }
    }

    // Insert text
    textmodel::replace (txt);

    linklist::release (lks);

    return 0;
}

The following script functions may help you create the reference text :

Function Summary
hyperlink::find Find all definitions by name and/or ID within the document or entire book
hyperlink::find1 Find the value of a defintion attribute by the name and/or ID of the reference
link::crossref::document Document name, folder and path of the reference definition
link::crossref::page Page number of the reference definiton
link::crossref::pagename Page name of the reference definiton
link::crossref::name Name of the reference definition
link::crossref::destination ID of the reference definiton
link::crossref::x XZ coordinate of the reference definition within text
link::crossref::y
link::crossref::left frame coordinates of the reference definition
link::crossref::top
link::crossref::right
link::crossref::bottom
link::crossref::pos Textposition of the reference definition
link::crossref::frame Frame of the reference definition