Skip to main content
Known Participant
September 11, 2009
Question

Table problem using FDK

  • September 11, 2009
  • 1 reply
  • 1342 views

Hi there

I'm having an issue with tables using the FrameMaker 8 API.I'm trying to process a document which has about 7 or 8 tables in it. Part of what I do is delete all the strings in a Frame Document and replace them with their equivalents in another language. The deletion is performed by querying the text items in a paragraph, iterating through each of them, finding the FTI_String objects, seleting them, and clearing them. However, I'm finding that the API is also deleting some of the tables in the document.

The code I use to do string deletion is :

F_TextItemsT textItems = F_ApiGetText(m_hDocument, hParagraph, -1);

int nItem = (int)textItems.len;

while (textItems.len > 0 && nItem >= 0)
{
    F_TextItemT thisTextItem = textItems.val[nItem];

    if (thisTextItem.dataType == FTI_String)
    {
       StringT string = thisTextItem.u.sdata;          //get text item string
       CString szText = ConvertFromStringT(string);    //convert to CString (for debugger)
           
       F_TextRangeT range;
       range.beg.objId = hParagraph;
       range.end.objId = hParagraph;
      


              range.beg.offset = thisTextItem.offset;        //get start,end offsets of current text item

       int nTextLength = szText.GetLength();

       range.end.offset = thisTextItem.offset + nTextLength;
                   
       F_ApiSetTextRange(FV_SessionId,

                                                  m_hDocument,

                                                  FP_TextSelection,

                                                  &range);         // I only want to select strings, but some tables are selected too
      

          F_ApiClear(m_hDocument, 0);
    }

}

However, with some (but not all) of the tables, F_ApiSetTextRange is selecting entire tables as well, for reasons I can't understand. and deleting them.

I was wondering if it's a problem in my approach, or if it's a possible problem with the document. I did notice that it was originally authored in FrameMaker 7, but it's being parsed with the FDK8 but I'm assuming that shouldn't make a difference.

Thanks

Eric

    This topic has been closed for replies.

    1 reply

    Legend
    September 14, 2009

    Hi Eric,

    I haven't had do deal with this problem myself, but I have a few ideas.

    I can't see any problem in your code that would directly cause this... a table anchor resides somewhere in the previous paragraph, wherever the insertion point was when it was inserted. From a F_TextRange perspective, it occupies a single "space," ie, a single character space. To select it, you would use an offset range of 1, as if selecting a single character.

    In your code, when you set the offset for text selection, it seems like it should work. Somehow, though, your code must be adding an additional value to the end offset, causing an anchor to be selected. Or, something like that. Here are two ideas:

    - Instead of using the GetLength() method to calculate the end offset, consider using the offset directly from the next text item. For example:

    range.end.offset = textItems.val[nItem + 1].offset;

    ...of course you would need provisions in case you are actually at the last item, otherwise big crashes cometh.    I don't think that would happen in this case, though, because you should always at least have a paragraph mark at the end of the array to handle a string before it.

    - Rearchitect your documents so that all tables have a single, empty paragraph reserved for the respective anchor. This is how I set up all my documents, because tables behave so much better this way, for reasons other than API manipulation. I use a simple 2pt format and insert a single table into each one, wherever I need a table. By getting the anchors out of text-containing paragraphs, you could avoid this problem altogether.

    I hope this helps some. I wish I could tell you exactly why your code is not working right, but I can't really see it. Also, BTW, the use of the while loop seems a little strange... consider a for loop based on textItems.len instead.

    Good luck,

    Russ

    eric247Author
    Known Participant
    September 14, 2009

    Hi Russ

    Thanks very much for taking the time to reply

    I tried your first suggestion of calculating the current text item's end offset based on the next text item's start offset.

    It didn't solve my problem but it did point me to the unusual set of circumstances which I believe is causing my problem.

    I noticed that all of the tables being wiped were preceded by a paragraph containing a certain word which seems to use unusual characters or glyphs.

    The word looks like this:

    What seems to be happening is that the FAPI breaks this word into two separate text items which are:

    "411" and the strange character immediately preceding it

    &

    "cobas<weirdchar>e"

    So it should require two iterations to properly delete this word, using the loop I showed you before. However, when we perform the first iteration and try to select the first text item,  "411" and the strange character immediately preceding it (we're parsing in reverse remember ) F_ApiSetTextRange () actually selects the entire word, therefore causing  F_ApiClear () to clear the entire word.

    When we go to delete the next text item which should be "cobas<weirdchar>e", we try to select it, but it's already been deleted during the previous iteration so the FAPI actually selects the table after where the word we just deleted was, and wipes it.

    I'm wondering what this character is, if the FAPI is capable of handling them, or if there is a workaround in dealing with them

    Thanks

    Eric

    eric247Author
    Known Participant
    September 15, 2009

    Ah yes, that makes sense. I should have thought of that, since you are making multiple changes in the same span of text. Indeed, that textItems list is just a statically-populated data structure... it has no dynamic link with the original document after it is allocated.

    One more thing... you probably know what you are doing here, but I'd like to add a cautionary note about copying pointers, such as in:

    StringT string = thisTextItem.u.sdata;

    If you aren't careful with these, it is super-easy to get crashes and/or memory leaks. In my personal work, I would either just use the array member itself, or copy the item and deallocate it when done. Such as:

    strBuf = F_StrCopyString(thisTextItem.u.sdata);

    . . .

    F_ApiDeallocateString(&strBuf);

    Having said that, I'm not a developer by trade, so it's certainly probable that your methodology is fine for someone who knows what they are doing.

    Russ


    Hi Russ

    Thanks for that.

    In terms of knowing what I'm doing, I'm constantly learning new things

    about what I can and can't do with the API. We use the FAPI as part

    of our computer assisted translation product, Alchemy Publisher.

    Have a quick google if you want to find out more about how it works.

    I started working on the Frame API once most of the work was done.

    We were having lots of niggling issues which, although individually are minor,

    collectively cause serious deterioration of document output fidelity.

    I wasn't aware that pointer copying like that were so risky!  Your approach

    of string copying seems like the safest for sure, so I'll make sure to replace

    pointer assignment with you line of code.

    Thanks very much for all your help, I doubt I would have solved my issue without.

    Eric