Find an XRef backwards - not successfull in all cases

Advocate ,
Jul 01, 2019

Copy link to clipboard

Copied

Dear Friends,

Again I have probably a weird idea: Add a cross reference in front of a footnote reference which points to that footnote.

See the FM document (FM15).

The cross reference text to be inserted is just an ellipsis. Then the whole construct (ellipsis + FN reference) will receive a character format to indicate the 'hotspot'.

Obviously I'm struggling with finding the stuff (nothing, cross-ref ellipsis, another crossref very far) in front of the FN reference.

The script first collects the FN refs of the document in an array, which allows me easy handling them back to front, thus not destroying locations of the FN anchors by inserting the ellipsis XRefs.

Most time the script works correctly, but in this test it fails at the FN anchor 3). It finds the ellipsis behind! It seems that the Find in line 67 does not search backwards but forwards.

Output of the script in first run:

Fn string =5)

    XRef is there:false

Fn string =4)

    oTL.offset=51 oTextItem.offset=281 dOffset=-230

    XRef is there:false

Fn string =3)

    oTL.offset=50 oTextItem.offset=51 dOffset=-1

    XRef is there:true                   <<< why?

Fn string =2)

    oTL.offset=310 oTextItem.offset=281 dOffset=29

    XRef is there:false

Fn string =1)

    oTL.offset=214 oTextItem.offset=310 dOffset=-96

    XRef is there:false

Output of the script in the second run is absolutely weird. None of the present ellipsis XRefs is found and hence new ellipsis XRefs are inserted!

Fn string =5)

    oTL.offset=284 oTextItem.offset=214 dOffset=70

    XRef is there:false

Fn string =4)

    oTL.offset=54 oTextItem.offset=284 dOffset=-230

    XRef is there:false

Fn string =3)

    oTL.offset=50 oTextItem.offset=54 dOffset=-4

    XRef is there:false

Fn string =2)

    oTL.offset=316 oTextItem.offset=50 dOffset=266

    XRef is there:false

Fn string =1)

    oTL.offset=217 oTextItem.offset=316 dOffset=-99

    XRef is there:false

The script is not that long - but obviously I make a bad mistake somewhere - with the evaluation of the text locations. Can anyone spot this ? You must know that we currently have some heat here in Switzerland - so my brain may be somewhat out of order.

// HandleFootnote.jsx

#target framemaker

main ();

function main () {

var nNotes, oDoc;

  oDoc = app.ActiveDoc;

  nNotes = EnhanceInDoc (oDoc);

  alert ("Number of footnotes handled: " + nNotes);

}

function EnhanceInDoc (oDoc) { //=== enhance footnotes in current document ===================

// Arguments oDoc   Current document

// Returns   Number of Footnote refs which got an XRef to the footnote

var bOK, aFnList = [], docStart, foundTR, j, k, lFnRef, lenFnList, nNotes=0,

    sXRefFmt = "zfnref-footnote-reference", oEFN, oFindParams, oLocation, oFnTI,

    oLocation, oObject, oPage, oTextItem, oTL, oTL1, oTL2, oTR, tloc;

   

  aFnList.length = 0;                             // clear array

  docStart = oDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;

  tloc = new TextLoc (docStart, 0);

  oDoc.TextSelection = new TextRange (tloc, tloc); // essential

  oFindParams= GetFindParameters (7, "");     // Find footnote anchor

  foundTR = oDoc.Find(tloc, oFindParams);

  while (foundTR.beg.obj.ObjectValid()) { 

    aFnList.push(foundTR);                        // fill array for next 'step'

    tloc = foundTR.end; 

    foundTR = oDoc.Find(tloc, oFindParams); 

  }

  lenFnList = aFnList.length;

  if (lenFnList < 1) {

    return null;                                  // common situation for new document

  }

// ---------------------------------------------- Insert link to footnote -------------------------

  for (j = lenFnList-1; j >=0; j--) {             // handle in reverse order to keep locations

  oFnTI = oDoc.GetTextForRange (aFnList, Constants.FTI_FnAnchor);

  for (k = 0; k < oFnTI.length; k++) { 

    oTextItem = oFnTI;     

    oObject = oTextItem.obj;                      // object Fn

    oTL   = oObject.TextLoc;                      // Location of the footnote anchor (beg)

$.writeln ("Fn string =" + oObject.FnAnchorString);

    bOK = CheckXRef (oDoc, oTL, sXRefFmt);

$.writeln ("\tXRef is there:" + bOK);

    if (bOK) {

      break;                                      // already an XRef inserted

    } else {

      lFnRef  = oObject.FnAnchorString.length;

      InsertXRef (oDoc, oTL, sXRefFmt, oObject, lFnRef);

      nNotes += 1;                                // statistics, quick answer

    }

  }

}

  return nNotes;

} //--- end EnhanceInDoc 

function CheckXRef (oDoc, oTL, sXRefFmt) { //=== Test XRef at location before FN reference? ===

// Arguments  oDoc:       Document receiving the XRef and containing the target marker

//            oTL:        Text location where the XRef is assumed

//            sXrefFmt:   Cross reference format name assumed

// Returns    true if an XRef exists inserted by InsertXRef.

//            false if no XRef present or not of this kind.

// Called by  EnhanceInDoc

var dOffset, foundTR, k, oFindParams, oObject, oTextItem, oXRefTI;

  oFindParams= GetFindParameters (8, "");         // find XRef backwards

  InitFA_errno ();                                // reset - it is write protected

  foundTR = oDoc.Find(oTL, oFindParams);

  if(FA_errno === Constants.FE_Success) {         // there may be nothing in front of FN-ref

    oXRefTI  = oDoc.GetTextForRange (foundTR, Constants.FTI_XRefBegin);

    for (k = 0; k < oXRefTI.length; k++) { 

      oTextItem = oXRefTI;     

      oObject = oTextItem.obj;                    // object XRef ?

      dOffset = oTL.offset - oTextItem.offset;    // Crucial part not yet working correctly

$.writeln("\toTL.offset="+oTL.offset +" oTextItem.offset="+oTextItem.offset +" dOffset="+dOffset);

      if (oObject.XRefFmt.Name == sXRefFmt) {     // this may be be a wrapped around XRef!

        if (dOffset <= 3 && dOffset >= -1) { return true;} // inserted item is close

      }

    }

  }

  return false;

} //--- end CheckXRef

function InsertXRef (oDoc, oTL, sXRefFmt, oTgtObj, lFnRef) { //=== Insert XRef at location ============

// Arguments  oDoc:       Document receiving the XRef and containing the target marker

//            oTL:        Text location Where to insert the  XRef. May be empty, defining only an Insertion Point

//            sXrefFmt:   Cross reference format name from the catalogue

//            oTgtObj:    To where the XRef shall point

//            lFnRef:     Length of the FN reference string

// Returns    -

// Called by  EnhanceInDoc

// Comment    This script handles only reference and target in the same document

// Reference  https://forums.adobe.com/thread/2088696

var oEFN, oHTR, oMarker, oXRef, sXRefID, oFnPgf, oTloc;

//                                                --- Prepare the required information ------------

  sXRefID = oTgtObj.id + ":" + oTgtObj.Unique;    // take properties from the oTgtObj

  oFnPgf  = oTgtObj.FirstPgf;

  oTloc   = new TextLoc (oFnPgf, 0);

//                                                --- Create the Cross reference Marker -----------

  oMarker = oDoc.NewAnchoredMarker(oTloc);        // Marker to be inserted in target object

  oMarker.MarkerTypeId = oDoc.GetNamedMarkerType ("Cross-Ref"); //Make it a Cross-Ref marker

  oMarker.MarkerText = sXRefID;                   // Marker text needs to be unique

//                                                --- Create the Cross reference ------------------

  oXRef = oDoc.NewAnchoredFormattedXRef(sXRefFmt, oTL); // Insert a new xref object

  oXRef.XRefSrcIsElem = false;                    // Required to make it an unstructured xref

  oXRef.XRefFile = oDoc.Name;                     // Required for same file ?

  oXRef.XRefSrcText = oMarker.MarkerText; 

  oDoc.UpdateXRef(oDoc, oXRef);                   //Update the new xref.

//                                                --- Apply character format to whole construct ---

  oEFN = oXRef.TextRange.end;                     // end of XRef

  oEFN.offset = oEFN.offset + lFnRef;             // after FN ref string

  oHTR = new TextRange (oXRef.TextRange.beg, oEFN); 

  applyCharFmt (oHTR, "hypertext", oDoc) ;

} //--- end InsertXRef

function GetFindParameters (iType, sSearch) { //=== set up parameters for various find actions ====

// Arguments iType:   what find to be performed

//                    7  Footnote (anchor)

//                    8  Cross reference, backwards

//           sSearch: what to search for (other types)

// Returns   Parameters for the find method

var findParams, propVal;

  findParams = new PropVals() ;

  switch (iType) {

    case 7: // ---------------------------------- find any Footnoe

      propVal = new PropVal() ; 

      propVal.propIdent.num = Constants.FS_FindWrap ; 

      propVal.propVal.valType = Constants.FT_Integer; 

      propVal.propVal.ival = 0 ;                  // don't wrap

      findParams.push(propVal); 

      propVal = new PropVal() ; 

      propVal.propIdent.num = Constants.FS_FindObject; 

      propVal.propVal.valType = Constants.FT_Integer; 

      propVal.propVal.ival = Constants.FV_FindFootnote ; 

      findParams.push(propVal); 

      return findParams;

    case 8: // ---------------------------------- find any cross reference backwards

      propVal = new PropVal() ; 

      propVal.propIdent.num = Constants.FS_FindWrap ; 

      propVal.propVal.valType = Constants.FT_Integer; 

      propVal.propVal.ival = 0 ;                  // don't wrap

      findParams.push(propVal); 

      propVal = new PropVal() ; 

      propVal.propIdent.num = Constants.FS_FindCustomizationFlags ; 

      propVal.propVal.valType = Constants.FT_Integer; 

      propVal.propVal.ival = Constants.FF_FIND_BACKWARDS ;

      findParams.push(propVal); 

      propVal = new PropVal() ; 

      propVal.propIdent.num = Constants.FS_FindObject; 

      propVal.propVal.valType = Constants.FT_Integer; 

      propVal.propVal.ival = Constants.FV_FindAnyXRef ; 

      findParams.push(propVal); 

      return findParams;

    default:

      alert ("GetFindParameters: Case " + iType + " is not defined");

      return null;

  }

} //---  end GetFindParameters

function applyCharFmt (textRange, name, doc) { //=== Apply character format ========================

  var charFmt = 0; 

  charFmt = doc.GetNamedCharFmt (name); 

  if (charFmt.ObjectValid()) { 

    doc.SetTextProps (textRange, charFmt.GetProps()); 

  } 

} //---  end applyCharFmt

TOPICS
Scripting

Views

292

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

1 Correct Answer

Advocate , Jul 01, 2019
K.Daube Advocate , Jul 01, 2019
Markus, thanks for Your ideas - but...Out of curiosity I wanted to see what is selected when the Find backward was performed and insertedoDoc.TextSelection = new TextRange (oTL, oTL); // essentiaafter line 41.Then I observed that dOffset never became -1 and I eliminated the before mentioned insertion after line 75...IMHO this is strange - but it seems to solve my problem.

Likes

Translate

Translate
Jump to answer Jump to answer
K.Daube AUTHOR
Advocate ,
Jul 01, 2019

Copy link to clipboard

Copied

To go further with my project I decided to insert after line 75:

if (dOffset == -1)  { return false;} // The strange case

Obviously I need many more tests here, but for the time beeing brute force is applied.

I will come back and report - if I found I a better solution (based on the additional tests).

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Engaged ,
Jul 01, 2019

Copy link to clipboard

Copied

Hi Klaus,

I don't understand what you are doing here in detail (too hot here and too complex use gase 🙂 ).

But do you think it's a good id to use FM's find function to find previous object.

Isn't there a Chance to link These objects more intelligent, like

1. Maybe you can use UserString property (careful others can use them, too)

2. add an id to crossref (ie. UserString = crossref_4711)

3. add an id to corresponding graphic object (ie. UserString = Ellipse_4711)

So have a a link between both (or more) objects.

Maybe you can also use graphic grouping, to Keep objects together, which belongs together.

I do not know how far I shot past, Maybe I misunderstood everthing 😉

Markus

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Advocate ,
Jul 01, 2019

Copy link to clipboard

Copied

Markus, thanks for Your ideas - but...

Out of curiosity I wanted to see what is selected when the Find backward was performed and inserted

oDoc.TextSelection = new TextRange (oTL, oTL); // essentia

after line 41.

Then I observed that dOffset never became -1 and I eliminated the before mentioned insertion after line 75...

IMHO this is strange - but it seems to solve my problem.

Likes

Translate

Translate

Report

Report
Reply
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more