Copy link to clipboard
Copied
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!
Try using textLoc instead of TextLoc for your variable. TextLoc with this spelling is a reserved word.
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
Try using textLoc instead of TextLoc for your variable. TextLoc with this spelling is a reserved word.
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
@Russ, thank you for your suggestion!
@Rick, thank you for the sample script!
I appreciate your help, guys!
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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.
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
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!
Copy link to clipboard
Copied
This
var props = doc.GetTextPropVal(trange.beg.Object, Constants.FP_InCond)
should be this
var props = doc.GetTextPropVal(trange.beg, Constants.FP_InCond);
-Rick
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
Hi Roman, I am not sure what is going on. I tried it in 10 and 12 and didn't get the crash. -Rick
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
Roman, can you post your code so I can take a look? Thanks. -Rick
Copy link to clipboard
Copied
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
Copy link to clipboard
Copied
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);
Copy link to clipboard
Copied
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