Skip to main content
Inspiring
April 16, 2012
Question

How to prevent crashes - ITextModelCmds

  • April 16, 2012
  • 1 reply
  • 1448 views

Hi

In our plugin we substitute text defined by xml marker positions. The following code is working fine for the majority of our test cases, but for a specific combination of substitutions it fails with an access violation when calling RecomposeThruLastFrame.

I really hope somebody can give me a hint on modifying the following code to prevent crashes?

Thanks

Kind regards Toke

Code snippet (This is called lots of times within a loop):

ErrorCode status = kFailure; 

                    do {

                               InterfacePtr<IIDXMLElement> data = myTextStory->QueryXMLData(ref);

                              if(!data) break;

                              TextIndex delStart, delEnd;

                              Utils<IXMLUtils>()->GetElementMarkerPositions (data, &delStart, &delEnd);

                              InterfacePtr<ITextModel> textModel(myTextStory, UseDefaultIID());

                              if(!textModel) break;

  if (delStart < 0 || delStart >= textModel->TotalLength()) break;

 

                              if (delEnd-delStart < 1 || delEnd >= textModel->TotalLength()) break;

                              InterfacePtr<ITextModelCmds> textModelCmds(textModel, UseDefaultIID());

                              if(!textModelCmds) break;

  // Check for global errors

                              status = ErrorUtils::PMGetGlobalErrorCode();

                              if(status != kSuccess) break;

                              InterfacePtr<ICommand> delCmd(textModelCmds->DeleteCmd(delStart,delEnd-delStart));

                              status = CmdUtils::ProcessCommand(delCmd);

                              if(status != kSuccess) break;

  // Check for global errors

                              status = ErrorUtils::PMGetGlobalErrorCode();

                              if(status != kSuccess) break;

 

                              boost::shared_ptr<WideString> wide(new WideString(substitution));

                              InterfacePtr<ICommand> insertCmd(textModelCmds->InsertCmd(delStart, wide));

                              status = CmdUtils::ProcessCommand(insertCmd);

                              if(status != kSuccess ) break;

 

                              InterfacePtr<IFrameList> frameList(textModel->QueryFrameList());

                              if (!frameList) break;

 

                              InterfacePtr<IFrameListComposer> frameListComposer(frameList, UseDefaultIID());

                              if(!frameListComposer) break;

 

  // Check for global errors

                              status = ErrorUtils::PMGetGlobalErrorCode();

                              if(status != kSuccess) break;

                              frameListComposer->RecomposeThruLastFrame(); //See Table 94 in the programming guide


} while(kFalse);

This topic has been closed for replies.

1 reply

Legend
April 21, 2012

Just a wild guess: there could be interfering TextPreProcess or TextPostProcess services (in short "PP").

When you delete a range that holds a protected character e.g. the start tag without the matching end tag, the responsible PP will reduce the range in question to exclude the protected character and process or schedule a delete for the remainder. The whole mechanism is very instable as soon as multiple PP's are involved, because the execution order of the PPs is not really predictable while you can be sure that text offsets shift around like hell.

Even though I would not use them in production code, for your diagnostics you could add an ICommandInterceptor and trace what's going on under the hood.

Some ideas: try to wait until the dust has settled down - e.g. process all scheduled commands, or schedule your insertion, or - even better - use a TypeTextCmd that does both delete and insert in one step ...

Dirk

TJH84Author
Inspiring
April 24, 2012

Hi Dirk

Thanks for your reply.

I've tried to use a TypeTextCmd instead, but this results in the same access violation.

A disassemble shows that it occurs at 0x61DDB7D8 in the Paragraph Composer.rpln, and caused by a pointer stored at memory address ecx+0C4h being null.

...

61DDB7D2  mov         eax,dword ptr [ecx+0C4h]

61DDB7D8  fld         dword ptr [eax+edx*4-8]

...

Any other hints on how I can proceed?

Thanks

Kind regards Toke

Legend
April 24, 2012

Hello,

How about doing this from the end, backwards.

P.