22 Replies Latest reply on Feb 10, 2015 1:45 AM by rombanks

    ES for FM10: Adding text at insertion point

    rombanks Level 1

      Hello fellows,

       

      What's the code for current insertion point (where the cursor is currently placed?)

      I saw code for adding text in the beginning/end of pgf but not at the current insertion point.

       

      Thank you in advance!

        • 1. Re: ES for FM10: Adding text at insertion point
          frameexpert Level 4

          Assuming doc is the active document, this will give you the current text selection:

           

          var textRange = doc.TextSelection;

           

          To get the insertion point, use either:

           

          var textLoc = doc.TextSelection.beg;

           

          or

           

          var textLoc = doc.TextSelection.end;

           

          -Rick

          • 2. Re: ES for FM10: Adding text at insertion point
            rombanks Level 1

            Hi Rick,

             

            Thank you for your response and suggestion!

             

            The following code does not do anything while the cursor is in a paragraph,. Am I missing something?

             

            var doc = app.ActiveDoc;

            var Tsel = doc.TextSelection;

            var TextLoc = Tsel.beg;

             

            doc.AddText (TextLoc, "Test ");

             

            Thank you!

            • 3. Re: ES for FM10: Adding text at insertion point
              frameexpert Level 4

              Try using textLoc instead of TextLoc for your variable. TextLoc with this spelling is a reserved word.

              • 4. Re: ES for FM10: Adding text at insertion point
                rombanks Level 1

                Hi Rick,

                 

                Thank you for your prompt response! The script now works. The only problem is that while using the script to insert the text, there is no Undo. There is no instruction in the code to save the file.

                Is there a way to prevent FM from saving the change immediately?

                Thanks again!

                • 5. Re: ES for FM10: Adding text at insertion point
                  Russ Ward Level 4

                  rombanks,

                   

                  Regarding undo, by default there is no undo for FDK/ES actions. However, there is information in the latest FDK manual about setting "checkpoints", which presumably registers the current state of a document in the undo stack. The implication is that you can programmatically allow your changes to be undone. However, I have never used it so I don't know anything about its behavior. Plus, the latest scripting guide (most recent update is for FM10) doesn't really contain any information. Therefore, I'm not clear on whether it works at all for ES and for FM10 period. If you want to explore further, get the latest FDK reference and look up:

                   

                  F_ApiUndoStartCheckPoint()

                  F_ApiUndoEndCheckPoint()

                   

                  Russ

                  • 6. Re: Re: ES for FM10: Adding text at insertion point
                    frameexpert Level 4

                    Here is an example that illustrates how it works. I tested this in FM 12 so I am not sure about earlier versions.

                     

                    #target framemaker
                    
                    // Turn on undo recording.
                    app.UndoFDKRecording = true;
                    
                    var doc = app.ActiveDoc;
                    
                    // Set a starting point for "recording" behavior that can be undone.
                    // The string is what you will see next to the Undo command in the Edit menu
                    // and the History panel.
                    doc.UndoStartCheckPoint ("Add text");
                    
                    // Add some text at the current insertion point.
                    var textLoc = doc.TextSelection.beg;
                    doc.AddText (textLoc, "Test");
                    
                    // Set an end point for this operation.
                    doc.UndoEndCheckPoint ();
                    

                     

                    I believe that this was added back in one of the FrameMaker 7 releases. I used this as far back as 2006 in one of my FrameScript scripts. I haven't found it very useful though; it only shows up in about 20 of over 6,000 scripts that I have written. There are certain operations that are not undoable and clear the undo buffer. For example, if you call a function after line 15 to apply a paragraph format, the undo buffer is cleared and you can't undo the "Add text" that you did in line 15.

                     

                    The InDesign scripting API is way ahead as far as undos. You can undo an entire script (most of the time) or you can undo each step that the script performs.

                     

                    -Rick

                    • 7. Re: ES for FM10: Adding text at insertion point
                      rombanks Level 1

                      @Russ, thank you for your suggestion!

                       

                      @Rick, thank you for the sample script!


                      I appreciate your help, guys!

                      • 8. Re: ES for FM10: Adding text at insertion point
                        rombanks Level 1

                        Guys,

                         

                        I need your advice. I am trying to programmatically apply a condition (called Comment) to the string I added at the insertion point. So I wrote the following code:

                         

                        var doc = app.ActiveDoc;

                        var Tsel = doc.TextSelection.beg;

                        var My_comment = "<Check>";

                        doc.AddText (Tsel, My_comment);

                        var tr = new TextRange();

                        tr.beg.obj = tr.end.obj = My_comment;

                        newFmt = doc.GetNamedCondFmt("Comment");

                        var props = doc.GetTextPropVal(tr.beg.object, Constants.FP_InCond)

                                    props.propVal.isval[0] = newFmt.id

                                    props.propVal.osval[0] = newFmt

                                    doc.SetTextPropVal(tr, props)

                         

                        I am not sure how to select the text string I've inserted.

                        I've tried to select the text range by using  tr.beg.obj = tr.end.obj = My_comment; but this does not seem to work. Please, advise!

                         

                        Thank you in advance!

                        • 9. Re: Re: ES for FM10: Adding text at insertion point
                          frameexpert Level 4

                          Hi Roman, Try the code below:

                           

                          var doc = app.ActiveDoc;
                          var Tsel = doc.TextSelection.beg;
                          var My_comment = "<Check>";
                          var textLoc = doc.AddText (Tsel, My_comment);
                          var tr = new TextRange(new TextLoc (textLoc.obj, textLoc.offset - My_comment.length), textLoc);
                          doc.TextSelection = tr;
                          

                           

                          -Rick

                          • 10. Re: Re: ES for FM10: Adding text at insertion point
                            rombanks Level 1

                            Hi Rick,

                             

                            Thank you for your response! Could you please explain line 05?

                            For some reason, running the script adds the text string and FM (10) crashes immediately after that.

                            • 11. Re: Re: Re: ES for FM10: Adding text at insertion point
                              frameexpert Level 4

                              First of all, try commenting out line 06. Does FrameMaker still crash?

                               

                              Here is the explanation: a document's TextSelection property is the current text selection or insertion point in the document. It is a TextRange object. A TextRange is made up of two TextLoc objects, one at the beginning of the selection and one at the end. (If you just have an insertion point, but TextLocs will be the same.)

                               

                              Here is how to make a TextRange for the first 2 characters of the paragraph containing the insertion point:

                               

                              var doc = app.ActiveDoc;
                              var pgf = doc.TextSelection.beg.obj;
                              var tr = new TextRange (new TextLoc (pgf, 0), new TextLoc (pgf, 2));
                              // Select the text range.
                              doc.TextSelection = tr; // Does this crash FM 10?
                              

                               

                              I have a meeting to attend, but will follow up later. See if FrameMaker still crashes if you comment out line 06.

                              • 12. Re: Re: Re: ES for FM10: Adding text at insertion point
                                rombanks Level 1

                                Hi Rick,

                                 

                                Thank you for your explanations! I appreciate your help!

                                FM crashes even if you comment out line 6. BTW, why do we need "textLoc" in the end of line 5?

                                And what's the difference between

                                doc.TextSelection.beg and doc.TextSelection.beg.obj


                                Thank you again and have a great day!

                                • 13. Re: ES for FM10: Adding text at insertion point
                                  rombanks Level 1

                                  Hi Rick,

                                   

                                  After looking into the object reference guide, it seemed to me that the following script should have worked correctly.

                                   

                                  var doc = app.ActiveDoc; 

                                  var Tsel = doc.TextSelection.beg; 

                                  var My_comment = "<Check>"; 

                                  var textLoc = doc.AddText (Tsel, My_comment); 

                                  var offs = textLoc.offset - My_comment.length;

                                  var Tbeg = new TextLoc (textLoc.obj, offs);

                                  var trange = new TextRange(Tbeg, textLoc); 

                                  doc.TextSelection = trange;

                                  newFmt = doc.GetNamedCondFmt("Comment");

                                  var props = doc.GetTextPropVal(trange.beg.Object, Constants.FP_InCond)

                                              props.propVal.isval[0] = newFmt.id

                                              props.propVal.osval[0] = newFmt

                                              doc.SetTextPropVal(trange, props)

                                   

                                  It adds the text, but does not apply the condition to the text range. Moreover, when trying to run the script again, I get an error message saying "Engine is Busy". I have to restart FM to run the script again. Have you encountered this issue before?

                                   

                                  Thanks you!

                                  • 14. Re: ES for FM10: Adding text at insertion point
                                    frameexpert Level 4

                                    This

                                     

                                    var props = doc.GetTextPropVal(trange.beg.Object, Constants.FP_InCond)

                                     

                                    should be this

                                     

                                    var props = doc.GetTextPropVal(trange.beg, Constants.FP_InCond);

                                     

                                    -Rick

                                    • 15. Re: ES for FM10: Adding text at insertion point
                                      rombanks Level 1

                                      Hi Rick,

                                       

                                      Thank you for your response and for the suggestion! The condition is indeed applied.

                                      The problem is that Framemaker crashes right after the text is inserted.

                                      The question is if there is something wrong with the script (although I doubt) or with FM v10 (that partially supports ES)...

                                       

                                      I'll try to port this script to Framescript. It seems that it is a more mature and stable scripting environment and provides better integration with FM.

                                       

                                      Thank you again!

                                       

                                      Best wishes,

                                      Roman

                                      • 16. Re: ES for FM10: Adding text at insertion point
                                        frameexpert Level 4

                                        Hi Roman, I am not sure what is going on. I tried it in 10 and 12 and didn't get the crash. -Rick

                                        • 17. Re: ES for FM10: Adding text at insertion point
                                          rombanks Level 1

                                          Hi Rick,.

                                           

                                          To rule out a local problem, I tested the script on 2 computers with Framemaker v.10.0.2.419 installed. FM crashes immediately after running the script.


                                          In any case, I've started porting the script to Framescript, and there is something that is not clear to me.


                                          When you deduct My_comment.length from textLoc.offset (as below), aren't you supposed to get the offset of the text that comes to the left of textLoc.offset? That's what at least happens when using Framescript.


                                          var textLoc = doc.AddText (Tsel, My_comment);

                                          var offs = textLoc.offset - My_comment.length;

                                           

                                          Thank you for your help in advance!

                                          Roman

                                          • 18. Re: ES for FM10: Adding text at insertion point
                                            rombanks Level 1

                                            I am basically done with porting this script to Framescript. I would also like to add a marker in the middle of the text string I am adding with the script.

                                             

                                            AFAIK, the New Marker definition includes the TextLoc parameter that defines the location of the marker. If the TextLoc is not specified, the marker is added at the insertion point.

                                             

                                            So, in my script, I specified the TextLoc as the text range end offset - (minus)  3.

                                             

                                            However, the TextLoc is for some reason ignored and the marker is added before the 1st character of the added text string.

                                             

                                            Any ideas what could be wrong?

                                             

                                            Thank you in advance!

                                            Roman

                                            • 19. Re: ES for FM10: Adding text at insertion point
                                              frameexpert Level 4

                                              Roman, can you post your code so I can take a look? Thanks. -Rick

                                              • 20. Re: ES for FM10: Adding text at insertion point
                                                rombanks Level 1

                                                Hi Rick,

                                                 

                                                No problem, here it is:

                                                 

                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                                                IF ActiveDoc = 0

                                                MsgBox 'There is no active document.';

                                                LeaveSub;

                                                ELSE

                                                SET vCurrentDoc = ActiveDoc;

                                                ENDIF

                                                 

                                                Set Tsel = vCurrentDoc.TextSelection;

                                                Set My_comment = '<Sample Text>';

                                                New Text TextLoc (Tsel) My_comment;

                                                 

                                                Set vStartOffset = Tsel.Offset;

                                                Set vEndOffset = Tsel.Offset + My_comment.Size +1;

                                                 

                                                New TextRange NewVar(vTextRange) Object(Tsel) Offset (vStartOffset) Object(Tsel) Offset(vEndOffset);

                                                 

                                                Set vMarkerLoc = vEndOffset - 5;

                                                 

                                                New Marker NewVar(vMarker) MarkerName('Index') MarkerText('sample marker') TextLoc(vMarkerLoc);

                                                 

                                                Apply TextProperties CondFmt('Comment') TextRange(vTextRange);

                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                                                Thanks!

                                                Roman

                                                • 21. Re: ES for FM10: Adding text at insertion point
                                                  frameexpert Level 4

                                                  OK, a few small corrections with explanations:

                                                   

                                                  New Text TextLoc(Tsel.Begin) My_comment;

                                                   

                                                  Tsel is a TextRange (so is vCurrentDoc.TextSelection) and New Text requires a TextLoc. So you use .Begin to get the TextLoc at the beginning of the TextRange.

                                                   

                                                  Set vStartOffset = Tsel.Begin.Offset;

                                                  Set vEndOffset = Tsel.Begin.Offset + My_comment.Size +1;

                                                   

                                                  Since Tsel is a TextRange, it doesn't have an Offset property. A TextLoc does so you use Tsel.Begin.

                                                   

                                                  New TextRange NewVar(vTextRange) Object(Tsel.Begin.Object) Offset (vStartOffset) Offset(vEndOffset);

                                                   

                                                  Tsel is a TextRange, not a text object, so you need Tsel.Begin.Object to get the text object for the TextRange. Since your TextRange is in a single paragraph, you only need one Object parameter.

                                                   

                                                  Set vMarkerLoc = vEndOffset - 5;

                                                   

                                                  You don't need this any more.

                                                   

                                                  New TextLoc NewVar(vMarkerLoc) Object(Tsel.Begin.Object)

                                                    Offset(vTextRange.Begin.Offset+3);

                                                   

                                                  You can use this to make a location for the Index marker. It will offset the marker 3 characters from the front of the text range.

                                                   

                                                  Here is the whole thing:

                                                   

                                                  IF ActiveDoc = 0

                                                    MsgBox 'There is no active document.';

                                                    LeaveSub;

                                                  ELSE

                                                    SET vCurrentDoc = ActiveDoc;

                                                  ENDIF

                                                   

                                                  Set Tsel = vCurrentDoc.TextSelection;

                                                  Set My_comment = '<Sample Text>';

                                                   

                                                  New Text TextLoc (Tsel.Begin) My_comment;

                                                   

                                                  Set vStartOffset = Tsel.Begin.Offset;

                                                  Set vEndOffset = Tsel.Begin.Offset + My_comment.Size+1;

                                                  New TextRange NewVar(vTextRange) Object(Tsel.Begin.Object) Offset (vStartOffset) Offset(vEndOffset);

                                                   

                                                  New TextLoc NewVar(vMarkerLoc) Object(Tsel.Begin.Object)

                                                    Offset(vTextRange.Begin.Offset+3);

                                                  New Marker NewVar(vMarker) MarkerName('Index') MarkerText('sample marker') TextLoc(vMarkerLoc);

                                                   

                                                  Apply TextProperties CondFmt('Comment') TextRange(vTextRange);

                                                  • 22. Re: ES for FM10: Adding text at insertion point
                                                    rombanks Level 1

                                                    Hi Rick,

                                                     

                                                    First of all, thank you for reviewing the code and providing your valuable input!

                                                    It was a great coding lesson, and I learnt a lot, owing to your great input.

                                                     

                                                    It is interesting that the text insertion part did work with the "dirty" code I originally created. I wonder why Framescript allows for such flexibility (which is a great capability too, by the way :-)).

                                                     

                                                    My next step is trying to understand what went wrong with the Extendscript. I'll download a trial version of FM12 and see if I can reproduce the crash.

                                                     

                                                    Thanks again for your help!

                                                     

                                                    My best regards,

                                                    Roman