0 Replies Latest reply on Jul 7, 2015 6:14 AM by K.Daube

    First found item not replaced - random behaviour

    K.Daube Level 1

      Dear friends and experts

      In my project I use a (minor) modification of Ian Proudfoot's find/replace script.
      The find- and replace-strings are taken from global arrays (which are filled from an RTF file).
      Randomly the first call of the function FindAndReplaceString does not find/replace the item in question.
      A trace of the function calls gives these results (first few items only):

       

      ~~~~ReplaceInDoc
      ~~~~~~FindAndReplaceString
      find = >{Bartels, 1981 #14}< replace = >[1]<
      ~~~~~~FindAndReplaceString
      find = >{Daube, 1989 #6}< replace = >[2]<
         success
      ~~~~~~FindAndReplaceString
      find = >{Daube, 2005 #15}< replace = >[3]<
         success

      Since the whole script is far to long for a justification of the problem, I have set up a testprogram which defines the findreplce stings directly (the test file is here):

       

      /* use test file t-find-replace.fm
      There must be a subtle differene to the real script environment:
      This test exhanges all occurrances
      In FM-bilbio.jsx only the secont-to-last item is found and replaced. 
      */
      var doc = app.ActiveDoc;
      var flow = doc.MainFlowInDoc;             // collection would have been failed, if flow/frame invalid
      var inString = ["{Daube, 2005 #15}", "{Müller, 1925 #13}", "{Sèsíüs,  #26}"];
      var outString = ["[15]", "[19]", "[23]"];
      
      for (j = 0; j < 3; j += 1) {
        FindAndReplaceString (doc, inString[j], outString[j], 100);
      }
      
      
      function FindAndReplaceString (activeDoc, findString, replaceString, loopMax) {
      // FindText, ConsiderCase; Function returns replacemtCounter
      // Since we have collected only in doc.MainFlowInDoc, we replace only in this flow
      // loopMax used as emrgency back door - twice the # of initially found citations
      // We do not have an initial TextSelection, hence start directly at the first para
      // Source: https://forums.adobe.com/message/3888653#3888653 by Ian Proudfoot
      Console ("find = >" + findString + "< replace = >" + replaceString + "<"); 
        var tr = new TextRange();
        var restoreTR, frame = 0, loopCounter = 0, replacementCounter = 0;
        var findParams = new PropVals();
        var firstPgf = activeDoc.MainFlowInDoc.FirstTextFrameInFlow.FirstPgf;
        
        tr.beg.obj = tr.end.obj = firstPgf;             //  set up the starting text range as the very beginning
        tr.beg.offset = tr.end.offset = 0;              // of the flow. We'll move straight from beginning to end.
        trSaved = tr                                    // to come back after work
      //Set up find parameters. We want to configure it to look for a string and perhaps be case sensitive.
      //We don't need the find to wrap because we are controlling the flow from beginning to end.
        findParams = AllocatePropVals(2);
        
        findParams[0].propIdent.num = Constants.FS_FindText;
        findParams[0].propVal.valType = Constants.FT_String;
        findParams[0].propVal.sval = findString;
        
        findParams[1].propIdent.num = Constants.FS_FindCustomizationFlags;
        findParams[1].propVal.valType = Constants.FT_Integer;
        findParams[1].propVal.ival = Constants.FF_FIND_CONSIDER_CASE;
      
        FA_errno = Constants.FE_Success;                // errno global, to be used to track the progress of the find and replace
        tr = activeDoc.Find(tr.beg, findParams);        // and do an initial find to get started.
        
        while(FA_errno === Constants.FE_Success && loopCounter++ < 2*loopMax) { //find and replace loop as long as we keep finding
          activeDoc.TextSelection = tr;                 // set up the text range to clear the original text
          activeDoc.Clear(0);                           // clear it
          activeDoc.AddText(tr.beg, replaceString);     // insert the new text at the original beginning of the text range
          tr.beg.offset += replaceString.length;        //  lets jimmy the text range in memory to place it directly after
                                                        //  the string we just inserted, so the find picks back up after that.
          if(FA_errno === Constants.FE_Success) {       // increment our return counter
            replacementCounter++;
      Console ("   success"); // <=== debugging ====================
          }
          FA_errno = Constants.FE_Success;              // ...  find the next instance. We'll reset FA_errno again just in case
          tr = activeDoc.Find(tr.beg, findParams);      // something screwy happened while we were replacing text.
        }
        activeDoc.ScrollToText(trSaved);                // we're done. Restore the document to it's original area of display
        return replacementCounter;
      } // --- end FindAndReplaceString
      

       

      And guess what?

      • opening the test-doc and running script => First item not found/replaced
      • opening the test-doc and running script => OK (all 3 items found/replaced)
      • opening the test-doc and running script => OK
      • opening the test-doc, efresh script in catalogue, run script => OK
      • opening the test-doc and running script => OK
      • opening the test-doc and running script => OK
      • After 3h of testing I'm tired now

      I have not the slightest idea what may cause the random behaviour. Do You have any (the highest temparature sensed on the main board is 50°C  (122°F) - not that alarming).