Sunday, October 30, 2011

Deleting a Text Range

Deleting text means working with a text range. The range specifies the starting and ending paragraph or text line and the offset from each.

While a user must select text in order to delete it, a script does not need to do so. 

NOTE: A text range cannot span text lines but can span paragraphs. Any selection within a flow must be contiguous but can begin in one paragraph and end in another.

The following example shows how to delete the third through the fifth characters in the first paragraph of the main flow. Selecting the third character means starting the range at an offset of 2, just before that character.

var doc = app.ActiveDoc;
var mainflow = doc.MainFlowInDoc;
var tframe = mainflow.FirstTextFrameInFlow;
var pgf = tframe.FirstPgf;

var tRange= new TextRange();
tRange.beg.obj = pgf;
tRange.beg.offset = 2;
tRange.end.obj = pgf;
tRange.end.offset = 5;
doc.DeleteText(tRange);

Here are the before and afters of  a simple test:
Before running the script









After running the script

Saturday, October 29, 2011

Adding Text at a Location in Text

Just as user typing appears at the insertion point, a script adds text at a text location.

A text location consists of an object identifier (either an paragraph or a text line) and an offset from the start of that object.

The following example inserts text at the beginning of the first paragraph in the active document.

var doc = app.ActiveDoc;

var mainflow = doc.MainFlowInDoc;
var tframe = mainflow.FirstTextFrameInFlow;
var pgf = tframe.FirstPgf;

var tLoc= new TextLoc(); //create the text location object
tLoc.obj = pgf; //make it a paragraph
tLoc.offset = 0; // insert at the start of the paragraph
doc.AddText (tLoc, "Izzy ");

If you start out with the following document











and run the script, you get









If you change the text location to 3 (tLoc.offset = 3; ), you get the following:




Calculating Offsets

To work with text you need to understand how FrameMaker uses offset. While your scripts can work with text in flows or even documents, offset is always from either the start of a paragraph of text line.

Counting offset
Use the following rules in calculating the offset of a location in text:
• The start of a paragraph or text line has offset 0.
• Each character adds offset of 1.
• Anchors of any type have an offset of 1.
• Element boundaries have offset of 1.

The following have no offset:
• Paragraph begins.
• Line begins and ends.

But, paragraph ends have offset and must be selected to
change paragraph defaults. The end of flow marker cannot be selected either by an end user or by a script. It has no offset.

Working with Text

Sooner or later, you are likely to write a script that works with text. Some things you might want to do are:
  • Determine the content of a range of text.
  • Add text to a document.
  • Remove text from a document.
  • Alter the formatting of text.
  • Work with objects that are anchored in text such as tables, markers, or graphic.
Where is text found?
Lots of places including:
  • table cells
  • structure elements
  • flows
  • footnotes
  • paragraphs
  • text frames
  • text lines
  • sub columns
  • text insets of various types
  • variables
  • cross references
What is found in text?
Text contains the alphabetic, numeric, and special characters that make up document content. But text can also contain anchored objects. Those are the tables, anchored frames, markers, cross references that can be inserted at locations between characters.

Text is different
Text, unlike documents, paragraphs, graphics and just about everything else that makes up a FrameMaker document is not an object. There is no FO_Text object. Instead, text within paragraphs, text lines and other objects that contain text are processed as text items. (The details will be the subject of a later post.)

Text is formatted
Text all appears in a given font, at a particular size and style. It contains line breaks and page breaks and other information that reflects how it looks on the page. When you work with text, you will need to be able to determine how it is formatted and, if desired, change that formatting. Text items also give you the information needed to tackle those tasks.

Locations and Ranges
To work with text, you need to understand the concepts of text location and text range. You can think of a text location as analogous to an insertion point and a text range as analogous to a text selection. (But a text range can be selected or not selected!)

    Friday, October 28, 2011

    Error codes: when are they actually set?

    The function PrintFAErrno() displays the current value of FA_errno not as a number but as a constant. This is convenient in understanding what went wrong in your code.

    I did a little experimenting and found some surprising results. If I give the following correct code, I get an error code of FE_Success as expected.

    var doc = app.ActiveDoc.FirstPgfInDoc;
    PrintFAErrno();


    If I change my code as shown below, I expect a non-zero error code as documents do not have the property NextPgfInDoc. (That is a paragraph property.) My tests show, however, that FA_errno remains FE_Success.

    var doc = app.ActiveDoc.NextPgfInDoc;
    PrintFAErrno();

    So what is going on? I am not quite sure. While I distinctly recall seeing actual error codes as I developed other examples, I find that right now I am unable to get anything other than FE_Success. My error? ESTK problem? I fear I have made some subtle mistake. I will be keeping this issue in mind as I go forward and will report on my findings.


    Thursday, October 27, 2011

    Debugging with Error Codes

    The FDK and the ESTK use the global variable FA_errno to indicate whether or not a plug-in or script has executed correctly in the sense that all function calls were well-formed and  executed correctly in a formal sense. 

    Initially FA_errno has the value 0 (Constants.FE_Success). FE_Success has the value 0. All other possible values of FA_errno are negative integers.

    The value of  FA_errno remains FE_Success so long as no error occurs. 

    You can view the current value of FA_errno in the ESTK Data Browser. Just be sure to connect to FrameMaker first.




    If an error takes place, FA_errno is reset to a non-zero value. That value remains until another error causes it to be reset or until you reset it yourself.

    The ESTK lists 111 error code constants on pages 59-65 of the FrameMaker 10 Scripting Guide.  Individual functions that set error codes have detailed information within the function documentation.
      What sort of things cause an error code to be set? For example, you might
      • Attempt to set a value for  a read-only property. (Constants.FE_ReadOnly)
      • Attempt to get the value of a property that the object in question does not possess. (Constants.FE_BadPropType)
      • Pass an invalid object identifier to a function. (Constants.FE_BadObjId)
      • Pass the wrong object type of a function (Constants.FE_NotFrame, is one possibility)
      • Request an operation that cannot be carried out.(Constants.FE_BadOperation)

      Tuesday, October 25, 2011

      Ungrouping graphics

      Ungrouping a graphic is just a matter of setting its GroupParent property to zero.

      graphic.GroupParent = 0;

      The graphic being ungrouped may itself be group.  Ungrouping its members is easy, however, as when looping through all of the graphics in a frame, you find both ordinary graphics and groups.

      This code ungroups any grouped graphics within an anchored frame by setting all GroupParent properties to zero.

      group = doc.NewGraphicObject(Constants.FO_Group, aFrame); 
      graphic = aFrame.FirstGraphicInFrame;
      while (graphic.ObjectValid()) {
              graphic.GroupParent = 0;
              graphic = graphic.NextGraphicInFrame
              }